EJB2.1的localhome问题
最近要重构一批代码,某些EJB要改成local访问,于是先动手做了个简单例子做试验,没想到这里就碰了钉子。
首先说明,所有东西不变,只要改用remote和remoteHome接口就完全没问题
我用来试验的容器是glassfish u2
提示一直都是TestLocal not found (NameNotFoundException)
客户端Servlet的代码很简单:
- Java code
Context ctx = new InitialContext();Object o = ctx.lookup("ejb/TestLocal");……执行到第二句已经出错,后面的什么create()早就免谈。
网上搜到无数解决方案,对我都无效。先把试过的方案先摆一摆:
1. 在war包的WEB-INF里的web.xml里,加入<ejb-local-ref>标签内容如下:
- XML code
<ejb-local-ref> <ejb-ref-name>ejb/TestLocal</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local-home>com.jeff.TestLocalHome</local-home> <local>com.jeff.TestLocal</local> <ejb-link>TestLocalEJB.jar#TestLocal</ejb-link> </ejb-local-ref>
结果,按照"ejb/TestLocal"或"TestLocal"去lookup,都一样失败。servlet和ejb在同一个ear,但不在同一个jar包里,所以<ejb-link>里才要采用引入jar的方法。
2. 看到有人说一定要在同一个包里才能用到localhome, 于是在同一个包里定义另一个stateless session EJB,并在其ejb-jar配置内容下加上以上同样的XML(ejb-link改成TestLocal),然后在其商业方法中尝试lookup TestLocalHome,结果同样失败。实际上我认为这种说法不过是第一步里ejb-link的一种简单化方案,两者之间没有本质区别。
3. 查找资料,发现本地接口是通过link方法实现的,与JNDI没有关系,因此上述XML应该没错。
4. 尝试servlet以外其他途径,如jsp,独立客户端,pojo调用等等,没用。
论坛不能上传附件,只好把源码/XML一一贴在这里,盼望热心人帮我测试一下,到底哪里出的问题(也许是glassfish的问题?有没有可能用weblogic或jboss试试?)。 下面的代码,尤其是xml我已经试着改过不少地方,所以,希望大家帮忙尽量亲自测试一下, 而不只是指点一些毛病。 如果能通过邮箱把通过测试的源码包发给我那就更感谢了,我的邮箱 : jeff2033333@yahoo.com.sg
分数比较少,请多担待,白读了很久CSDN今天才开始发帖,惭愧。
TestLocalHome:
- Java code
package com.jeff;import javax.ejb.CreateException;import javax.ejb.EJBLocalHome;public interface TestLocalHome extends EJBLocalHome { public TestLocal create() throws CreateException;}TestLocal:
- Java code
package com.jeff;import javax.ejb.EJBLocalObject;public interface TestLocal extends EJBLocalObject { public int get6();}TestBean:
- Java code
package com.jeff;import java.rmi.RemoteException;import javax.ejb.EJBException;import javax.ejb.SessionBean;import javax.ejb.SessionContext;public class TestBean implements SessionBean { public TestBean() { } public void ejbActivate() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws EJBException, RemoteException { } public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException { } //business methods; public int get6() { return 6; }}ejb-jar.xml:
- XML code
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"><ejb-jar> <enterprise-beans> <session> <ejb-name>TestLocal</ejb-name> <local-home>com.jeff.TestLocalHome</local-home> <local>com.jeff.TestLocal</local> <ejb-class>com.jeff.TestBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans></ejb-jar>
sun-ejb-jar.xml:
- XML code
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sun-ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Application Server 8.1 EJB 2.1//EN' 'http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-1.dtd'> <sun-ejb-jar> <enterprise-beans> <ejb> <ejb-name>TestLocal</ejb-name> <jndi-name>ejb/TestLocal</jndi-name> </ejb> </enterprise-beans></sun-ejb-jar>
DoTest(Servlet, 访问时加参数 ?remote=true或false,可以看到remote=true时正确地返回值6):
- Java code
package com.jeff;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.rmi.PortableRemoteObject;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DoTest extends HttpServlet { public DoTest() { super(); } public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { TestHome home1; TestLocalHome home2; Test test1; TestLocal test2; String jndiName = "ejb/Test"; String localLookupName = "ejb/TestLocal"; try { Context ctx = new InitialContext(); if ("true".equals(request.getParameter("remote"))) { home1 = (TestHome)PortableRemoteObject.narrow(ctx.lookup(jndiName), TestHome.class); test1 = home1.create(); System.out.println(test1.get6()); } else { Object o = ctx.lookup(localLookupName); home2 = (TestLocalHome) o; test2 = home2.create(); System.out.println(test2.get6()); } } catch (Exception e) { e.printStackTrace(); } } public void init() throws ServletException { // Put your code here }}web.xml:
- XML code
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.4" 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/web-app_2_4.xsd"> <servlet> <description>DotestServlet</description> <display-name>DotestServlet</display-name> <servlet-name>DoTest</servlet-name> <servlet-class>com.jeff.DoTest</servlet-class> </servlet> <servlet-mapping> <servlet-name>DoTest</servlet-name> <url-pattern>/servlet/DoTest</url-pattern> </servlet-mapping> <ejb-local-ref> <ejb-ref-name>ejb/TestLocal</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local-home>com.jeff.TestLocalHome</local-home> <local>com.jeff.TestLocal</local> <ejb-link>TestLocalEJB.jar#TestLocal</ejb-link> </ejb-local-ref></web-app>
[解决办法]
TestLocal not found (NameNotFoundException)
JNDI名字没找到
配置文件一般都是自动生成的,不会有错,看看JNDI名字有没搞错
或者源文件发我邮箱ming_303@126.com,我跑跑看,这上面贴太多看的我眼花