`
lixw
  • 浏览: 197034 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

初次玩玩传言中已过时的EJB2

    博客分类:
  • J2EE
阅读更多

今天返璞归真,在JBoss上做了一个EJB2的简单例子,我是怎么做的呢?

首先我们看下面的RMI架构图,它说明了本地对象如何与远程对象进行通信:

 

我们采用WTP创建EJB工程的向导,还是利用那个经典的例子:

 

利用XDoclet自动生成的工程包含的文件有:

 

 

这里我们忽略Local接口。

在ConverterBean的foo()方法中编写我们的业务逻辑。

默认生成一个ejb-jar.xml配置文件,它是EJB规范中要求的描述文件,可能像这样:

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar id="ejb-jar_1" xmlns="http://java.sun.com/xml/ns/j2ee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">
   <description><![CDATA[TestEJB2 generated by eclipse wtp xdoclet extension.]]></description>
   <display-name>TestEJB2</display-name>
   <enterprise-beans>

      <!-- Session Beans -->
      <session id="Session_Converter">
         <description><![CDATA[An EJB named Converter]]></description>

         <display-name>Converter</display-name>
         <ejb-name>Converter</ejb-name>
         <home>cn.com.samueli.ejb2.ConverterHome</home>
         <remote>cn.com.samueli.ejb2.Converter</remote>
         <ejb-class>cn.com.samueli.ejb2.ConverterBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
      </session>

     <!--
       To add session beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called session-beans.xml that contains
       the <session></session> markup for those beans.
     -->

      <!-- Entity Beans -->
     <!--
       To add entity beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called entity-beans.xml that contains
       the <entity></entity> markup for those beans.
     -->

      <!-- Message Driven Beans -->
     <!--
       To add message driven beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called message-driven-beans.xml that contains
       the <message-driven></message-driven> markup for those beans.
     -->
   </enterprise-beans>
</ejb-jar>

我们这里部署在JBoss4上,所以还需要特定于容器的部署描述文件,可能像这样:(jboss.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">
<jboss>
	<enterprise-beans>
		<session>
			<ejb-name>Converter</ejb-name>
			<jndi-name>MyConverter</jndi-name>
		</session>
	</enterprise-beans>
</jboss>

万事俱备,我们部署我们的EJB应用到<JBoss-install>/server/default/deploy下面,并启动服务。

 

客户端我们采用两种方式来调用远程对象,一种利用Lookup查找接口,一种利用Spring的支持:

首先来看第一种:

public static void main(String[] args) {
		try {
			Context initial = new InitialContext();
			Object objref = initial.lookup("MyConverter");
			ConverterHome home = (ConverterHome) PortableRemoteObject.narrow(
					objref, ConverterHome.class);
			Converter c = home.create();

			c.foo();
			System.exit(0);
		} catch (Exception ex) {
			System.err.println("Caught an unexpected exception!");
			ex.printStackTrace();
		}
	}

由于采用JNDI查找,我们还需要这样的配置文件:(jndi.properties)

# jndi.properties --
#
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
 

 

第二种方法,对于spring支持,我们首先需要有这样的配置文件:(applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
	<bean id="jndiTemplate"
		class="org.springframework.jndi.JndiTemplate">
		<property name="environment">
			<props>
				<!--
				<prop key="java.naming.provider.url">
					t3://127.0.0.1:7001
				</prop>
				<prop key="java.naming.factory.initial">
					weblogic.jndi.WLInitialContextFactory
				</prop>
				
				<prop key="java.naming.provider.url">
					iiop://127.0.0.1:2809
				</prop>
				<prop key="java.naming.factory.initial">
					com.ibm.websphere.naming.WsnInitialContextFactory
				</prop>
				-->
				
				<prop key="java.naming.provider.url">
					localhost:1099
				</prop>
				<prop key="java.naming.factory.initial">
					org.jnp.interfaces.NamingContextFactory
				</prop>
				
			</props>
		</property>
	</bean>

	<bean id="ConvertorEJB"
		class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"
		lazy-init="true">
		<property name="jndiTemplate">
			<ref local="jndiTemplate" />
		</property>
		<property name="jndiName">
			<value>MyConverter</value>
		</property>
		<property name="businessInterface">
			<value>cn.com.samueli.ejb2.Converter</value>
		</property>
	</bean>
	
	</beans>

我们的代码中就很简单了,可能是这样:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");		
Converter c = (Converter) context.getBean("ConvertorEJB");
try {
	c.foo();
} catch (RemoteException e) {
	e.printStackTrace();
}

 

OK,我们的两种客户端访问方式都可以调用远程对象的方法,并输出了理想中的结果。

 

当然在上面的过程也出现了一些问题,比如在客户端运行时出现了一些错误:

客户端代码片段:

try {
	Context initial = new InitialContext();
	Object objref = initial.lookup("java:comp/env/ejb/Converter/MyConverter");
	ConverterHome home = (ConverterHome) PortableRemoteObject.narrow(
			objref, ConverterHome.class);
	Converter c = home.create();

	c.foo();
	System.exit(0);
} catch (Exception ex) {
	System.err.println("Caught an unexpected exception!");
	ex.printStackTrace();
}

报错:

javax.naming.NoInitialContextException: Cannot instantiate class: 
org.jnp.interfaces.NamingContextFactory 
[Root exception is java.lang.ClassNotFoundException: 
org.jnp.interfaces.NamingContextFactory]
 at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
   at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
   at javax.naming.InitialContext.init(Unknown Source)
   at javax.naming.InitialContext.<init>(Unknown Source)
   at ConverterClient.main(ConverterClient.java:12)

原来是缺少客户端依赖文件,把<JBoss-install>/client目录下的:jbossall-client.jar和jnp-client.jar添加到Build path中,再运行仍然报错:

javax.naming.NameNotFoundException: comp not bound

Google了一下,发现原来问题是这样:

CJSDN开发者社区 写道
当你的程序运行在 container 环境中的时候 java:comp 才需要
当你的程序运行在客户端的时候,直接使用
lookup("interest/Interest") 就可以了
在运行之前你可以访问
http://localhost:端口/jmx-console/
然后使用 service=JNDIView
点击最后的 list 下面的 invoke 看一看现在 jboss3 的 jndi 里面都有哪些对象
直接看最下面的 global 部分就可以了,看看有没有 interest/Interest
如果有,那就说明部署成功了,调用应该就没有问题了

 于是把我的客户端程序的:

Object objref = initial.lookup("java:comp/env/ejb/Converter/MyConverter");

 修改为:

Object objref = initial.lookup("MyConverter");

 运行OK了。

 

参考:

http://blog.csdn.net/baobao8505/archive/2007/05/21/1619368.aspx

http://www.blogjava.net/kawaii/archive/2007/02/06/98395.html

  • j-rmi.zip (564.3 KB)
  • 描述: IBM DW上的一个关于分布式对象的教程。
  • 下载次数: 15
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics