今天返璞归真,在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
分享到:
相关推荐
**EJB 3.0 规范概述** Enterprise JavaBeans(EJB)是Java平台企业版(Java EE)的一部分,用于构建可扩展、安全且事务处理的服务器端应用...无论是初次接触EJB,还是寻求提升现有应用的开发者,都能从中受益匪浅。
8. **持久化**:讨论JPA(Java Persistence API)和JDO(Java Data Objects)在EJB中的应用,以及ORM(Object-Relational Mapping)策略。 9. **异步处理**:讲解消息驱动bean如何处理异步请求和工作流。 10. **...
EJB3的初次体验** 本书的第一章“EJB3初体验”介绍了EJB3的基本概念及其相对于前代版本的重大改进,通过实际示例帮助读者快速入门。这一章节对于初学者来说尤为重要,因为它不仅涵盖了EJB3的基础知识,还展示了...
这一章深入探讨了EJB中消息驱动Bean的使用场景和编程模型。读者将学到如何处理异步消息,以及如何集成JMS消息系统。 5. **第5章:学习高级EJB概念** 本章涉及EJB的一些高级主题,如拦截器、定时服务等。这些特性...
尽管如此,初次接触JBoss的开发者可能会因缺乏图形化向导而感到困扰,配置和部署EJB相对复杂。 在JBoss3.0中,EJB的配置和部署主要涉及以下文件: 1. **ejb-jar.xml**:这是EJB的描述文件,按照J2EE规范定义,是...
- 对于初次接触 EJB 的读者来说,这一章是非常重要的入门章节,它能够帮助读者建立起对 EJB 3.0 的整体认知。 - **第 2 章:EJB 3.0 初体验** - 在这一章中,作者通过一个简单的示例项目引导读者快速上手 EJB 3.0...
**JPA**是在EJB3.0规范中引入的,它的出现极大地简化了企业级应用中数据库访问的复杂性。JPA的目标是为Java SE和Java EE提供一个统一的对象/关系映射工具的标准,使开发人员能够在不牺牲性能的前提下,以声明的方式...
#### 第2章:初次接触EJB - **章节内容**:通过一个简单的示例来引导读者初步了解如何使用EJB。 - **核心知识点**: - EJB容器的概念及其作用。 - 如何创建和部署简单的EJB项目。 - 基础的EJB接口和实现类的编写...
Session Beans是EJB中最常见的类型之一,它们负责处理客户端请求,执行业务逻辑,并协调与其他EJB组件的交互。通过JBuilder 4的向导和特性,开发者可以轻松创建和部署参与容器管理事务的Session Beans,实现复杂的...
以上就是Keil的初次使用过程中涉及的主要知识点,掌握这些基础知识后,你就可以开始编写和调试基于8051的嵌入式程序了。随着经验的增长,你将更加熟悉Keil的高级功能,如宏定义、函数库的使用等,进一步提升你的开发...
针对祁南煤矿34下4综采工作面采用7.0 m×3.0 m的大断面开切眼,利用FLAC2D数值模拟软件,对综采工作面初次来压期间的应力分布规律进行了数值模拟,得到了工作面初次来压期间工作面的垂直应力及水平应力的分布规律,可为...
2. 电气连接:文档中详细介绍了控制柜与机器人本体之间的电气连接细节。具体包括了控制柜供电接口、机器人安全回路接口、信号线和数据线的连接,以及如何正确使用这些接口。 - 控制柜供电接口(X1接头):根据不同...
Hadoop 分布式集群初次启动是大数据处理中的重要步骤,本文将指导用户如何在虚拟机中搭建 Hadoop 分布式集群,并对其进行初次启动。 1. SSH 免密登录 在 Hadoop 分布式集群中,各个节点之间需要配置 SSH 免密登录...
初次来压是指工作面开采过程中,上覆岩层首次产生显著下沉和应力重新分布的现象,此时顶板的压力显著增大,可能导致大面积垮落,引发压垮型、漏跨型甚至摧垮型冒顶事故,这些事故不仅影响工作进度,还可能伴有水灾、...
为了研究阻化剂对煤样初次与二次氧化特性的影响,选用KCl、Ca Cl2、Mg Cl2和Na Cl等4种常用阻化剂对原煤样和初次氧化煤样分别进行处理,通过程序升温实验,研究阻化剂对煤的两次氧化过程自燃特性的影响程度。...
员工初次定级标准表.xls