可移植性、炸魚薯條

工程 | Rod Johnson | 2008年5月9日 | ...

很高興在 JavaOne 現場和網上聽到關於 SpringSource 應用平臺 的如此多的討論。其中最有見地的評論之一來自 WebSphere 事務架構師 Ian Robinson

這一切是否會影響 WebSphere?核心 Spring 框架沒有任何改變。無論 SpringSource 應用平臺未來如何,核心 Spring 框架專案仍然與 WebSphere 相輔相成。就像炸魚薯條一樣。
Ian 完全正確。SpringSource 應用平臺是 Spring 部署的另一個選擇。...沒有任何改變。

SpringSource 應用平臺清單頭

工程 | Glyn Normington | 2008年5月8日 | ...

SpringSource 應用平臺由 OSGi bundle 構建而成,並支援同樣由 OSGi bundle 構建的應用程式。該平臺支援 OSGi 的標準功能,但也支援一些額外的清單頭。有些人問過 為什麼 SpringSource 添加了專有頭? 以及 新頭的語義是什麼?,因此本文解釋了背景動機以及 Import-LibraryImport-Bundle 的語義。

標準 OSGi Bundle 支援

該平臺基於 OSGi R4.1 標準構建,如果您願意,也可以說是 JSR 291,並使用 Equinox 作為其 OSGi 實現。因此,您可以使用平臺的工具開發標準 OSGi bundle,並將這些 bundle 部署到平臺上,許多使用者自平臺釋出以來一直在這樣做。

因此,熟悉 OSGi 的開發者可以將平臺用作標準的 OSGi 容器,並受益於平臺的功能,例如

  • 能夠使用 Admin Console 或透過將 bundle 放入平臺的 pickup 目錄來部署 bundle,
  • 診斷功能,例如解析失敗診斷、應用程式特定跟蹤和自動死鎖檢測,
  • 與 Spring 和 Spring Dynamic Modules 的強大整合,適合希望使用這些框架的開發者,以及
  • 從倉庫自動提供依賴項。
然而,該平臺還旨在讓對 OSGi 幾乎或完全沒有接觸的企業應用開發者也能輕鬆受益於 OSGi,這對平臺提出了一些額外要求。

企業應用程式的額外要求

正如 Sam 最近關於平臺部署選項的部落格所解釋的,您可以在平臺上部署現有的單體 WAR 檔案,無需理解 OSGi - 平臺會為您處理一切。但要受益於共享庫、共享服務,以及最終的 PAR 檔案作用域,需要將單體 WAR 檔案分解為 OSGi bundle。這有多難?

嗯,過程中的一些步驟相對容易,特別是如果遵循了良好的軟體工程實踐並將程式碼組織成了服務、領域和基礎設施元件。這些元件可以轉換為 bundle,並且它們之間的依賴關係可以使用 META-INF/MANIFEST.MF 中的標準 OSGi Import-Package 和 Export-Package 頭來表達。

更困難的一步是表達對企業框架(如 Spring 和 Hibernate)的依賴。完全可以使用標準的 OSGi Import-Package 和 Require-Bundle 頭來表達這些依賴關係,如果您的目標是建立可以在其他 OSGi 容器中執行的 OSGi bundle,這正是您應該做的,但這種方法有一些隱性成本。

首先,開發者必須精確決定一個給定框架包含哪些包。僅僅匯入應用程式程式碼使用的包是不夠的,因為一些企業框架在應用程式載入時會將進一步的依賴項織入到應用程式的位元組碼中。開發者必須(很可能透過反覆試驗)發現需要匯入哪些額外的實現包,以確保織入的應用程式行為正確。

然後是框架版本遷移的麻煩,因為組成框架的精確包集合可能已經改變。織入所需的額外包通常不是由公共契約定義的,因此可能會發生變化。

此外,由此產生的包匯入未能正確捕獲設計意圖,這使得將來維護或擴充套件應用程式更加困難。

我們真的不想將這些負擔強加給使用者,因此我們建立了一些 SpringSource 應用平臺特定的額外清單頭,即 Import-LibraryImport-Bundle,作為表達對企業框架依賴關係的便捷方式。正如您將在下面看到的,這些頭實際上只是用標準 OSGi 包匯入來表達的 語法糖

Import-Library

基本語法與其他清單頭類似
    Import-Library: <librarySymbolicName>;version=<versionRange>
其中 <librarySymbolicName> 是庫的 符號名,而 <versionRange> 是使用 OSGi 版本範圍表示法表示的庫的可接受版本範圍。庫定義指定了庫的符號名和版本,這兩者共同唯一地標識了平臺中的庫。

如果您不熟悉 OSGi 版本範圍表示法,目前最常用的形式是最低版本範圍,例如 2,表示 版本 2 或更高,以及 半開 範圍,例如 [2.2.1,2.2.2),表示版本在 2.2.1(包含)到 2.2.2(不包含)之間。如果省略 version=<versionRange> 以及分號分隔符,則預設範圍包含所有版本。

對於每個庫匯入,平臺會選擇具有給定符號名和在給定版本範圍內平臺倉庫中可用的最高版本的庫。然後,平臺將庫匯入替換為一組與庫 bundle 匯出的所有包匹配的包匯入。平臺會檢測到當一個 bundle 匯入兩個或多個匯出相同包的庫的情況,發出適當的日誌訊息,並無法安裝該匯入 bundle。

例如,以下頭匯入了版本在 2.5.4(包含)到 2.5.5(不包含)之間的 Spring Framework 庫

    Import-Library: org.springframework.spring;version="[2.5.4,2.5.5)"

可選庫匯入

您可以使用以下語法指示庫匯入是可選的。請注意特殊分隔符 :=,它表示修改清單頭語義的 指令,與表示 匹配屬性(如 version)的分隔符 = 不同。
    Import-Library: <librarySymbolicName>;version=<versionRange>;resolution:=optional

如果未指定 resolution,或指定為 mandatory,則如果不存在具有給定符號名和給定範圍內版本的庫,則包含該匯入庫頭的 bundle 將無法安裝。但如果指定了 resolution:=optional,則在沒有合適的庫可用時,該庫匯入將被忽略。

因此,例如,以下頭匯入 Spring Framework 庫 2.5 或更高版本,但在沒有合適的庫可用時將被忽略

    Import-Library: org.springframework.spring;version="2.5";resolution:=optional

匯入多個庫

如果您需要匯入多個庫,則在單個 Import-Library 清單頭中指定一個逗號分隔的庫匯入列表,如下例所示
    Import-Library: org.foo.p;version="[1,2)",org.bar.q;version="[2,3)"

Import-Bundle

Import-Bundle 是另一種便捷方式,適用於庫只包含一個 bundle 且建立庫定義不方便的情況。其語法與 Import-Library 非常相似,只是它引用的是 bundle 的符號名和版本,而不是庫的。

正如您所預期的,對於每個匯入的 bundle,平臺會選擇具有給定符號名和在給定版本範圍內平臺倉庫中可用的最高版本的 bundle。然後,平臺將 bundle 匯入替換為一組與該 bundle 匯出的包匹配的包匯入。

因此,例如,以下頭匯入了 Hibernate 物件關係對映器 bundle

    Import-Bundle: com.springsource.org.hibernate;version="[3.2.6,3.2.7)"

為什麼不過載 Require-Bundle

如果您熟悉 OSGi,您可能會問自己為什麼我們沒有過載 Require-Bundle,而是引入了 Import-Bundle

嗯,我們希望 Require-Bundle 保留其標準語義,包括合併拆分包(split package)各個部分的能力。但我們希望 Import-LibraryImport-Bundle 具有與 Import-Package 相同的底層語義,以避免拆分包帶來的複雜性。

我們還預計,隨著平臺的不斷發展,我們需要在 Import-LibraryImport-Bundle 中新增更多指令,而這些指令不適合新增到 Require-Bundle 中。

下一步是什麼?

平臺 beta 專案 正在進行中,我們將聽取所有關於平臺功能的反饋,包括新的清單頭。

對於希望利用平臺頭部,但需要生成能在其他 OSGi 容器上執行的 bundle 的使用者,我們計劃開發一個工具來替換 Import-LibraryImport-Bundle...

SpringSource 應用平臺部署選項

工程 | Sam Brannen | 2008年5月6日 | ...

