服务器端:@Stateless
@Remote({UserDao.class})
public class UserDaoImpl implements UserDao {
/**
 * unitName="ejb" 是调用persistence.xml中的ejb这个数据源
 * 如果persistence.xml里只有一个数据源配置,则无需显示调用unitName="ejb"
 */
@PersistenceContext(unitName="ejb")
private EntityManager em;
public void add(User user) {
em.persist(user);
System.out.println("add has been called ! ");
}
public User get(int id) {
System.out.println("get has been called ! ");
return em.find(User.class,1);
}

@SuppressWarnings("unchecked")
public List<User> getAll(){
Query query = em.createQuery("from User u order by u.id desc");
List<User> users = query.setMaxResults(100).setFirstResult(0).getResultList();
em.clear();
System.out.println("getAll has been called ! ");
return users;
}
}
客户端中servlet这样访问:try{
InitialContext ctx = new InitialContext();
UserDao userDao=(UserDao)ctx.lookup("UserDaoImpl/remote");
List<User> users = userDao.getAll();
System.out.println(users.get(0).getUsername());
}catch (Exception e) {
e.printStackTrace();
}
问题是比较奇怪的:
我新建一个普通的java类,直接在主函数中调用上面的一段代码就可以访问到服务器,但是放到tomcat里的web应用里就不行,jsp页面和servlet都报错:javax.naming.NameNotFoundException: Name UserDaoImpl is not bound in this Context
at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:137)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at servlet.TestServlet.service(TestServlet.java:23)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
让我郁闷坏了。
jndi.properties:java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost客户端已经把jboss里的client中的jar包全部copy过来了。

解决方案 »

  1.   

    Tomcat 不是J2EE容器,能运行EJB吗
      

  2.   

    楼主在什么地方上班,好想使用EJB3作项目阿 
      

  3.   

    因为你的 jndi.properties 没有加载啊。private UserDao initRemoteTest() throws NamingException, IOException {
        Properties p = new Properties();
        // jndi.properties 放在 src 下
        p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jndi.properties"));
        InitialContext ctx = new InitialContext(p);
        return (UserDao) ctx.lookup("UserDaoImpl/remote");
    }
      

  4.   


    不用全拷过来,拷个 jbossall-client.jar 就可以了。
      

  5.   

    jboss控制台的jndi里有我需要的方法Global JNDI Namespace
      +- UserTransactionSessionFactory (proxy: $Proxy103 implements interface org.jboss.tm.usertx.interfaces.UserTransactionSessionFactory)
      +- UUIDKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.uuid.UUIDKeyGeneratorFactory)
      +- HiLoKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory)
      +- XAConnectionFactory (class: org.jboss.jms.client.JBossConnectionFactory)
      +- topic (class: org.jnp.interfaces.NamingContext)
      +- persistence.unit:unitName=#ejb (class: org.hibernate.impl.SessionFactoryImpl)
      +- ClusteredConnectionFactory (class: org.jboss.jms.client.JBossConnectionFactory)
      +- DIServiceImpl (class: org.jnp.interfaces.NamingContext)
      |   +- remote (class: Proxy for: test.DIService)
      |   +- remote-test.DIService (class: Proxy for: test.DIService)
      +- ProfileService (class: AOPProxy$0)
      +- UserDaoImpl (class: org.jnp.interfaces.NamingContext)
      |   +- remote-dao.UserDao (class: Proxy for: dao.UserDao)
      |   +- remote (class: Proxy for: dao.UserDao)
      +- queue (class: org.jnp.interfaces.NamingContext)
      |   +- mdb (class: org.jboss.jms.destination.JBossQueue)
      |   +- DLQ (class: org.jboss.jms.destination.JBossQueue)
      |   +- ExpiryQueue (class: org.jboss.jms.destination.JBossQueue)
      +- ClusteredXAConnectionFactory (class: org.jboss.jms.client.JBossConnectionFactory)
      +- UserServiceImpl (class: org.jnp.interfaces.NamingContext)
      |   +- local (class: Proxy for: test.UserServiceLocal)
      |   +- local-test.UserServiceLocal (class: Proxy for: test.UserServiceLocal)
      |   +- remote-test.UserServiceRemote (class: Proxy for: test.UserServiceRemote)
      |   +- remote (class: Proxy for: test.UserServiceRemote)
      +- UserTransaction (class: org.jboss.tm.usertx.client.ClientUserTransaction)
      +- ConnectionFactory (class: org.jboss.jms.client.JBossConnectionFactory)
      +- jmx (class: org.jnp.interfaces.NamingContext)
      |   +- invoker (class: org.jnp.interfaces.NamingContext)
      |   |   +- RMIAdaptor (proxy: $Proxy104 implements interface org.jboss.jmx.adaptor.rmi.RMIAdaptor,interface org.jboss.jmx.adaptor.rmi.RMIAdaptorExt)
      |   +- rmi (class: org.jnp.interfaces.NamingContext)
      |   |   +- RMIAdaptor[link -> jmx/invoker/RMIAdaptor] (class: javax.naming.LinkRef)
      +- TomcatAuthenticators (class: java.util.Properties)
      +- console (class: org.jnp.interfaces.NamingContext)
      |   +- PluginManager (proxy: $Proxy105 implements interface org.jboss.console.manager.PluginManagerMBean)
      

  6.   


    我的jndi.properties加载了啊,我已经放在src下了,debug的时候也能看到jndi.properties已经加载了
      

  7.   

    默认情况下会加载相对路径中的 jndi.properties 文件。如果是 main 方法的话,相对路径为当前工程目录。但是,如果是 web 应用的话,当前目录为 tomcat/bin 目录。因此,需要使用 Thread.currentThread().getContextClassLoader().getResourceAsStream("jnlp.properties") 进行加载。如果要看具体的相对于哪一个路径的话,很简单,使用 System.getProperties("user.dir") 就知道了。
      

  8.   


    问题依然没有解决,默认情况下web程序就是去类路径下去找jndi.properties的,我试验了:
    private UserDao initRemoteTest() throws NamingException, IOException { Properties p = new Properties(); // jndi.properties 放在 src 下  p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jndi.properties")); InitialContext ctx = new InitialContext(p); return (UserDao) ctx.lookup("UserDaoImpl/remote"); }
    还是不行啊,跟刚才报错一样。其实问题比较奇怪:我在那个servlet里面直接写一个main函数就能直接访问到,代码一模一样,但是用web访问这个servlet就不行了!
      

  9.   


    很明显,8 楼的代码不是你的,而是我在 3 楼贴的。
    原因我在 7 楼已经说过了,不同的 ClassLoader 导致不同的上下文环境不一样。既然你已经试过了“默认情况下web程序就是去类路径下去找jndi.properties的”那我也没有办法了。3 楼的代码我是亲自试验过的,能调用成功。
      

  10.   

    原来是没加包的问题如果是远程访问对象。eg:部署在tomcat中的web应用远程调用部署在jboss中的ejb下的remote对象时,需将jboss中的两个jar文件(ejb主目录\client\jbossall-client.jar 和 jnp-client.jar 两个文件)导入到自己的应用中。否则报上述错误。