MyEclipse+JBoss创建第一个EJB,部署并通过JNDI远程调用全过程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyEclipse+JBoss创建第一个EJB,部署并通过JNDI远程调用全过程相关的知识,希望对你有一定的参考价值。

在EJB3规范中,Entity Bean被摒弃了,替代之的是实体与JPA(Java Persistence API,Java 数据持久化API)作为数据持久层解决方案。现在看看EJB3的规范:

图1

技术分享

关于实体与JPA规范和hibernate之间的联系本文不care,本文的目的是研究SessionBean(会话企业bean),特别是无状态(stateless)SessionBean。

 

第一步

在myEclipse中新建一个EJB工程:

图2

技术分享

JPA支持暂时不选,Maven也不启用,直接单击Finish。

 

创建一个名为HelloWorld的EJB SessionBean:

右键点击src——new 选择EJB3 SessionBean,看到如下界面

技术分享图3

注意Session Type选择Stateless(不保持客户机状态),自动创建Interface Remote(勾选后系统自动为我们创建HelloWorldRemote接口,暴露给客户机调用我们的远程方法),单击finish。

 

@Stateless
public class HelloWorld implements HelloWorldRemote {
}

我们看到系统给我们的函数名上面添加了注解。这种@annotation注解的方式替代了在EJB2规范中的xml配置方式,但同时也兼容XML配置方式。关于EJB还有几种@annotation注解我们以后再做讨论。

 

在HelloWorldRemote中我们写一个远程方法HelloEJB:

import javax.ejb.Remote;

@Remote
public interface HelloWorldRemote {
  public String HelloEJB(String name);
}

control+s 一下然后发现 HelloWorld 这个实现类的类名被下滑花线标起来了,鼠标移上去,提示我们有未实现的接口方法,点第一个选项, myeclipse 直接帮我们创建该方法的模版代码,这也是先写接口 ( 当里面有很多很多方法的时候 ) 再写实现类的快速创建方法。

技术分享图4

 

本文的题目是创建EJB并通过JNDI进行引用,那么在我们的实现类中,必须绑定一个JNDI名,这里我们直接通过@Stateless(mappedName=”HelloEJB”)来绑定JNDI.

package com.getcoo.service;

import javax.ejb.Stateless;

@Stateless(mappedName="HelloEJB")
public class HelloWorld implements HelloWorldRemote {

  public String HelloEJB(String name) {
    // TODO Auto-generated method stub
    return name+",你好,欢迎访问我的EJB。";
  }

}

 

接下来我们需要将此项目部署至jboss服务器,由于我这里myeclipse部署有点小问题,我们采用最笨拙的部署方式:

右键点击此项目,选择导出项目

图5

技术分享

导出成Jar file

图6

技术分享

选择以下导出路径,单击确定。

再打开jBoss控制台: localhost:8080

图7

技术分享

展开图示的路径,我们发现helloEJB.jar还是没有出来,我再从右上角的add resource再添加一下(懒得找原因了),

图8

 

 

单击continue,OK 应该是部署好了

 

图9

技术分享

图10

技术分享

等status变为Success。

 

第二步:

还是在这个工程下创建一个test类(如果另建一个普通java工程,需要把上面的两个java文件拷贝过去,或者jar包拷过去当做lib,不然无法import):

/**
 * 
 */
package com.getcoo.client;

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.getcoo.service.HelloWorldRemote;


/**
 * @author 墨半成霜
 *
 */
public class HelloEJBTest {
  public void test() throws NamingException{
    
    Context jbossCtx = getJBossInitialContext();
    
    HelloWorldRemote myEJB =(HelloWorldRemote)jbossCtx.lookup("HelloEJB");
    

    System.out.println("成功获得对远程EJB实例的引用,该引用实例为:"+myEJB);
    
    System.out.println(myEJB.HelloEJB("墨半成霜"));

  }	

  private Context getJBossInitialContext()
  {
    final String INIT_FACTORY="org.jnp.interfaces.NamingContextFactory";
    final String SERVER_URL="localhost:1099";
    Context ctx=null;
    try{
      Properties props = new Properties();
      props.put(Context.INITIAL_CONTEXT_FACTORY,INIT_FACTORY);
      props.put(Context.PROVIDER_URL, SERVER_URL);
      ctx= new InitialContext(props);
    } 
    catch (NamingException ne){
      System.err.println("不能连接JBoss Server 在:"+SERVER_URL);
      ne.printStackTrace();
    }
    return ctx;
  }
  
  public static void main(String[] args) throws Exception
  {
    HelloEJBTest  client= new HelloEJBTest();
    client.test();
    
  }

}

run一下:

不能连接JBoss Server 在:localhost:1099
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(NamingManager.java:657)
  at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
  at javax.naming.InitialContext.init(InitialContext.java:223)
  at javax.naming.InitialContext.<init>(InitialContext.java:197)
  at com.getcoo.client.HelloEJBTest.getJBossInitialContext(HelloEJBTest.java:38)
  at com.getcoo.client.HelloEJBTest.test(HelloEJBTest.java:22)
  at com.getcoo.client.HelloEJBTest.main(HelloEJBTest.java:50)
Caused by: java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory
  at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
  at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
  at java.lang.Class.forName0(Native Method)
  at java.lang.Class.forName(Class.java:247)
  at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:46)
  at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:654)
  ... 6 more
Exception in thread "main" java.lang.NullPointerException
  at com.getcoo.client.HelloEJBTest.test(HelloEJBTest.java:23)
  at com.getcoo.client.HelloEJBTest.main(HelloEJBTest.java:50)

 

 

Why?我仔细检查了一下,我这里没有错,如果被这一大堆错误吓懵了 立马去找错误的话,不是一个好程序员,我们要看什么呢?要找Root exception,对根源异常,往往这是问题关键。

root exception显示:

Cannot instantiate class: org.jnp.interfaces.NamingContextFactory
    [Root exception is java.lang.ClassNotFoundException: 
           org.jnp.interfaces.NamingContextFactory]

多么清楚的异常,org.jnp.interfaces.NamingContextFactory这个类系统没找到。那么说我命我们引用了这个类,但是没在添加相关的lib。

这个类是jBoss的JNDI 命名上下文工厂类,我们不管了,直接把上个例子中添加的jBoss lib添加进来:

 

图11

技术分享
 

 

 

再run一次:

成功获得对远程EJB实例的引用,该引用实例为:Proxy to jboss.j2ee:jar=helloEJB.jar,name=HelloWorld,service=EJB3 implementing [interface com.getcoo.service.HelloWorldRemote]
墨半成霜,你好,欢迎访问我的EJB。

 

 

恭喜,到这里,欢迎您踏入EJB的世界. 

以上是关于MyEclipse+JBoss创建第一个EJB,部署并通过JNDI远程调用全过程的主要内容,如果未能解决你的问题,请参考以下文章

Myeclipse10, JBoss7.11 final, EJB 3.1 配置部署

3EJB3.0开发第一个无会话Bean和客户端(jboss4.2.3)

使用MyEclipse开发Java EE应用:用XDoclet创建EJB 2 Session Bean项目

JBoss 7 里一个EJB依赖其他jar的几种方式

使用MyEclipse开发Java EE应用:EJB项目开发初探(下)

JBoss 监控/分析