服务器端:@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过来了。
@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过来了。
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");
}
不用全拷过来,拷个 jbossall-client.jar 就可以了。
+- 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)
我的jndi.properties加载了啊,我已经放在src下了,debug的时候也能看到jndi.properties已经加载了
问题依然没有解决,默认情况下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就不行了!
很明显,8 楼的代码不是你的,而是我在 3 楼贴的。
原因我在 7 楼已经说过了,不同的 ClassLoader 导致不同的上下文环境不一样。既然你已经试过了“默认情况下web程序就是去类路径下去找jndi.properties的”那我也没有办法了。3 楼的代码我是亲自试验过的,能调用成功。