EJB 3.0 JNDI lookup (Weblogic 10.x)

2019-07-20 14:58发布

问题:

I use weblogic 10.3.6 and so EJB 3.0. I have EJB and local interface. Both packaged in ejb-jar inside ear.

@Local
public interface TestLocal {
...
}

@Stateless
public class TestEJB implements TestLocal {
...
}

To access this EJB from war I have in my web.xml

<ejb-local-ref>
  <ejb-ref-name>ejb/TestLocal</ejb-ref-name>
  <ejb-ref-type>Session</ejb-ref-type>
  <local>testpackage.TestLocal</local>
</ejb-local-ref>  

And lookup looks like

test = (TestLocal) new InitialContext().lookup("java:comp/env/ejb/TestLocal");

Everything works fine. Now I need to call this EJB from the same ejb-jar where it packaged. But I have javax.naming.NameNotFoundException all the time. What I have already tried:

  1. In ejb-jar.xml in ejb-jar (not ear)

    <ejb-name>TestEJB</ejb-name>
    <ejb-local-ref>
      <ejb-ref-name>TestEJB</ejb-ref-name>
      <ejb-ref-type>Session</ejb-ref-type>
      <local>testpackage.TestLocal</local>
      <ejb-link>myjar.jar#TestEJB</ejb-link>
    </ejb-local-ref>
    

and following lookups

 initialContext.lookup("java:comp/env/TestEJB");
 initialContext.lookup("TestEJB");
  1. in weblogic-ejb-jar.xml

    <weblogic-enterprise-bean>
     <ejb-name>TestEJB</ejb-name>
     <jndi-name>TestEJB</jndi-name>
     <local-jndi-name>TestEJB</local-jndi-name>
     <enable-call-by-reference>True</enable-call-by-reference>
    </weblogic-enterprise-bean>
    
  2. Both weblogic-ejb-jar.xml and ejb-jar.xml

Have you any ideas of what I'm doing wrong?

回答1:

JNDI in Java EE has different namespaces. Prior to Java EE 6, there is typically only the "global" namespace and the "component environment" namespace.

Each EJB has it's own component environment. A webapp also has it's own component environment. This is what you're looking up when you use a JNDI name prefixed with java:comp/env. Objects are added to the component environment via deployment descriptors (ejb-jar.xml and web.xml):

    <ejb-name>TestEJB</ejb-name>
    <ejb-local-ref>
         <ejb-ref-name>TestEJB</ejb-ref-name>
         <ejb-ref-type>Session</ejb-ref-type>
         <local>testpackage.TestLocal</local>
         <ejb-link>myjar.jar#TestEJB</ejb-link>
    </ejb-local-ref>
    ...

So, from within the calling context of TestEJB, you would lookup the reference above:

  TestLocal testLocal = (TestLocal) new InitialContext().lookup("java:comp/env/TestEJB");

The JNDI lookup name is always java:comp/env/<ejb-ref-name>.

You can see this actually looking up another instance of itself, because that is what you have declared above. It's possible this is not what you intended.

Given the above, the answer to your question depends upon the calling context of your POJO.

If it is webapp -> POJO -> TestEJB, then you should use the webapp's component environment and lookup "java:comp/env/ejb/TestLocal".

If it is webapp -> SomeEJB -> TestEJB, then you need to add a component environment to SomeEJB (not TestEJB as you have in your example) and lookup the name that you define there.