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 Bundle模块来构建松耦合系统的范式。从一组独立开发的模块构建系统可能并不是一个新范式,我们已经这样做了(希望如此)多年。话虽如此,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提供的“将现有项目导入工作区”向导将两个示例项目导入工作区。文件(File) -> 导入(Import) -> 通用(General) -> 现有项目到工作区(Existing Projects into Workspace) -> 下一步(Next) 浏览到示例目录的位置并选择osgi-inboundosgi-outbound项目

picture-51

点击完成(Finish) 您应该会看到两个有错误的项目。

picture-4

这些错误是预料之中的,因为我们的项目不知道dm Server目标运行时,而我们的dm Server目标运行时也不知道Spring Integration bundle。让我们一次解决一个问题。首先,通过将Spring Integration及其依赖的bundle部署到dm Server的仓库中,让dm Server知道Spring Integration。这是一个非常简单的过程。将org.springframework.integration-1.0.3.RELEASE.jarorg.springframework.integration.file-1.0.3.RELEASE.jar (我们的示例依赖的两个bundle)复制到dm Server的repository/bundles/usr 目录中。然后在STS的Server视图中双击dm Server实例 -> 点击Repository选项卡,在右上角您会找到一个Refresh按钮。点击它,您应该会在dm Server的仓库中看到这两个bundle。

picture-6

现在我们需要让我们的bundle项目知道我们新的目标运行时。右键单击每个项目 -> 属性(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时,这可能不是一个大问题。但是如果超过两个呢?您是否准备好仅仅因为消息写入的目录发生了变化,或者引入了一个应该记录每条传入消息的新子系统,就重建和重新部署整个打包为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 或服务器控制台,像之前一样发送另一条消息,看看新文件是否已写入您刚指定的目录。希望如此 ;)

结论

请记住,尽管在这个简单的例子中我们只处理两个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 社区所有即将举行的活动。

查看所有