Search code examples
jakarta-eejbossejbwebsphereweblogic

Remote EJB lookup in Websphere (and Weblogic/JBoss)


I have a EJB class that is used for searching,

@Local(ILuceneEmployeeSearchManagerLocal.class)
@Remote(ILuceneEmployeeSearchManagerRemote.class)
public class LuceneEmployeeSearchManager implements ILuceneEmployeeSearchManagerLocal, ILuceneEmployeeSearchManagerRemote{
....
}

There is another class in a WAR project in the same EAR, which accesses this,

public class EmployeeAccessor {

    private ILuceneEmployeeSearchManagerRemote searcher;

    public EmployeeMstAccessor() {

        Context ic = null;
        try {
            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY, "<WHAT_TO_PUT_HERE>");
            props.put(Context.PROVIDER_URL, "iiop://127.0.0.1:9083");
            ic = new InitialContext(props);
            this.searcher = (ILuceneEmployeeSearchManagerRemote) ic
                .lookup("<WHAT_TO_PUT_HERE?>");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    ....

}

This is working perfectly, when I was performing local lookups using JNDI. Due to some requirements, it is now necessary to deploy the EAR in multiple APs, (both in clustered and non-clustered environments). Also, the application server used will be same across APs, but not necessarily Websphere, i.e all of the APs may be using JBoss/Websphere/Weblogic.

My question is there an implementation independent way of looking up and invoking remote EJBs ? Something that will work for Websphere, Weblogic or JBoss environments (homogeneous environments).

My second question is assuming the AP servers are running Websphere (in clustered or non-clustered environment), say I want EmployeeAccessor in all of the AP servers to be using the LuceneEmployeeSearchManager EJB deployed in AP01 (ip:x.x.x.x, port:yy), how do I configure it ? Is it necessary to give the full JNDI name (including cell name and node name for websphere) ? What are the proper values for INITIAL_CONTEXT_FACTORY ? and what is the correct JNDI lookup syntax ?

Thank you for any help :)


Solution

  • You should use default InitialContext() constructor - then it is platform independent, and use ejb references - then it is location independent - you map your references during installation. So the code is independent, but mapping is platform specific, but is done outside of application. If you are using Java EE 6 compliant server you can also use injection @EJB.

    So your code could be like this:

    public EmployeeMstAccessor() {
    
            Context ic = null;
            try {
                ic = new InitialContext();
                this.searcher = (ILuceneEmployeeSearchManagerRemote) ic
                    .lookup("java:comp/env/ejb/ILuceneEmployeeSearchManagerRemoteRef");
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    

    then you will need to create ejb/ILuceneEmployeeSearchManagerRemoteRef EJB reference in web.xml of your web module and map that reference to JNDI name of your bean. It can be done during installation/configuration of the application, or in case of WebSphere via ibm-web-bnd.xml file.

    Here is sample with @EJB (this must be in servlet or JSF managedBean for Java EE 5, for Java EE 6 you may put it in any class, but you will need to enable CDI for the application):

    public class MyServlet exetends HttpServlet {
        @EJB(name="ejb/ILuceneEmployeeSearchManagerRemote")
        private ILuceneEmployeeSearchManagerRemote searcher;  // replaces lookup
    ...}
    

    again you will need to map ejb/ILuceneEmployeeSearchManagerRemote reference which is defined by @EJB annotation to the actual JNDI name.

    Regarding your second question (in case of WebSphere):

    • If the bean is located on the SAME cell, but on other server it will be in the form:

      cell/nodes/<node-name>/servers/<server-name>/<name binding location> 
      

      e.g.:

      cell/nodes/S47NLA1/servers/Server47A1/ejb/Department549/AccountProcessors/CheckingAccountReconciler 
      
    • If the bean is in external cell, then the best way, if you want to avoid providing properties (host, port, factory) in the Initial context, is to use configured bindings. Remember that for cross cell in default configuration you will have to exchange SSL certificates to make it work.

    See also: