好久没写了,以前也只在weblogic下写过,凭记忆写了一个例子,虽然很小,但是为了调这个东西,走了很多弯路,呵呵,写出来分享一下
1.编写一个主接口,创建组件接口的接口
package com.EJB.interfaces;
public interface HelloWorldHome extends javax.ejb.EJBHome{
HelloWorld create() throws java.rmi.RemoteException,javax.ejb.CreateException;
}
2.编写一个组件接口,被客户端使用的接口
package com.EJB.interfaces;
public interface HelloWorld extends javax.ejb.EJBObject{
public String getHello() throws java.rmi.RemoteException;
}
3.编写组件接口的实现,即具体的逻辑
package com.EJB.impl;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionContext;
public class HelloWorldImpl implements javax.ejb.SessionBean{
/*hello方法是实际的业务逻辑,它可以在客户端显示“hello,world”这个字符串*/
public String getHello() throws EJBException, RemoteException {
System.out.println("getHello()");
return "hello,worldasdfasdfasdf";
}
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
public void ejbRemove() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {
// TODO Auto-generated method stub
}
public void ejbCreate() throws javax.ejb.CreateException{}; //这个东西如果用eclipse的快速修改是不会有这个方法的,如果没有这个方法,部署到jboss会报错的,所以这个需要手工加上。
}
4.编写客户端
package test;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import com.EJB.interfaces.HelloWorld;
import com.EJB.interfaces.HelloWorldHome;
public class Test {
public static void main(String args[]){
String url = "127.0.0.1:1099";IP地址加端口号,服务器的地址,Ejb在Jboss上是1099端口
InitialContext initCtx = null;
try {
Hashtable<String,String> env = new Hashtable<String,String>();
//设置上下文环境,Context.INITIAL_CONTEXT_FACTORY这个的value根据不同的应用服务器不同而不同,weblogic也提供了自己的类。
env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
env.put(Context.PROVIDER_URL, url);
initCtx = new InitialContext(env);
Object obj=initCtx.lookup("FirstEjb");这里的FirstEjb就是jndi名字,在jboss-xml中配置的
HelloWorldHome home=(HelloWorldHome)PortableRemoteObject.narrow(obj,HelloWorldHome.class);//用rmi远程方法调用获得主接口
HelloWorld hello = home.create();//用主接口创建组件接口
String s = hello.getHello();//执行方法
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}
}
}
5.部署EJB
在EJB的项目中,在META-INF中加入ejb-jar.xml,这个就是ejb的描述了,以后jboss启动的时候会找这个项目了文件,进行部署。
jboss.xml是为了更好更简洁的处理本ejb,才加进去的,里面包括jndi的描述。
进入first/build/classes/下,运行jar -cvf hello.jar *.* 进行打包,然后把这个jar包拷贝到jboss的develop下,运行就可以了。
ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" version="2.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">
<display-name>First</display-name>
<enterprise-beans>
<session>
<ejb-name>FirstEjb</ejb-name>
<home>com.EJB.interfaces.HelloWorldHome</home><!--主接口-->
<remote>com.EJB.interfaces.HelloWorld</remote><!--组件接口-->
<ejb-class>com.EJB.impl.HelloWorldImpl</ejb-class><!--组件接口的实现-->
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
jboss.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss>
<enterprise-beans>
<session>
<ejb-name>FirstEjb</ejb-name> <!--EJB名称和ejb-jar.xml中的<ejb-name>一样-->
<jndi-name>FirstEjb</jndi-name> <!--jndi路径,被客户端调用是使用的jndi,即可以找到ejb的路径-->
</session>
</enterprise-beans>
</jboss>
6.运行EJB
运行客户端,即可获得在屏幕上打印一行hello,world的效果
注意:
运行EJB,最主要就是要分布式,那么如果在同一个项目中编写客户端就没什么意义了,基于这个,下面举一个远程调用的例子:
1.把主接口和组件接口拷贝到要调用EJB的项目中
2.把jbossall-client.jar拷贝到要调用EJB的项目中,要不然会报如下错误
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 test.Test.main(Test.java:20)
Caused by: java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.sun.naming.internal.VersionHelper12.loadClass(Unknown Source)
... 5 more
3.确定实现和主接口和组件接口分离,不要把实现也拷过去了,那就没啥用了,这里
4.如果报连接不到远程的地址什么的,请检查url中时候包含rmi://,如果有会报错的。
这里讲的很浅,家里的weblogic 的EJB例子比较详细,而且分包的,把接口和实现分成两个包,拷贝起来也方便,可以回去看看。