自上週三釋出 SpringSource 應用平臺以來,許多開發者下載了 1.0.0 beta 版本並開始試用平臺。因此,人們開始問:"如何將我的應用部署到平臺上,我有哪些部署和打包選項?" 此外,開發者急切地要求檢視可用的示例。作為回應,S2AP 團隊將在未來幾周內釋出一些示例應用程式,展示這些功能及更多內容,但在您獲得這些示例之前,我想先給您一個高層次的...

Spring Web Services 1.5.1 釋出

釋出 | Arjen Poutsma | 2008年5月4日 | ...

尊敬的 Spring 社群成員:

我很高興宣佈 Spring Web Services 1.5.1 已釋出!

下載 | 網站 | 更新日誌 | 公告

這是 Spring-WS 1.5 系列的第一個 bug 修復和增強版本。它修復了自 1.5.0 以來報告的所有 bug,並引入了框架中的各種增強功能

  • 引入了一個使用 OXM marshaller 的 Spring JMS MessageConverter
  • 引入了一個使用 OXM marshaller 的 Spring MVC View
  • 修復了與 SAAJ 訊息結合使用 WSS4J 時的 WS-Security 簽名問題
  • 支援 HTTP 傳輸中的超時
  • 支援 Castor 1.2,參見下面的說明
  • Airline 示例現在使用 Spring Security

以及更多。詳細資訊請參見更新日誌。

請注意,由於向後相容性問題,CastorMarshaller 現在需要 Castor 1.2 或更高版本。

祝好,

Arjen Poutsma
Spring Web Services Lead

使用 SpringSource 應用平臺在 OSGi 上執行 Spring 應用

工程 | Rob Harrop | 2008年5月2日 | ...

許多人一直在問,SpringSource 應用平臺到底為 Spring 應用做了什麼,使其在 OSGi 下執行良好,這超出了 OSGi 和 Spring Dynamic Modules 開箱即用的能力。Adrian 昨天的文章強調了一些一般性問題,現在我們來看一些細節。

在 OSGi 上執行 Spring 應用的三個最具挑戰性的方面是

  • 載入時織入
  • Classpath 掃描
  • 執行緒上下文類載入器管理

其餘但不太有趣的問題包括:JSP 支援、TLD 掃描、註解匹配和資源查詢。總的來說,需要解決一系列相當大的問題,才能使應用程式順利部署。

載入時織入

載入時織入是支援起來最麻煩的功能之一。在基本層面,它需要掛接到 Equinox ClassLoader 中,以便在 defineClass 呼叫期間可以附加和使用標準的 ClassFileTransformers。此外,許多 LTW 用法需要訪問一個可丟棄的 ClassLoader,用於檢查型別以決定在織入期間需要發生什麼,而不會影響真實的 ClassLoader

這種基礎級別的支援實際上相當容易實現。困難在於當織入由一個 bundle 中的類驅動,但另一個 bundle 中的類需要被織入時。這在企業應用中非常常見,其中一個 bundle 包含領域實體,另一個 bundle 包含使用 JPA EntityManager 的型別。平臺透過確保應用程式中的所有 bundle 都可以使用適當的 ClassFileTransformers 進行織入來處理這種複雜性。

當您開始將織入傳播到其他 bundle 時,您確實需要知道何時停止。如果您只是簡單地將織入應用於所有 bundle,那麼應用程式將相互干擾。平臺透過明確限定織入的作用域,使其僅應用於應用程式中的模組來防止這種情況發生。

LTW 的另一個問題是它使重新整理複雜化。當一個 bundle 被重新整理時,OSGi 將重新整理所有依賴於它的 bundle。這意味著,在我上面給出的示例中,重新整理領域 bundle 將導致 EntityManager bundle 被重新整理。然而,重新整理 EntityManager **不會**重新整理領域 bundle,這意味著織入可能不同步。平臺透過將重新整理傳播到受織入影響的其他 bundle 來處理此問題。

Classpath 掃描

對於 classpath 掃描,主要問題是 Equinox 不暴露標準的 jar:file: 資源。平臺在中間放置了一個介面卡,以便庫能夠看到它們所期望的資源協議。這產生了一個很好的副作用,使得**許多**第三方庫能夠工作 - 這不僅僅是針對 classpath 掃描的修復。

