导读:本文主要讲解WebSphere Process Server V7.0的新功能。读者可以从本篇文章中学习到EJB export binding的基础知识和配置方法以及EJB import binding的高级用法,了解错误和异常的处理方式。
面向服务的体系架构(SOA)提出了把功能包装成服务的设计理念。服务组件架构(SCA)是一种实现SOA理念的方式。作为编程模型和框架,SCA定义了描述服务和调用服务的标准方法,是WebSphere Process Server(WPS)的核心概念。SCA模块定义和实现各种服务。而绑定使得SCA模块通过不同的协议与其他外部服务或系统交互。绑定分为导入绑定(import binding)和导出绑定(export binding)两种,前者帮助SCA模块调用外部服务,后者使SCA模块能被外部服务使用。
EJB导出绑定
EJB导出绑定是WPS V7.0的新功能。以SCA编程模型实现的组件,可通过EJB导出绑定发布成EJB无状态会话Bean(Stateless Session Bean),以便与外界J2EE环境集成。这样对于那些熟悉 EJB 的客户就能以调用普通 EJB 的方式调用SCA服务。EJB导出绑定支持WSDL接口和Java接口,支持EJB 3.0和EJB 2.1规范,EJB远程调用(Remote Interface)和本地调用 (Local Interface)。
WSDL接口
WPS的数据编程模型是Service Data Objects(SDO)。SDO方便WPS用XML schema描述XML 数据。然而基于Java接口的EJB要求传输数据支持 Java序列化。为了让两者能够对接,我们需要做Java对象到XM数据的转换。幸运的是,业界已经提出一个根据XML schema产生Java类的标准:JAXB(Java Architecture for XML binding)。JAXB提供方法将XM 数据转换成Java对象,也能把Java对象的内容写到XML实例文档。如果用户想通过 Java 接口调用一个实现了WSDL接口的SCA组件,或者手头有一个实现了WSDL接口的服务,想把该服务发布成EJB应用,WebSphere Integration Developer (WID)会自动生成JAXB的类,帮助用户实现XML数据与Java对象的转换。
W-type EJB导出绑定
对于使用 WSDL 接口的 SCA 组件,如 BPEL 等,可以通过W-type EJB导出绑定的方式将该组件发布为EJB无状态会话Bean。
下面我们以一个简单的业务场景为例,介绍如何在WID 7中开发符合EJB 3.0规范的使用EJB远程调用的W-type EJB导出绑定。
创建SCA模块
创建一个包含WSDL接口的SCA模块,提供贷款人资格审查功能。该模块通过客户端输入的贷款人信息来判断是否接受当前贷款人的贷款申请。
我们已为您准备此SCA模块,请点击附件下载,并导入WID。
在Assembly Editor里您将看到一个名为WSDLComponent的SCA组件,它实现如下WSDL接口:
图 1. WSDL接口
在该WSDL接口里使用的参数类型为DataObject。此处的Borrower是我们自定义的一个DataObject,属性amount代表贷款的金额,accepted 表示该贷款申请是否被接受。Borrower包含的信息如下:
图 2. DataObject Borrower
这里validate方法还定义了错误信息(Fault),在具体的接口实现逻辑里可以决定在特殊情况下返回一个错误信息。此处的ServiceFault也是自定义的一个DataObject,它包含的信息如下:
图 3. DataObject ServiceFault
在后文您将看到W-type EJB导出绑定怎样把DataObject 转换为EJB client所用的Java类。
创建W-type EJB导出绑定
在Assembly Editor里右键单击WSDLComponent,选择Generate Export > Enterprise JavaBeans Binding;
图 4. 生成EJB导出绑定
在弹出的New Enterprise Java Bean Export Service对话框中,选择Create an EJB client Jar Module,并新建一个名为EJBExportClient的EJB Client Project用于存放EJB client Jar,然后点击“OK”;
图 5. 新建EJB client Project
选择EJB interface type为Remote,EJB session bean version为EJB 3.0,然后点击“Finish”;
图 6. 生成EJB client JAR
稍等几秒钟,一个新的EJB导出绑定将出现在Assembly Editor中,默认名称为EJBExport,您可以单击EJB导出绑定的文字部分将其重命名为 EJBExport_WSDL_Target;
图 7. EJB导出绑定出现在Assembly Editor里
选中EJB导出绑定,在 Properties 视图里可以看到WID为EJB导出绑定自动生成的一些属性:
图 8. EJB导出绑定的属性
JNDI name:EJB Client 可以通过查找这个JNDI获取EJB导出绑定连接的SCA服务。用户可以自定义JNDI name,然后在EJB Client端查找的时候使用自定义的JNDI name;
Data Handler Type:该数据绑定处理EJB调用使用的Java类与SCA调用使用的DataObject之间的数据转换。默认的数据绑定为 JAXWSDataHandler,用户也可以使用自定义的数据绑定;
Function Selector:Function Selector 用于选择与进入EJB导出绑定的EJB调用相对应的 WSDL 接口方法。默认的Function Selector 为 SLSBExportFunctionSelector,用户同样可以使用自定义的Function Selector。
创建EJB Client
在工作空间中可以看到一个新项目EJBExportClient,这是创建EJB导出绑定时自动生成的。它包含了WSDL接口对应的Java信息,比如EJB远程接口、DataObject对应的Java类等。
单击File > New > Project > Web > Dynamic Web Project,新建名为LoanWeb的Web项目;
右键单击LoanWeb > Properties > Java Build Path,在右边的Project选项卡中,添加EJBExportClient;
图 9. 创建EJBClient
右键单击LoanWeb下的WebContent > New > JSP,新建一个名为index.jsp的页面;
编辑index.jsp,这里只展示调用EJB服务的部分:
清单 1. 部分index.jsp代码
以下是引用片段:
String name=request.getParameter("name"); Integer age=Integer.getInteger(request.getParameter("age")); Float yearlyIncome=Float.valueOf(request.getParameter("yearlyIncome")); Float amount=Float.valueOf(request.getParameter("amount")); Borrower input = new Borrower(); input.setName(name); input.setAge(age); input.setYearlyIncome(yearlyIncome); input.setAmount(amount); InitialContext context = new InitialContext(); WSDLComponentInterfaceRemote mySession = (WSDLComponentInterfaceRemote)context.lookup |--10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| ("ejbbindings.wsdlcomponentinterface.binding.WSDLComponentInterfaceRemote"); if(mySession != null){ try{ Borrower output = mySession.validate(input); } catch(ValidateFaultMsg fault){ //deal with fault } } |
这样我们就可以在JSP里以访问普通EJB的方式调用SCA服务了。
J-type EJB导出绑定
我们用如下的Java接口为例:
清单 2. Java接口
以下是引用片段:
package com.example.binding.ejb; public interface JavaComponentInterface { public Data businessOperation(Data in); } |
对于使用Java接口的SCA组件,如Java模块,可以通过J-type EJB导出绑定的方式将该组件发布为EJB无状态会话Bean。J-type EJB导出绑定同样支持EJB 3.0和EJB 2.1规范,远程调用和本地调用。值得注意的是,Java接口的参数和返回值需要实现 java.io.Serializable接口,这是EJB规范的要求,确保传输数据的可序列化。
创建J-type的EJB导出绑定的过程类似于创建 W-type 绑定。首先我们要创建SCA模块,该模块包含 Java 接口,然后在 Assembly Editor 里右键单击JavaComponent,选择Generate Export > Enterprise JavaBeans Binding。在弹出的New Enterprise Java Bean Export Service对话框中,选择Create an EJB client Jar Module。稍等几秒钟,新的EJB导出绑定将出现在Assembly Editor中,如图 10 所示。
图 10. EJB导出绑定出现在Assembly Editor中
选中EJB导出绑定,在Properties视图里可以看到WID为EJB导出绑定自动生成的JNDI名称,用户可以修改此JNDI名称。
图 11. EJB导出绑定的属性
EJB导入绑定
EJB导入绑定是WPS V6提供的功能。它能帮助SCA模块访问现有J2EE应用。
Java组件通过J-type接口调用EJB服务
EJB应用本身基于Java接口,SCA模块通过Java接口调用EJB是水到渠成的。假设我们有一个运行于应用服务器上的EJB应用,如果SCA模块需要访问它,并且该模块可以使用Java接口,比如SCA模块含有Java组件,我们就在SCA模块里添加EJB导入绑定,为绑定指定Java接口,然后设置EJB的JNDI名称为绑定的目标JNDI,把EJB client JAR设置为SCA模块的依赖项目,最后把Java组件与EJB导入绑定连线,这样我们就完成了SCA模块与EJB应用的集成。
实际生产环境中,我们常常会遇到这种情况:SCA模块和EJB服务运行于同一个单元 (cell) 的不同服务器上,或者SCA模块和EJB服务处于不同cell中,例如在WPS上运行的SCA模块要使用另一个cell里的WebSphere Application Server(WAS)上的EJB服务。这时候我们需要在WAS上配置命名空间绑定 (Name Space Bindings),定义一个在cell级别有效的JNDI名称或者跨越cell的基于CORBA协议的URL,通过命名空间绑定找到目标EJB。
BPEL流程通过W-type接口调用EJB服务
BPEL流程只有WSDL接口。WPS V6的EJB导入绑定只支持Java接口,我们无法把WSDL接口的组件和Java接口的组件直接连线,只能在它们之间添加一个Java组件作桥梁。Java组件需要实现 WSDL 接口,能连线BPEL流程,它把WSDL调用转换成对EJB导入绑定的Java调用。
创建WSDL接口的EJB导入绑定
WPS V7.0和WID V7.0为EJB导入绑定提供了新功能,支持WSDL接口,这样WSDL接口的组件就能直接连线EJB导入绑定。如果WID的workspace里已经有EJB应用,我们可以直接把它的接口拖入需要使用EJB服务的SCA模块里。WID会询问用户是创建Java组件还是EJB绑定。如果用户选择了后者,WID提示用户选择接口的类型,如图 12 所示,缺省是WSDL接口。
图 12. WID提示用户为EJB导入绑定选择接口类型
应用实例
我们继续使用EJB导出绑定选择的业务场景:贷款的审批。假设负责审批的工作人员要先获得贷款申请者的信用后再决定是否接受当前贷款人的贷款申请,而查询申请者信用的服务由EJB应用提供,也就是说SCA模块需要调用EJB服务来查询申请者信用。该EJB是符合EJB 3.0规范的无状态会话Bean:CheckCustomerCredit。它实现了远程接口CheckCustomerCreditRemote,使用的方法是:
清单 3. EJB方法
以下是引用片段:
public long checkCredit(CustomerInfo input)throws CustomerInfoInvalidException; |
我们把 EJB拖入SCA模块 (EJBBindings) 的Assembly Editor,选择生成WSDL接口的EJB导入绑定。点击OK之后,从图 13 可以看到模块结构图的变化。
图 13. Assembly Editor
WID自动创建WSDL接口checkCredit,如图 14 所示,它与EJB的Java接口checkCredit是对应的。
图 14. WSDL接口checkCredit
图 15 显示WID在创建import绑定的同时,还生成WSDL接口要用的WSDL、XSD文件,以及与XSD对应的Java类。
图 15. WID为WSDL接口生成的文件和代码
对于EJB导入绑定而言,最重要的属性是目标EJB的JNDI名称。只要JNDI名称填写正确,我们就可以通过EJB导入绑定调用目标EJB。
安全
EJB架构不鼓励开发人员用代码的方式实现安全机制,而是采用安全角色的方法,通过定义可以访问的安全角色,来限制对某个方法的访问权限。缺省情况,在EJB 3.0里面所有的方法都是 "unchecked"。也就是说缺省情况下对所有方法不用安全控制策略。如果开发人员想要指定某个方法仅能被具有某个角色的调用者执行,可用 @RolesAllowed("roleName") 来注解该方法。在我们的实例中,查询申请者信用的方法只能被角色为bankStaff(银行工作人员)的调用者执行:
清单 4. 定义EJB方法的角色
以下是引用片段:
@RolesAllowed(“bankStaff”) public long checkCredit(CustomerInfo input)throws CustomerInfoInvalidException |
EJB导入绑定在访问有安全设置的EJB时,要在与导入绑定连线的SCA模块上配置安全属性。如图 16 所示,与导入绑定连线的是 WSDLComponent,我们要为它配置 security identity qualifier (安全身份),这样WSDLComponent在运行时就以安全身份指定的角色运行,而 EJB绑定能把角色信息传递给EJB。本例中我们WSDLComponent配置的安全角色是bankStaff,它可以正常地调用EJB应用的方法 checkCredit。
图 16. SCA模块的安全设置
角色只是逻辑概念,最终还是要把角色影射到用户或用户组。在安装EJB和SCA应用时,我们都需要在安装后配置角色和用户的映射关系。登陆管理控制台,找到应用配置界面:
Application > WebSphere enterprise applications > targetApplication > Security role to user/group mapping,配置细节如图 17 所示:
图 17. 配置角色和用户的映射关系
事务
事务是企业开发的重要部分。事务保证了一个单元里面的任务是完整的,要么全部执行,要么出错后完全退回到初始状态。按照EJB 3.0 的规范,EJB由容器管理事务,而且针对所有的Bean方法,应用Required Transaction属性,它的意思是如果调用这个方法的应用没有 Transaction Environment,那么这个方法会自动创建一个新的事务。EJB导入绑定可以把事务传递到目标EJB。图 18 显示,用户要在接口上配置正确的join transaction qualifier,保证它的值是 true。同时与绑定连线的SCA组件使用的接口也做同样的设置,另外还要确保模块的实现配置了transaction qualifier为Global,如图 19 所示。这两个设置保证该组件与它后面连线的组件处于全局事务中。如果目标EJB出错抛出异常,那么所有操作都退回到初始状态。
图 18. 为接口配置事务属性
图 19. 为实现配置事务属性
结束语
EJB绑定为熟悉EJB的客户提供了访问SCA服务的一种方式,使得WPS作为集成产品满足更多客户的需求。
原文链接:http://www.searchsoa.com.cn/showcontent_45136.htm