面向 WLI 用户的 SOA 套件概要 比较:Oracle WebLogic Integration 自定义控件与 SOA 套件 Spring 组件作者:Clemens Utschig-Utschig 和 Simone Geib 面向 WLI 用户的 SOA 套件概要系列的这一部分将介绍与 WebLogic Integration 的自定义控件功能相对应的 SOA 套件的 Spring 组件的功能。2009 年 12 月发布
简介自定义 Java 代码是每个 Oracle WebLogic Integration (WLI) 业务流程 (JPD) 的一个重要部分。尽管 Oracle SOA 套件的大部分组件都是以 XML 为中心的,Oracle 还是增加了对 Spring 组件的支持,以便为开发人员提供充分的 Java 支持和强大的 IOC 容器。Spring 组件在 SOA 套件 11g PS1 中作为技术预览版提供,在 SOA 套件 11g PS2 中将正式提供。 本文介绍 SOA 套件的 Spring 组件如何提供与 WLI 的自定义控件相同的功能。本文使用一个记录器组件示例循序渐进地介绍如何实现和部署 Spring 组件。 本文是专为那些想开始学习 SOA 套件 11g 的 WLI 开发人员和架构师准备的。 WLI 中的自定义控件WLI 使用自定义控件封装 Java 代码(例如,对资源或应用程序功能的访问),然后通过将控件方法拖放到流程中在 WLI 流程 (JPD) 中使用该控件。 用户可以构建自己的自定义控件,这些自定义控件必须与系统控件基于相同的框架。用户从头设计自定义控件,包括设计控件的接口和实现,以及在需要时添加其他控件。 SOA 套件中的 Spring 组件Oracle SOA 套件使用自己的 Spring Java 组件用 Java 实现特定业务逻辑,完全不必考虑 XML。 Spring(参见 SpringSource)是一个 IOC 容器(控制反转;参见 Martin Fowler 编写的控制反转容器和依赖注入),允许通过配置进行依赖注入。因此提供一个没有任何依赖性的 JavaBean 时,Spring 的开销很小,需要的外部组件越多,Spring 的使用就越容易。 尽管 Oracle SOA 套件的主要组件基于 XML 作为数据交换格式,但 Spring 组件的目标是允许无缝的 Java 集成,因此也允许重用 Java 组件和技能。组件一旦实现,接下来就可将其公开为服务,从而可以从其他组件(如 BPEL)调用它。 通过下面的几个步骤,可以轻松实现在一个组合中使用 Java 类。 a) 创建 Java 接口,然后公开应该公开可用的方法。 public interface IInternalPartnerSupplier { /** * Get a price for a list of orderItems * @param pOrderItems the list of orderitems * @return the price */ public double getPriceForOrderItemList(List<Orderitem> pOrderItems) throws InternalSupplierException; } b) 创建该接口的实现。 public class InternalSupplierMediator implements IInternalPartnerSupplier { /** * Get the price for a list of orderItems and write the quote via * injected reference * @param pOrderItems the list of orderItems * @return the price for the list of orderItems */ @Override public double getPriceForOrderItemList(List<Orderitem> pOrderItems) throws InternalSupplierException { // just return a default price - or do something else .. return 0.0; } } c) 创建一个 spring 组件,这也为您提供了 spring 上下文,然后创建一个 bean(描述步骤 b) 中创建的类)。为这个 bean 指定一个名称(以便引用)并声明类。 <!-- spring bean inside a context, declaring a name, the class it's implemented with and the scope (singleton or new instance on each BeanFactory.getBean()) --> <bean id="InternalPartnerSupplierMediator" class="com.otn.sample.fod.soa.internalsupplier.InternalSupplierMediator" scope="prototype"> </bean> d) 创建一个将 bean 公开为服务的 <sca:service>。为使组件可供其他组件引用,组件必须有一个声明的服务。 <!-- exposed bean 'InternalPartnerSupplierMediator'. Note the type, which represents the java interface --> <sca:service name="IInternalPartnerSupplier" target="InternalPartnerSupplierMediator" type="com.otn.sample.fod.soa.internalsupplier.IInternalPartnerSupplier"/> 一旦创建了 Spring 组件(包括服务),就可将它与任何其他组件连接,如下面图 1 所示。 图 1 用例示例:简单的记录组件WLI 自定义控件的一个最常见的例子是自定义记录器,它用在流程中的某些特定点。在本示例中,我们将记录流程的名称、实例 ID 以及日志消息。 在 WLI 中实现用例我们不准备详细讲解这个用例,因为我们假定读者了解如何在 WLI 中创建和使用自定义控件。我们重点介绍 SOA 套件的 Spring 组件。 WLI 的记录器控件包含两个 java 文件: 接口类 LoggerControl.java package sample.oracle.otn.soaessentials.javainteg.controls; /** * Simple logger interface * @author simone.geib@oracle.com * @author clemens.utschig@oracle.com */ import org.apache.beehive.controls.api.bean.ControlInterface; @ControlInterface public interface LoggerControl { /** * Implementation of the log method * @param pProcessName the name of the originating process * @param pInstanceId the instanceID * @param pMessage the message to be logged to std.out * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log */ public void log (String pProcessName, String pInstanceId, String pMessage); } 实现 LoggerControlImpl.java package sample.oracle.otn.soaessentials.javainteg.controls; import org.apache.beehive.controls.api.bean.ControlImplementation; import java.io.Serializable; /** * Implementation of a simple logger component * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent * @author simone.geib@oracle.com * @author clemens.utschig@oracle.com */ @ControlImplementation public class LoggerControlImpl implements LoggerControl, Serializable { private static final long serialVersionUID = 1L; /** * Implementation of the log method * @param pProcessName the name of the originating process * @param pInstanceId the instanceID * @param pMessage the message to be logged to std.out * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log */ public void log(String pProcessName, String pInstanceId, String pMessage) { StringBuffer logBuffer = new StringBuffer (); logBuffer.append("[").append(pProcessName).append("] [Instance: "). append(pInstanceId).append("] ").append(pMessage); System.out.println(logBuffer.toString()); } } 图 2 显示了 JPD Data Palette 中的记录器控件。 图 2 图 3 显示了记录控件在 JPD 中的使用 图 3 在 SOA 套件中实现用例注: 为了使用 SOA 套件 11g PS1 中的这个预览特性,您必须先启用预览模式。转到 $JDeveloper_HOME/integration/seed/soa/configuration,打开 soa-config.xml。搜索 ${SPRING_COMPONENT_NAME_L},删除它附近的 xml 注释 (<!-- -->)。保存该文件后,重新启动 JDeveloper。 在本节中,我们将创建一个可以从其他组件(如 BPEL 流程管理器或调解器)使用的简单记录组件,它可将日志消息(包括初始实例 ID)记录到标准输出中。 创建 Spring 组件首先,在 JDeveloper 中创建一个新应用程序,命名为“SOASuiteWLIEssentials”。 图 4 接着,创建一个名为“JavaIntegration”的新项目。 图 5 单击“Finish”。 创建一个新 Java 程序包“sample.oracle.otn.soaessentials.javainteg”(这需要多个步骤)。 图 6 在“sample.oracle.otn.soaessentials.javainteg”程序包中创建一个新 Java 接口“ILoggerComponent”。 图 7 图 8 向该接口添加一个新方法“log”,其中包含初始组件、实例 ID 和消息的参数。 package sample.oracle.otn.soaessentials.javainteg; /** * Simple logger interface * @author simone.geib@oracle.com * @author clemens.utschig@oracle.com */ public interface ILoggerComponent { /** * Log a message, including the originating component, its instance id and * a message. * @param pComponentName the name of the component that sends this log msg * @param pInstanceId the instanceId of the component instance * @param pMessage the message to be logged */ public void log (String pComponentName, String pInstanceId, String pMessage); } 图 9 从“ILoggerComponent”接口创建一个 Java 类(“LoggerComponentImpl”)。 图 10 命名新建的类,单击加号查找该类所基于的接口。 图 11 图 12 图 13 下面是该记录组件的实现: package sample.oracle.otn.soaessentials.javainteg.impl; import sample.oracle.otn.soaessentials.javainteg.ILoggerComponent; package sample.oracle.otn.soaessentials.javainteg.impl; import sample.oracle.otn.soaessentials.javainteg.ILoggerComponent; /** * Implementation of a simple logger component * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent * @author simone.geib@oracle.com * @author clemens.utschig@oracle.com */ public class LoggerComponentImpl implements ILoggerComponent { /** * Implementation of the log method * @param pComponentName the name of the orginating component * @param pInstanceId the instanceid * @param pMessage the message to be logged to std.out * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log */ @Override public void log(String pComponentName, String pInstanceId, String pMessage) { StringBuffer logBuffer = new StringBuffer (); logBuffer.append("[").append(pComponentName).append("] [Instance: "). append(pInstanceId).append("] ").append(pMessage); System.out.println(logBuffer.toString()); } } 在接下来的步骤中,我们将创建一个新 Spring 上下文(“logger-context.xml”),定义一个 Spring bean(“logger”),然后将该 bean 公开为一个 服务(“logService”)。 图 14 图 15 接下来,从 Component Palette 拖动 bean。 图 16 放到 spring 上下文画布 上。 图 17 将这个 bean 命名为“logger”,并声明指向该实现的类属性。 图 18 现在,可以将该 bean 公开为一个 SCA 服务。 为此,将 Component Palette 中的下拉列表更改为“Spring 2.5 SCA”,然后将“service”拖放到画布上。 图 19 将该服务命名为“logService”。它的目标将是“logger”bean。 图 20 最后,选择类型,它是 LoggerComponent 类(“sample.oracle.otn.soaessentials.javainteg.ILoggerComponent”)的接口。 图 21 图 22 完成的 spring 上下文如下所示: <?xml version="1.0" encoding="windows-1252" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca"> <!-- expose the logger bean as service --> <sca:service name="logService" target="logger" type="sample.oracle.otn.soaessentials.javainteg.ILoggerComponent"/> <!-- declaration of the logger bean --> <bean name="logger" class="sample.oracle.otn.soaessentials.javainteg.impl.LoggerComponentImpl"/> </beans> 创建一个新组合“JavaIntegration”。 图 23 使用“Composite with BPEL”选项,将该流程命名为“BPELProcessWithLogger”。其他均保留为默认设置。 图 24 图 25 下面的图 26 显示了新创的 BPEL 流程,包括一个 receive 活动和一个 callback 活动。 图 26 切换回组合视图,将“Spring 上下文”拖放到组合画布上。将其命名为“logger-context”并选择您之前创建的 spring 上下文。 图 27 图 28 编译这些 Java 类,以便创建可在 BPEL 流程内使用的有效 WSDL 定义。 图 29 将 spring 组件的服务拖至 BPEL 流程。这将在流程中创建一个 wsdl 和一个伙伴链接。 图 30 图 31 接着,将 invoke 活动从 Component Palette 拖至 BPEL 画布 上。这将用于在前面创建的记录服务上调用 log() 方法。 图 32 将 invoke 活动与该记录器服务的伙伴链接 连线。 图 33 创建 input 和 output 变量。稍后将使用这些变量分配组件名称、组件实例 id 和日志 消息的值。 图 34 在完成 invoke 活动后,该流程应该类似于下面的图 35。 图 35 为了填充创建的变量,将 assign 活动从 Palette 拖放到 BPEL 流程上。 图 36 在接着的三个步骤中,您将创建必需的复制 规则以填充输入变量。 双击 assign 活动,添加一个 copy 操作,以便将组件名称 分配给第一个参数。 图 37 添加另一个 copy 操作,以便将组件实例 id 分配给第二个参数。 图 38 添加第三个 copy 操作,以便将消息 分配给第三个参数。 图 39 确保 assign 活动包含全部三个复制规则。 图 40 构建了所有复制规则只有,该流程就应类似于下面的图 4,流程以 receive 开始,接着是日志消息值的 assign,后边接着日志服务的日志方法的 invoke,最后是 callback,流程是通过 invoke 实现的。 图 41 部署 SOA 组合下一步是使用 Oracle JDeveloper 部署组合。请确保您的 SOA 服务器正在运行。 请查看部署 SOA 组合应用程序的第 43 节,了解如何使用 Oracle JDeveloper 和脚本编写工具来部署 SOA 组合应用程序,以及如何创建可在开发、测试和生产环境之间来回移动 SOA 组合应用程序的配置计划。 请查看部署 SOA 组合应用程序的第 5 节,了解如何在 Oracle 企业管理器融合中间件控制台中部署、重新部署及取消部署 SOA 组合应用程序。 在 JDeveloper 内部部署组合时,日志应与下面的日志类似: [06:15:55 AM] ---- Deployment started. ---- [06:15:55 AM] Target platform is (Weblogic 10.3). [06:15:55 AM] Running dependency analysis... [06:15:55 AM] Building... [06:16:11 AM] Deploying profile... [06:16:11 AM] Updating revision id for the SOA Project 'JavaIntegration.jpr' to '1.0'.. [06:16:12 AM] Wrote Archive Module to C:\JDeveloper\mywork\SDOStuff\JavaIntegration\ deploy\sca_JavaIntegration_rev1.0.jar [06:16:12 AM] Deploying sca_JavaIntegration_rev1.0.jar to soa_server1 [sta00251.us.oracle.com:8001] [06:16:12 AM] Processing sar=/C:/JDeveloper/mywork/SDOStuff/JavaIntegration/deploy/ sca_JavaIntegration_rev1.0.jar [06:16:12 AM] Adding sar file - C:\JDeveloper\mywork\SDOStuff\JavaIntegration\deploy\ sca_JavaIntegration_rev1.0.jar [06:16:12 AM] Preparing to send HTTP request for deployment [06:16:12 AM] Creating HTTP connection to host:sta00251.us.oracle.com, port:8001 [06:16:13 AM] Sending internal deployment descriptor [06:16:13 AM] Sending archive - sca_JavaIntegration_rev1.0.jar [06:16:41 AM] Received HTTP response from the server, response code=200 [06:16:41 AM] Successfully deployed archive sca_JavaIntegration_rev1.0.jar to soa_server1 [sta00251.us.oracle.com:8001] [06:16:41 AM] Elapsed time for deployment: 46 seconds [06:16:41 AM] ---- Deployment finished. ---- 测试 BPEL 流程部署成功后,可以通过 Oracle 企业管理器融合中间件控制台(企业管理器)启动组合服务。 要登录到企业管理器,使用 Internet Explorer 7、Mozilla Firefox 2.0.0.2 或 Firefox 3.0.x 访问以下 URL: 输入 weblogic/password,单击 Login。 请查看 管理 Oracle SOA 套件入门,获得更多信息。 图 42 在 EM 信息板中找到 JavaIntegration 组合并单击。这将显示该组合的主页: 图 43 您可以在该页面中测试 组合服务。 图 44 填充“clemens”作为输入,然后单击“Test Web Service”。 图 45 创建了实例之后,可以单击 Launch Message Flow Trace,这将使您转到该组合实例: 图 46 您也可以检查 BPEL 实例流,这将向您显示传给该 spring 组件的实际消息: 图 47 检查 soa 套件所在服务器的标准输出。应显示与下面类似的条目: ==> CubeEngine deploy BPELProcessWithLogger took 4 seconds INFO: DeploymentEventPublisher.invoke Publishing deploy event for default/JavaIntegration!1.0*c39dc7a2-5031-424e-9ae0-aeec949769b3 [BPELProcessWithLogger] [Instance: 20009] Got input: clemens 下载完整的项目可以从以下地址下载包含完整项目(包括 java 源代码和组合)的 zip 文件: wli-soaessentials-JavaIntegration-source.zip。要在 JDeveloper 中打开该文件,创建一个新应用程序,然后打开项目文件 (JavaIntegration.jpr)。 要点和建议
为了创建可重用的实体和 bean,可以将 spring 上下文本身(无需组合)打包并部署到 WebLogic Server 中,将 bean 公开为 EJB/web 服务。 这样大大简化了可重用 Java 组件的创建,能够以 WLI JPD 使用自定义控件的方式在 BPEL 流程或调解器组件中使用这些组件。 深入阅读
|