執行緒上下文類載入器管理

許多第三方庫使用執行緒上下文 ClassLoader 來訪問應用程式型別和資源。OSGi 中的每個 bundle 都有自己的 ClassLoader,因此,在任何時候只有一個 bundle 可以被暴露為執行緒上下文 ClassLoader。這意味著如果一個第三方庫需要檢視分佈在多個 bundle 中的型別,它將無法按預期工作。

平臺透過建立一個 ClassLoader 來解決這個問題,該 ClassLoader 匯入應用程式中每個模組匯出的所有包。然後,該 ClassLoader 被暴露為執行緒上下文 ClassLoader,從而使第三方庫能夠看到應用程式中所有匯出的型別。

這只是平臺解決的問題的一小部分,但希望它能讓您瞭解平臺對 Spring Framework 使用者意味著什麼。

Spring Security 2.0.1 釋出

釋出 | Ben Alex | 2008年5月2日 | ...

Spring Security 2.0.1 現已可用。

下載 | 更新日誌 | 公告 | 網站

Spring Security 2.0.1 提供了針對最近釋出的 2.0.0 版本的一些修復。它還在 OSGi 支援、擴充套件名稱空間配置和加密強度令牌生成方面提供了一些進一步改進。它與 2.0.0 版本完全向後相容,可以作為 JAR 替換檔案直接使用。

完善的畫面:Spring、OSGi 和 SpringSource 應用平臺

工程 | Adrian Colyer | 2008年5月1日 | ...

** 5月2日更新,包含案例研究:- 詳情請參見本文底部 ** 我相信大多數閱讀這篇部落格的人昨天都已經看到了 SpringSource 應用平臺的釋出公告。如果還沒有,請務必檢視 Rob 的部落格文章,其中描述了一些動機、程式設計模型和路線圖。

本文中,我想直接回答幾個常見問題。之後,我將描述另外兩個令人振奮的公告,它們是對 SpringSource 應用平臺本身的補充,但昨天並未成為頭條新聞:...

介紹 SpringSource 應用平臺

工程 | Rob Harrop | 2008年4月30日 | ...

經過數月的緊張編碼,我很高興宣佈 SpringSource 應用平臺 1.0 的 beta 版本釋出。

2007 年初,我們開始討論與企業 Java 代名詞的單體且重量級的應用伺服器的可能替代方案。客戶正在尋找一個輕量級、模組化且足夠靈活的平臺,以滿足他們的開發和部署需求。

Spring 和 Tomcat 的組合證明了開發者和運維人員可以在生產環境成功使用輕量級平臺。儘管這種組合取得了成功,但缺乏模組化以及對非 Web 應用的明確支援限制了其適用性和靈活性。

我們著手構建 SpringSource 應用平臺,以滿足這些要求並消除這些限制。

平臺的核心是動態模組核心(Dynamic Module Kernel,簡稱 DMK)。DMK 是一個基於 OSGi 的核心,它充分利用了 OSGi 平臺的模組化和版本化特性。DMK 構建在 Equinox 之上,並擴充套件了其供應(provisioning)和庫管理能力,同時為平臺提供了核心功能。

SpringSource Application Platform Architecture

為了保持最小的執行時 footprint,DMK 供應子系統會按需安裝 OSGi bundle。這使得應用程式可以安裝到正在執行的平臺中,並且其依賴項可以從外部倉庫獲取。這不僅消除了手動安裝所有應用程式依賴項的需要(這會很繁瑣),而且將記憶體使用量保持在最低。

DMK 本身只需要最少的一組 bundle 即可執行,並透過配置一個 profile 來精確控制載入哪些額外的模組。例如,DMK 不需要 Tomcat 存在,但預設的平臺 profile 包含了 Tomcat,以便部署 Web 應用程式。如果您想執行一個不帶 Tomcat 的平臺,只需編輯 profile 即可,它將不會被安裝。(如果您嘗試這樣做 - 請記住移除 Web 支援意味著 Web 模組將不再部署,因此刪除 pickup 目錄的內容,這樣平臺啟動時就不會嘗試安裝 Admin 和啟動螢幕應用程式。)安裝了 Admin Console 的預設平臺配置僅佔用 15MB 記憶體。

