Spring Integration 1.0.3 示例:只需新增 OSGi

工程 | Oleg Zhurakousky | 2009 年 7 月 28 日 | ...

引言

上週,Mark Fisher 向您介紹了隨 Spring Integration 1.0.3 新版本釋出的、經過重新組織和簡化的 Spring Integration 示例,到目前為止,收到的反饋非常積極。除了重組和簡化現有示例之外,我們還引入了一些新的示例,目的是展示在基於 OSGi 的平臺上執行 Spring Integration 的一些好處。在這篇部落格中,我們將使用一個非常簡單但功能強大的例子,來探討 Spring Integration 和 OSGi 結合使用時,如何應對當今企業的動態性。

Spring Integration 是一個基於 POJO 的輕量級、可嵌入的訊息傳遞框架,它採用一種松耦合的程式設計模型,旨在簡化基於 企業整合模式 的異構系統整合,而無需單獨的 ESB 引擎或專有的開發和部署環境。另一方面,OSGi 是一種正規化,它允許從稱為 OSGi Bundles 的獨立模組構建松耦合的系統。從一組獨立開發的模組構建系統可能不是什麼新正規化,我們(希望如此)已經這樣做了很多年。話雖如此,OSGi 模組化的真正好處並非來自於其靜態打包模型,而是來自於對其部署和執行時動態性的理解,以及它如何很好地適應當今業務流程的動態性。

那麼,讓我們透過一個簡單的例子看看基於訊息交換的整合和OSGi 的動態性如何互補,從而實現一個非常強大且動態的系統。

Spring Integration 示例與 Spring Integration 的發行版一起提供。您也可以從這裡單獨下載。為了簡化,這些示例被開發為 SpringSource Tool Suite (STS) 專案,同時利用 dm Server 工具快速整合 SpringSource dm Server - 一個基於 OSGi 和 Spring 的企業 Java 平臺。然而,作為符合 OSGi 規範的專案,這些示例可以在任何配置正確的 OSGi 平臺上充分執行。

環境

首先,確保我們擁有一個配置正確的開發/部署環境。

要配置 STS/dm Server 環境,請按照以下步驟操作

此處 下載並解壓 STS 從 此處 下載並解壓 SpringSource dm Server

Spring Source Tool Suite v2.1.x 將自帶預配置的 SpringSource dm Server,但瞭解如何手動配置它仍然有所幫助。
開啟 STS 並配置 dm Server:開啟Server View -> 在 Server 檢視的空白處右鍵單擊 -> New -> Server

picture-14

選擇 SpringSource -> SpringSource dm Server v1.0 -> Next

指向您安裝伺服器的根目錄

picture-22

點選Finish

picture-3

您現在已經在 STS 環境中配置了 SpringSource dm Server。啟動 dm Server 並確保它成功啟動且沒有錯誤。

假設您已經下載了 Spring Integration 示例,現在讓我們使用 STS/Eclipse 提供的“Import Existing Projects into the workspace”嚮導將這兩個示例專案匯入工作區。File -> Import -> General -> Existing Projects into Workspace -> Next 瀏覽到 samples 目錄的位置並選擇 osgi-inboundosgi-outbound 專案

picture-51

點選Finish。您應該會看到兩個專案有錯誤。

picture-4

這些錯誤是預料之中的,因為我們的專案不知道 dm Server Target Runtime,而我們的 dm Server Target Runtime 不知道 Spring Integration 包。讓我們一個一個地解決問題。首先讓 dm Server 知道 Spring Integration,方法是將 Spring Integration 及其依賴的包部署到 dm Server 的儲存庫中。這是一個非常簡單的過程。將 org.springframework.integration-1.0.3.RELEASE.jarorg.springframework.integration.file-1.0.3.RELEASE.jar(我們的示例依賴的兩個包)複製到 dm Server 的 repository/bundles/usr 目錄中。然後在 STS 的 Server 檢視中雙擊 dm Server 例項 -> 點選 Repository 選項卡,在右上角您會找到一個 Refresh 按鈕。點選它,您應該會看到這兩個包在 dm Server 的儲存庫中可用。

picture-6

現在我們需要讓我們的 bundle 專案知道新的 Target Runtime。右鍵單擊每個專案 -> Properties -> Target Runtimes -> SpringSource dm Server (Runtime) v1.0

picture-7

現在所有錯誤都應該消失了。您已準備好測試這些示例

示例

這兩個示例基於非常簡單和熟悉的生產者/消費者概念。第一個 bundle osgi-inbound 是一個生產者,它允許您生產一個訊息,該訊息將被髮送到一個訊息通道。第二個 bundle osgi-outbound 是一個消費者,它將消費 osgi-inbound bundle 放置在通道上的訊息,並將訊息寫入檔案。

透過右鍵單擊伺服器例項 -> Start 來啟動 dm Server

透過簡單地將 osgi-inbound 專案拖放到 dm Server 例項上來部署 osgi-inbound。幾秒鐘後,您應該會看到啟動成功的訊息

[2009-07-27 21:56:49.040] onnection(5)-172.16.12.1 <SPDE0010I> Deployment of 'org.springframework.integration.samples.osgi.inbound'
version '1.0.3' completed.

然後對 osgi-outbound bundle 執行相同的操作

[2009-07-27 21:58:45.220] onnection(8)-172.16.12.1 <SPDE0010I> Deployment of 'org.springframework.integration.samples.osgi.outbound'
version '1.0.3' completed.

