views:

3911

answers:

6

I have an EAR file with a bunch of JARs in it, and one of these JARs contains Local Session Beans (EJB3). I need to perform a JNDI lookup of these Session Beans from within an unmanaged POJO, also contained in the EAR (and in this case in the same JAR as the EJBs as well). I tried following the Glassfish EJB FAQ, but I keep on receiving a javax.naming.NameNotFoundException no matter what I try.

I am unsure of a few things. Where should I put my ejb-jar.xml (I tried the EARs META-INF as well as the JARs META-INF)? Do I need a sun-ejb-jar.xml? What exactly is ejb-link, what does it do? What could I be doing wrong (my configuration is almost identical to the one given in the FAQ for local lookups)?

I list some of the configuration I tried and the result below:

<enterprise-beans>
  <session>
    <ejb-name>ITestBean</ejb-name>
    <ejb-class>com.test.TestBean</ejb-class>
    <ejb-local-ref>
      <ejb-ref-name>ITestBean</ejb-ref-name>
      <local>com.test.ITestBean</local>
    </ejb-local-ref>
  </session>
 </enterprise-beans>

Application deploys but JNDI lookup returns null.

<enterprise-beans>
  <session>
    <ejb-name>ITestBean</ejb-name>
    <ejb-class>com.test.TestBean</ejb-class>
    <ejb-local-ref>
      <ejb-ref-name>ITestBean</ejb-ref-name>
      <local>com.test.ITestBean</local>
      <ejb-link>ITestBean</ejb-link>
    </ejb-local-ref>
  </session>
 </enterprise-beans>

Application doesn't deploy: Unable to determine local business vs. remote business designation for EJB 3.0 ref Unresolved Ejb-Ref ITestBean@jndi.

<enterprise-beans>
  <session>
    <ejb-name>ITestBean</ejb-name>
    <ejb-class>com.test.TestBean</ejb-class>
    <ejb-local-ref>
      <ejb-ref-name>ITestBean</ejb-ref-name>
      <local>com.test.ITestBean</local>
      <ejb-link>MyJar.jar#ITestBean</ejb-link>
    </ejb-local-ref>
  </session>
 </enterprise-beans>

Application doesn't deploy: Error: Unresolved : MyJar.jar#ITestBean.

<enterprise-beans>
  <session>
    <ejb-name>ITestBean</ejb-name>
    <local>com.test.ITestBean</local>
    <ejb-local-ref>
      <ejb-ref-name>ITestBean</ejb-ref-name>
    </ejb-local-ref>
  </session>
 </enterprise-beans>

Error processing EjbDescriptor

+2  A: 

ejb-jar.xml for your ejb file goes into META-INF (of the EJB-Jar, not of the ear). EJB Refs in the deployment descriptor look something like this:

<ejb-local-ref>
    <ejb-ref-name>EJBName</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <local>classname</local>
    <ejb-link>JARName.jar#EJBName</ejb-link>
</ejb-local-ref>

The lookup code looks something like:

Context c = new InitialContext();
return (EJBLocalInterface) c.lookup("java:comp/env/EJBName");

I don't believe that you will need a container specific deployment descriptor (sun-ejb-jar.xml) for this type of lookup.

jsight
Please see updates to the question.
Zecrates
+1  A: 

I think the EJB 3 Portability Issue blog post should help you.

elhoim
Yes that is a nice post... thankfully JEE6/EJB3.1 will finally fix this.
jsight
Congratulations, elhoim. It is a good ideia standard the JNDI.
Arthur Ronald F D Garcia
Thanks for the link, I saw it earlier while searching but assumed that it only applied to Remote interface, not Local interfaces like in my case. Does the same apply to Local interfaces?
Zecrates
@Ristretto: Names are indeed not standardized for local names either.
elhoim
Does this mean that I should use the fully qualified name when looking up Local beans?
Zecrates
+4  A: 

You can always also dump on System.out or in a log all the names in the InitialContext.

//Get all the names in the initial context
NamingEnumeration children = initialContext.list("");

while(children.hasMore()) {
    NameClassPair ncPair = (NameClassPair)children.next();
    System.out.print(ncPair.getName() + " (type ");
    System.out.println(ncPair.getClassName() + ")");
  }
}
elhoim
Thanks for this, it will definitely come in handy.
Zecrates
A: 

It isn't possible to perform a JNDI lookup of a bean from a POJO, unless that POJO is called (directly or indirectly) from a managed class (such as a session bean). In other words, the first example won't work while the second one will (assuming MyPOJO is the class that tries to perform a JNDI lookup):

1) UnmanagedClass1 -> UnmanagedClass2 -> UnmanagedClass3 -> MyPOJO
2) ManagedClass -> UnmanagedClass2 -> UnmanagedClass3 -> MyPOJO

Zecrates
This is not correct, you definitely can lookup an EJB from a non managed component (injection won't work, but a standard lookup certainly will).
Pascal Thivent
Hi Pascal, if you know how to get it to work, please tell me as well. None of the tests I tried were successful. Like I said in the answer, the only way I could lookup an EJB from a non managed component was if the call stack included a managed component on a higher level.
Zecrates
A: 

Hi,

I tried the sample given in the 1st answer, made the ejb-jar.xml with the same entries and tried to access an EJB from a POJO, but it gives NamingNotFoundException. I am using Java 5, EJB 3.0, Weblogic 10.3. I am hitting my head around this local interface lookup from couple of days but no success. I made the ejb-reference entry in web.xml and able to lookup the local ejb in the web context, but when i try to lookup the ejb in the ejb context it fails. Please let me know what else i can try to make it working.

sachin
A: 

Hi,

I have working on glassfish v2 and calling JSNI from EJB3 I need only ejb-jar.xml no sun-ejb-jar.xml

http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">

         <enterprise-beans>

             <session>
                 <ejb-name>TestBean1</ejb-name>
                 <ejb-local-ref>
                    <ejb-ref-name>ejb/TestLocal</ejb-ref-name>
                    <ejb-ref-type>Session</ejb-ref-type>
                    <local>com.clients.TestLocal</local>
                    <mapped-name>ejb/TestLocal</mapped-name>
                </ejb-local-ref>
                 <ejb-local-ref>
                    <ejb-ref-name>ejb/Test2Local</ejb-ref-name>
                    <ejb-ref-type>Session</ejb-ref-type>
                    <local>com.clients.Test2Local</local>
                    <mapped-name>ejb/Test2Local</mapped-name>
                </ejb-local-ref>
              <session>
        <enterprise-beans>

@Stateless(mappedName="ejb/TestLocal") public class TestBean1 implements TestLocal

@Stateless(mappedName="ejb/Test2Local") public class TestBean2 implements Test2Local

calling service locator inside TestBean1 as ic.lookup("java:comp/env/ejb/Test2Local"); will return Test2Bean

velabhai