我在企業 Java 中一直感到沮喪的一點是,應用程式經常被生硬地塞進人為設計的孤島中,並且缺乏對不同應用型別的明確支援。考慮一個線上商店的應用。該應用有一個 Web 前端、一個訊息驅動的訂單處理模組、一個批處理驅動的庫存補貨模組和一個 B2B Web 服務模組。如今,許多這樣的應用程式會被打包成 WAR 或 EAR,模組看起來非常相似,對模組型別之間的差異支援很少。有趣的是,許多人會將此類應用稱為 Web 應用程式,而不是帶有 Web 模組的應用程式。

在 SpringSource 應用平臺中,應用程式是模組化的,每個模組都有一個描述其型別的 personality:web、批處理、web 服務等。平臺以 personality 特定的方式部署每種 personality 的模組。例如,web 模組在 Tomcat 中配置 web context。應用程式中的每個模組都可以獨立於其他模組進行更新,同時保留作為更大應用程式一部分的身份。無論您構建何種應用程式,程式設計模型都保持標準 Spring 和 Spring DM。

在 1.0 平臺版本中,我們支援 webbundle 型別的模組(personalities),這使您能夠構建複雜的 Web 應用程式。未來的版本將包括對更多 personality 的支援,詳情稍後介紹。

構建應用程式

平臺支援三種打包形式的應用程式

  1. Java EE WAR
  2. 原始 OSGi bundle
  3. 平臺檔案 (PAR)

平臺直接支援標準的 WAR 檔案。部署時,WAR 檔案會轉換為 OSGi bundle 並安裝到 Tomcat 中。所有標準的 WAR 契約都得到遵守,您現有的 WAR 檔案應該可以直接放入並部署,無需更改。

任何符合 OSGi 標準的 bundle 都可以直接部署到平臺中,並且可以充分利用針對 Import-PackageRequire-Bundle 引用的任何依賴項的即時供應(on-the-fly provisioning)功能。

PAR 格式是平臺打包和部署應用程式的推薦方法。PAR 只是 OSGi bundle(模組)的集合,它們被分組到一個標準 JAR 檔案中,並帶有一個唯一標識應用程式的名稱和版本。PAR 檔案作為一個整體單元部署到平臺中。平臺將從 PAR 中提取所有模組並安裝它們。第三方依賴項將在需要時即時安裝。

PAR 格式相比直接將 bundle 部署到平臺具有三個主要優點。首先,它更簡單。一箇中等大小的企業應用可能包含 12 個以上的 bundle - 手動部署這些會過於繁瑣。其次,PAR 檔案在應用程式中的所有 bundle 周圍形成一個明確的作用域,這防止了使用重疊型別或服務的應用程式相互衝突。這個作用域也用於一些高階功能,如載入時織入,以確保一個應用的織入不會干擾另一個應用的織入。最後,PAR 形成一個邏輯分組,定義哪些模組是一個應用的一部分以及該應用有哪些第三方依賴項。管理工具使用這個分組來提供應用程式的詳細檢視。典型的 PAR 應用程式看起來像這樣

PAR File Structure

應用程式中模組之間的依賴通常使用 Import-PackageExport-Package 來表達。對第三方庫的依賴也可以用相同的方式表達,但對於許多庫來說,這可能容易出錯且耗時。使用像 Hibernate 這樣的庫時,您通常需要匯入比最初預期更多的包。為了繞開這個問題,您可以使用 Require-Bundle,但這有一些語義上的問題,例如拆分包(split packages),其中一個邏輯包被拆分到兩個或更多類載入器中,導致執行時出現問題。平臺引入了兩種引用第三方依賴的新機制:Import-BundleImport-LibraryImport-Bundle 類似於 Require-Bundle,但它避免了拆分包和 Require-Bundle 的其他問題。Import-Library 提供了一種機制,可以在單個宣告中引用由一組 bundle 匯出的所有包,例如 Spring Framework 中的所有 bundle

Bundle-SymbolicName: com.myapp.dao.jdbc
Bundle-Version: 1.0.0
Import-Bundle: org.apache.commons.dbcp;version="1.2.2.osgi"
Import-Library: org.springframework.spring;version="2.5.4.A"