現在您已準備好測試這些 bundle 提供的功能。為了使其更有趣,我們透過 OSGi 控制檯啟用了命令列介面 (CLI),您可以透過提供命令訊息以及要將訊息寫入的檔名來與 osgi-inbound bundle 互動。您可以透過以下方式連線到 OSGi 控制檯

telnet localhost 2401

或者您可以使用 Server 檢視的 Server Console 選項卡並輸入

siSend "Hello World" hello.txt

然後點選Execute

您將看到以下內容

picture-9

去驗證您的訊息是否已寫入檔案。

這個非常簡單且微不足道的概念展示了基於 Spring Integration 提供的訊息模型,兩個系統之間的松耦合整合。然而,在現實世界中,我們在嘗試整合兩個系統時必須面對的問題之一是這些系統的獨立生命週期,其中行為的變化新系統的新增和/或舊系統的生命週期結束是正常的發生。通常,此類變化不僅需要程式碼更改,還需要在完全重啟伺服器後重新部署整個單體(例如,EAR、WAR)應用程式。Spring Integration 的 POJO 程式設計模型非常適合處理這些系統的松耦合特性,其中一個系統的更改很少影響另一個系統。但是它的生命週期動態性如何呢?讓我們假設(在我們這個小示例的範圍內)關於檔案應該寫入何處或如何寫入的要求已經改變了。無論是“何處”還是“如何”,都是 osgi-outbound bundle 的責任。在正常情況下,對 osgi-outbound bundle 功能的任何更改都需要完全刷新系統(即,重新部署整個系統並重啟伺服器)。當您的系統僅由兩個 bundle 組成時,這可能不是一個大問題。但如果 bundle 數量超過兩個呢?僅僅因為訊息應該寫入的目錄發生了變化,或者引入了一個新子系統應該記錄每條傳入訊息,您是否準備好重建和重新部署打包為 WAR 或 EAR 的整個系統?

這就是 OSGi 及其服務層以及最重要的是 OSGi 服務動態性提供巨大幫助的地方。所以讓我們接受上述示例需求,看看如何基於擴充套件當前示例來實現它們。首先,讓我們回顧一下 osgi-inbound bundle 的應用程式上下文配置

<osgi:service id="inboundService" ref="inboundChannel"
interface="org.springframework.integration.channel.SubscribableChannel"/>

<integration:publish-subscribe-channel id="inboundChannel"/>

<integration:gateway id="inboundGateway"
service-interface="org.springframework.integration.samples.osgi.inbound.InboundGateway"
default-request-channel="inboundChannel"/>

正如您所見,一個非常簡單的配置,它定義了一個閘道器代理,允許以 POJO 的方式傳送訊息,該訊息將存入配置為釋出/訂閱通道的入站通道。然而,更有趣的是,該通道已透過 `` 元素作為服務匯出到 OSGi 服務登錄檔,從而允許當前和未來 bundle 之間實現更加松耦合但動態的協作模型。

我們再看看 osgi-outbound bundle 的應用程式上下文配置。

<osgi:reference id="filesIn"
interface="org.springframework.integration.channel.SubscribableChannel"/>

<file:outbound-gateway id="filesOut"
request-channel="filesIn"
directory="${java.io.tmpdir}/spring-integration-samples/output"
delete-source-files="true"/>

此 bundle 的目標是在 osgi-inbound bundle 啟動後立即動態訂閱其釋出的通道,並將訊息寫入由 `` 元素配置的目錄中的檔案,從而體現 OSGi 服務層提供的動態性。您可以在此配置中看到,由 osgi-inbound bundle 匯出的 'inboundChannel' OSGi 服務現在透過 `` 元素匯入。現在,由 OSGi 服務前端的入站通道已準備好在執行時動態接受和/或失去訂閱者。由於 OSGi 服務的動態性,我們還可以更新配置或完全重新設計/重新實現 osgi-outbound bundle,而不會影響系統的生產者部分 (osgi-inbound)。所以讓我們繼續更改檔案將寫入的目錄(確保 dm Server 仍在執行...實際上,在這篇部落格期間完全忘記停止它)。

開啟 osgi-outbound 專案 -> src -> META-INF -> spring -> osgi-outbound.xml,並在 'directory' 配置中新增一個子目錄(在本例中是 'foo')picture-8 儲存檔案。幾秒鐘後,您將看到您的 osgi-outbound bundle 已重新部署。開啟 OSGi 或 Server 控制檯,像之前一樣傳送另一條訊息,看看新檔案是否已寫入您剛剛指定的目錄。希望它成功了 ;)

結論

請記住,雖然在這個簡單的示例中我們只處理兩個 bundle,但這些型別的生產者/消費者 bundle 本身可能是您系統其他部分的閘道器,而這些部分本質上是動態的。例如,假設您想收到有關檔案寫入的電子郵件通知。使用 SI 和 OSGi,您只需建立一個新的 bundle 來代表您子系統的該部分,作為 osgi-inbound bundle 釋出的通道服務的消費者,當您不再需要它時 - 透過停止或解除安裝此消費者來取消訂閱,而不會影響您系統的其餘部分。事實上,您可以繼續嘗試開發另一個 bundle 作為 osgi-inbound消費者,或者發揮您的想象力,開發另一個 bundle 來處理 osgi-outbound bundle 寫入的檔案。

有關更多想法和更復雜的示例,您可能還會喜歡閱讀 Spring Integration 團隊成員 Iwein Fuld 的這篇文章

最重要的是 - 整合愉快!!!

獲取 Spring 時事通訊

透過 Spring 時事通訊保持聯絡

訂閱

先行一步

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

瞭解更多

獲得支援

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

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視全部