级别: 初级 陈亚强 (cyqcims@mail.tsinghua.edu.cn), 高级软件工程师, 北京华园天一科技有限公司
2003 年 8 月 15 日 本文和《J2EE连接器的开发》是姊妹篇,前一篇结合一个具体的案例介绍了连接器的开发技术,在本篇将开发资源适配器的典型客户端,然后把它们和上一篇开发的连接器部署到当今流行的J2EE应用服务器平台下(这些平台包括IBM WebShpere,J2SDKEE1.3,JBOSS3.2,BEA Weblogic8.1),并且在客户端进行调用测试。
阅读本文前,请先阅读《J2EE连接器的开发》一文,并且下载、安装相关的应用服务器的试用版。
本文的参考资料见
参考资料。
本文的全部代码在这里
下载。
开发访问资源适配器的EJB组件
EJB组件通过资源适配器来访问EIS,在EJB组件中,定义了最终客户端要使用的业务方法,一般实现为会话Bean,它一般通过和多个J2EE组件或者资源适配器交互来完成具体的业务逻辑。在这个案例中,EJB组件的功能非常简单,就是接收最终客户端的请求,然后通过资源适配器调用EIS并获得结果,最终把结果返回给客户端。
EJB组件定义了一个业务方法,它的远程接口的代码如例程1所示。
例程1 EJB组件的远程接口
package com.hellking.jca.ejb;
import java.rmi.RemoteException;
import javax.ejb.*;
public interface Demo extends EJBObject
{
public String sayHello(String arg) throws RemoteException;
}
|
在这个接口里,定义了一个业务方法,就是sayHello(String name)。我们来看EJB组件的实现类部分代码,如例程2所示。
例程2 EJB实现类的部分代码
package com.hellking.jca.ejb;
import ….
public class DemoEJB implements SessionBean
{
private SessionContext sessionCtx;
//业务方法
public String sayHello(String arg)throws Exception
{
System.out.println("echo, arg="+arg);
String result="";
try
{
InitialContext iniCtx = new InitialContext();
Context enc = (Context) iniCtx.lookup("java:comp/env");
Object ref = enc.lookup("eis/DemoEISFactory");//获得连接工厂
ConnectionFactory dcf = (ConnectionFactory) ref;
DemoConnection dc =(DemoConnection) dcf.getConnection();//从连接工厂创建连接
result=dc.sayHello(arg);//调用虚拟连接的业务方法
dc.close();//使用完,关闭虚拟的连接。
}
catch(NamingException e)
{
System.err.println("在查找JNDI名字时遇到错误:"+ e);
}
return result;//返回调用的结果
}
…
}
|
以上代码是典型的使用资源适配器的方法,首先通过JNDI来查找连接工厂实例(这个实例由应用服务器自动绑定),然后从这个连接工厂获得连接实例,接下来从连接实例调用业务方法,最后关闭连接。
开发客户端
本案例使用了两种类型的客户端,一种客户端基于浏览器,它通过HTTP访问JSP组件,JSP组件通过RMI调用EJB组件,EJB组件再通过资源适配器调用EIS;另一种客户端是普通的Java程序,这个Java程序通过RMI调用EJB,EJB组件再通过资源适配器调用EIS。
在实现中,JSP代码和普通java程序的代码基本一样,不同的是它们获得初始上下文环境(InitialContext)的方法不同。
我们看一下简单的JSP客户端,如例程3所示。
例程3 JSP客户端
<%@ page contentType="text/html;charset=gb2312" import="com.hellking.jca.ejb.*,javax.naming.*"%>
<html><body><form><table><tr><td>请输入名字:
</td><td><input name=name type=text></td></tr>
<tr><td><input value=submit type=submit></td></tr></table></form>
<%
String name=(String)request.getParameter("name");
try
{
InitialContext context=new InitialContext();
DemoHome home=(DemoHome)javax.rmi.PortableRemoteObject.narrow(
context.lookup("ejb/demo"),DemoHome.class);
Demo demo=home.create();
if(demo!=null)out.println("demo is ok");
out.println("调用ejb-->jca-->eis");
out.println("发送了:hellking,返回以下的值:<hr><font color=red>");
out.println(demo.sayHello(name));
out.println("</font>");
out.flush();
}
catch(Exception e)
{
}
%></body></html>
|
普通的java客户端和JSP基本一样,只是需要指定相关的属性才能获得InitialContext实例。可以通过以下的方法获得InitialContext实例。
例程4 在普通的Java客户端获得InitialContext实例
//创建初始的上下文环境
public Client()
{
context=this.getInitialContext();
}
public InitialContext getInitialContext()
{
try
{
Properties p=new Properties();
p.load(new FileInputStream("config.properties"));
return new InitialContext(p);
}
catch(Exception e)
{
System.out.println("got ee");
e.printStackTrace();
return null;
}
}
|
Java客户端的详细代码见src/client/Client.java文件。
下面介绍装配和部署的相关问题。
部署方法介绍
在不同的应用服务器下部署J2EE应用时,基本上大同小异。部署工作基本上按照以下步骤进行:
- 把J2EE应用和连接器打包成ear文件;
- 使用应用服务器厂商提供的工具把ear装配成可以部署的ear包,在装配的过程中,和应用服务器特定的部署描述符自动添加到ear包中;
- 使用应用服务器提供的控制台进行部署,在部署时,可能需要指定一些属性。
对于JBOSS,没有提供装配工具和部署控制台,需要手工进行编写专有的部署描述,并且手工部署。
在进行装配、部署工作前,请把J2EE应用打包成ear文建,打包后的结构如下:
+resource.ear
+hello.jar
-META-INF/ejb-jar.xml
+com/hellking/jca
+com/hellking/jca/ejb
+demo.rar
-META-INF/ra.xml
+com/hellking/jca
+web.war
-WEB-INF/web.xml
-test.jsp
-META-INF/application.xml
|
下面首先介绍在J2SDKEE1.3下装配和部署J2EE应用。
在J2SDKEE1.3下部署连接器和J2EE应用
step1 首先启动J2EE和部署工具,在控制台输入:
start j2ee -verbose
start deploytool
step2 新建一个应用。
依次点击【File】à【new】à【Application】,选择应用的目录,输入应用的名称,如图1所示。
图1新建一个应用
step3 把资源适配器添加到应用中
依次点击【File】→【new】→【Resource Adapter】,在第一个窗口点击【next】,然后把资源适配器的类添加进来,然后点击【next】,如图2所示。
图2 添加资源适配器相关的类
在下一个窗口指定资源适配器的相关接口和实现类,如图3所示。
图3 指定资源适配器的相关接口和实现类
然后点击【vsersion information】按钮,输入版本相关的信息,完成后,点击【next】。
在下一个窗口为连接工厂添加两个属性,然后点击【next】,它们的名称和值如图4所示。
图4 为连接工厂添加属性
在解下来的窗口直接点击【next】,最后将生成部署代码,点击【finish】。
Step4 把EJB组件添加到J2EE应用中
【File】→【new】→【Enterprise Bean】,然后把EJB组件相关的类添加进来,如图5所示。
图5 添加EJB组件相关的类
接下来的窗口指定Bean的类型为无状态会话Bean,实现类为DemoEJB,远程接口为Demo,Home接口为DemoHome,然后在接下来的窗口直接点击【Next】,直到出现资源工厂引用窗口,添加一个资源工厂引用,它的名字为"eis/DemoEISFactory",类型是"javax.resource.cci.ConnectionFactory",如图6所示。
图6 为EJB添加资源引用
然后点击【finish】。
Step5 新建一个Web组件,把test.jsp测试页面添加进来。
Step6 在部署工具中指定EJB的JNDI名字为"ejb/demo"。
Step 7 指定Web组件的Context(上下文)为"/resource"。
Step8 检查装配的描述是否正确,选中resource应用,然后点击工具栏 图标即可。
Step9 部署,选中resource应用,然后点击工具栏 ,在弹出的对话框点击【finish】即可。
Step10 部署成功后,把资源适配器添加到对应的应用服务器,使其运行。如图7所示,选择localhost,点击【new】。
图7 把资源适配器添加到服务器
然后指定连接工厂的JNDI,如图8所示。
图8 指定连接工厂的JNDI
部署成功后,启动EIS服务器,EIS服务器通过执行src/eis-server/run.bat进行启动,然后就可以进行测试了,在浏览器里输入:
http://localhost:8000/resource/test.jsp
进行测试。如果一切顺利,将在页面中返回测试的结果,如图9所示。
图9 测试资源适配器
在测试时,通用可以看到EIS服务器也输出了类似以下的信息:
启动服务....监听客户端连接...接收到一个连接监听客户端连接...接收到以下输入: hellking
在IBM WebShpere5.0下部署连接器和J2EE应用
step1 启动应用程序组装器,打开需要装配的J2EE应用,如图10所示。
图10打开需要装配的J2EE应用
step2 选中DemoEJB,点击【绑定】选项卡,输入DemoEJB的JNDI名字,然后点击【应用】,如图11所示。
图11 确定DemoEJB的JNDI名字
step3 其它的值都默认,然后保存更改。
Step4 生成部署代码。顺次点击【文件】→【生成部署代码】,在弹出的对话框里点击【现在生成】。如图12所示。
图12 生成部署代码
注意生成代码时应该是没有错误的,如果有错误,请参考对应的错误信息。
Step5 启动IBM Websphere服务器,在浏览器里输入:
http://localhost:9090/admin
进入管理控制台。
Step6 部署J2EE应用。
选择【应用程序】→【安装新的应用程序】,浏览到刚才生成的部署代码,如图13所示,然后点击【下一步】。
图13 安装应用程序第一步
在接下来的几个窗口直接点击【下一步】,直到出现如图14所示的窗口,在这个窗口中指定映射资源引用到资源的JNDI名字,这个是"eis/DemoEISFactory"。
图14 指定映射资源引用到资源的JNDI名字
其它的步骤全部默认即可,配置完成后,保存配置。
Step7 启动刚部署的J2EE应用
顺次选择【应用程序】à【企业应用程序】,然后选中刚部署的程序,点击【启动】。
Step8 为资源适配器指定J2C连接工厂
选中刚才部署的J2EE应用,顺次选择【连接器模块】→【demo.rar】→【J2C 连接工厂】,新建一个J2C连接工厂,它的名称为DemoEISFactory,JNDI名称为"eis/DemoEISFactory",其它默认,然后点击确定。最后别忘了保存配置。
Step9 重新启动应用服务器,启动EIS服务(src/eis-server/run.bat),在浏览器里输入:
http://localhost:9080/resource/test.jsp?name=hellking
进行测试,如果测试成功,那么结果和图9一样。
在JBOSS3.2下部署连接器和J2EE应用
JBOSS虽然没有装配工具和部署控制台,但是在JBOSS下部署J2EE应用和资源适配器同样非常方便,JBOSS支持及时开发、及时部署的方式,当把要部署的应用拷贝到JBOSS的部署目录下,JBOSS应用服务器会自动部署它。
在JBOSS下部署应用时,可以不打包,而是直接J2EE应用放在名称为***.jar、***.ear的文件夹下。如图15所示。
图15 JBOSS下的J2EE应用的结构
Step1 手工编写资源适配器的部署描述符,如例程5所示。
例程5 JBOSS下的资源适配器的部署描述符
<server>
<mbean code="org.jboss.resource.connectionmanager.NoTxConnectionManager"
name="jboss.jca:service=NoTxCM,name=DemoRA">
<depends>jboss.jca:service=RARDeployer</depends>
<depends optional-attribute-name="ManagedConnectionFactoryName">
<mbean code="org.jboss.resource.connectionmanager.RARDeployment"
name="jboss.jca:service=NoTxDemo,name=DemoRA">
<depends optional-attribute-name="OldRarDeployment">
jboss.jca:service=RARDeployment,name=DemoRA
</depends>
<attribute name="JndiName">NoTransDemo</attribute>
</mbean>
</depends>
<depends optional-attribute-name="ManagedConnectionPool">
<mbean code="org.jboss.resource.connectionmanager.JBossManagedConnectionPool"
name="jboss.jca:service=NoTxPool,name=DemoRA">
<attribute name="MinSize">0</attribute>
<attribute name="MaxSize">50</attribute>
<attribute name="BlockingTimeoutMillis">5000</attribute>
<attribute name="IdleTimeoutMinutes">15</attribute>
<attribute name="Criteria">ByContainer</attribute>
</mbean>
</depends>
<depends optional-attribute-name="CachedConnectionManager">
jboss.jca:service=CachedConnectionManager
</depends>
<depends optional-attribute-name="JaasSecurityManagerService">
jboss.security:service=JaasSecurityManager
</depends>
</mbean>
</server>
|
注意上面的两个黑体字,name=DemoRA,这里的DemoRA必须和资源适配器部署描述符ra.xml中的"DemoRA"保持一致,NoTransDemo是使用这个资源适配器的JNDI名字,使用"java:/ NoTransDemo"来引用它。把这个文件保存为hellkingjca-service.xml。
Step2 手工编写EJB的部署描述符jboss.xml。
并且在部署描述符里指定对资源适配器的引用。如例程6所示。
例程6 在EJB的描述中指定对资源适配器的引用
<?xml version="1.0"?>
<jboss>
<secure>false</secure>
<container-configurations />
<resource-managers />
<enterprise-beans>
<session>
<ejb-name>DemoEJB</ejb-name>
<jndi-name>ejb/demo</jndi-name>
<resource-ref>
<res-ref-name>eis/DemoEISFactory</res-ref-name>
<jndi-name>java:/NoTransDemo</jndi-name>
</resource-ref>
</session>
</enterprise-beans>
</jboss>
|
注意对资源适配器引用的JNDI名字,它必须和hellkingjca-service.xml的指定的JNDI名字一致。把这个文件保存在resource.ear/hello.jar/META-INF/目录下。
Step 3 部署,把resource.ear文件夹和hellkingjca-service.xml拷贝到%JBOSS_HOME%\\server\\default\\deploy\\目录下。启动JBOSS,部署就会自动完成。
Step4 测试,启动JBOSS和EIS服务(src/eis-server/run.bat),在浏览器里输入:
http://localhost:8080/resource/test.jsp?name=hellking
即可进行测试,如果一切成功,那么结果应该和图9一样。
在BEA Weblogic8.1下部署连接器和J2EE应用
step1 启动Weblogic Builder,打开待装配的应用(resource.ear)。
step 2 指定DemoEJB的JNDI名字。
选中DemoEJB,点击【General】选项卡,在JNDI name中输入"ejb/demo",如图16所示。
图16 在Weblogic Builder里指定EJB的JNDI名字
step3 指定资源适配器连接工厂的名字和JNDI名字:
选择DemoRA,点击【Weblogic Settings】选项卡,找到"Connection Factory name"标签,在下面的输入框输入"DemoEISFactory",然后找到"JNDI name"标签,在下面的文本框输入"eis/DemoEISFactory",它是这个连接工厂绑定的JNDI名字。
Step4 指定EJB对资源适配器连接工厂的引用:
点击DemoEJB,选择Resource,再点击【Resource References】选项卡,编辑这个引用的属性,把JNDI名字改为"eis/DemoEISFactory",如图17所示。
图17 确定EJB引用的资源适配器的连接工厂的名字
step5 其它的值都默认,保存这个应用,weblogic Builder会自动生成可以部署的代码。
Step 8 部署
启动Weblogic引用服务器,在浏览器里输入:
http://localhost:7001/console
输入用户名和密码进行验证,进入控制台,顺次点击【mydomain】à【Applications】à【Deploy a new Application】à【upload your file(s)】,然后上载刚生成的可部署代码。上载完成后,选择这个上载的文件,点击【Contnue】,在接下来的窗口点击【Deploy】,如果出现图18所示的窗口,表示部署成功了。
图18 在Weblogic下部署成功
Step 9 测试,部署完成后,启动EIS服务(src/eis-server/run.bat),然后在浏览器里输入:
http://localhost:7001/resource/test.jsp
进行测试,如果一切顺利,获得的结果和图9一致。
总结
从以上不同的部署过程可以看出,J2EE应用和资源适配器在不同的服务器平台下具有良好的可移植性。对于EJB组件,需要在应用服务器特有的部署描述符中指定JNDI名字。至于EJB对资源适配器连接工厂的引用方式的指定,它们又有所差别,有的在装配时就指定资源适配器连接工厂的JNDI名字,这种方式下,应用服务器启动或者资源适配器部署时,它的连接工厂就绑定到JNDI名称空间,比如Weblogic就是这样;而有的应用服务器需要在部署时为资源适配器指定连接工厂的JNDI名字,然后再在EJB的部署中进行映射,比如Websphere就是这种方式。
参考资料
关于作者  | |  | 陈亚强:北京华园天一科技有限公司高级软件工程师,擅长J2EE技术,曾参与多个J2EE项目的设计和开发,对Web服务有很大的兴趣并且有一定的项目经验。热爱学习,喜欢新技术,曾参与多本图书的写作。好交朋友,您可以通过
cyqcims@mail.tsinghua.edu.cn 和他联系。
|
对本文的评价
|