這裡我有一個模組 bundle,它依賴於 Commons DBCP bundle 和 Spring Framework 庫。Spring Framework 庫包含在您的應用程式中使用 Spring 所需的所有 bundle。

Import-LibraryImport-Bundle 在底層會擴充套件為 Import-Package,因此與標準 OSGi 語義一致。

平臺理解模組的 personality,並由此可以推斷如何配置模組的執行環境。部署 Web 模組時,典型 Spring MVC 應用程式所需的全部 servlet 基礎設施會自動建立,從而消除了在不同應用程式中重複建立這些樣板程式碼的需要。在 1.0 最終版本中,將向 Web 模組 personality 新增更多智慧功能,以支援額外的技術,例如 Spring Web Flow。

無論您選擇哪種打包格式,程式設計模型都只是 Spring Framework 和 Spring Dynamic Modules,其他 Spring Portfolio 產品在其之上執行。

可服務性

可服務性是整個工程團隊的一個關鍵考慮因素。我們花了大量時間擔心日誌訊息的格式和堆疊跟蹤的大小,以確保診斷應用程式問題儘可能容易。每當我們發現重複且耗時的任務時,我們都會尋找自動化或完全消除它的方法。

為了輔助問題診斷,平臺對日誌訊息和跟蹤訊息進行了嚴格區分。日誌訊息供終端使用者檢視,讓您可以輕鬆獲取最重要的故障資訊,而無需遍歷海量跟蹤內容。所有應用程式故障都在日誌輸出中顯示並編碼 - 這些程式碼是訪問知識庫或支援內容的便捷方式。要理解為什麼這如此有用,請看平臺啟動時的以下輸出

[2008-04-29 12:12:01.124] main                     <SPKB0001I> Platform starting.
[2008-04-29 12:12:04.037] main                     <SPKE0000I> Boot subsystems installed.
[2008-04-29 12:12:06.013] main                     <SPKE0001I> Base subsystems installed.
[2008-04-29 12:12:07.396] platform-dm-1            <SPPM0000I> Installing profile 'web'.
[2008-04-29 12:12:07.674] platform-dm…

Web 應用程式與 OSGi

工程 | Costin Leau | 2008年4月29日 | ...

自 Spring Dynamic Modules 的第一個里程碑以來,在 OSGi 中執行 Web 應用程式的需求開始出現。這可能是最常被請求的功能之一,不足為奇的是,一旦 1.0 最終版本釋出,Web 支援就成為了 1.1 分支的主要焦點。我很高興地報告,隨著剛剛釋出的 M2 版本,正如 Juergen 已經暗示的,Spring-DM 不僅支援普通的 WAR(自 1.1.0 M1 起可用),還支援在 OSGi 內部執行的 Spring-MVC 應用程式。在本篇文章中,我想簡要討論典型的 OSGi Web 場景和 Spring-DM 的方法。但首先,

為什麼要在 OSGi 中部署 WAR?

簡單的問題:OSGi 原生地提供了版本控制、包連線和熱過載。想象一下在您的應用程式中利用這些功能:您可以停止將庫嵌入到WEB-INF/lib並開始在您的 Web 應用之間共享它們,避免標籤庫重複(同時保持多個版本執行),並在執行時只更新應用程式的某些部分。這尤其有用,因為 Web 應用往往是分層的,因此在其生命週期中會發生大量變化。

為什麼 OSGi 中的 Web 應用會遇到問題?

Servlet 規範圍繞著 web 容器 的概念展開:一個為 Web 元件提供執行時環境的服務,提供標準服務,如生命週期管理(物件建立和銷燬、執行緒分配)、併發、HTTP 請求處理等等。另一方面,OSGi 平臺也作為一個受管環境執行,具有服務登錄檔、包連線和版本控制(僅舉幾例)。為了解決這個問題,OSGi 委員會設計了 Http Service,這是 compendium 規範的一部分。

...

訂閱 Spring 新聞通訊

隨時瞭解 Spring 新聞通訊

訂閱

提升自我

VMware 提供培訓和認證,助您快速提升。

瞭解更多

獲取支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一次簡單訂閱。

瞭解更多

近期活動

檢視 Spring 社群的所有近期活動。

檢視全部