How to inject EJB by parent interface?

1.1k views Asked by At

I`m developing a simple JEE application and tryng to choose @Local interface implementation while buildin the ear. I have interfaces` hierarchy: ParentLocal, ChildALocal, ChildBLocal and corresponding implementations: ChildABean, ChildBBean. I can choose the ChildALocal/ChildBLocal implementation of ParentLocal using annotation. How can I do the same thing using ejb-jar.xml?
ParentLocal.java

@Local
public interface ParentLocal {
    public String getName();
}

ChildALocal.java

@Local
public interface ChildALocal extends ParentLocal {
}

ChildBLocal.java

@Local
public interface ChildBLocal extends ParentLocal {
}

ChildABean.java

@Stateless
public class ChildABean implements ChildALocal {
    @Override
    public String getName() {
        return "ChildA";
    }
}

ChildBBean.java

@Stateless
public class ChildBBean implements ChildBLocal {
    @Override
    public String getName() {
        return "ChildB";
    }
}

ManagerBean.java

@Stateless
public class ManagerBean implements ManagerLocal {
    /**works fine, servlet prints "ChildA", so I would like to get the same result using DD
    @EJB(beanInterface = my.package.model.ChildALocal.class)
    ParentLocal annotatedChildBean;*/

    /**doesn`t work!*/
    @EJB
    ParentLocal childBeanUsingDeploymentDesrciptor;

    //....
}

resources/META-INF/ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar>
    <description>IBM WAS test application </description>
    <display-name>Test Manager</display-name>
    <enterprise-beans>
        <session>
            <ejb-local-ref>
                <ejb-ref-name>my.package.manager.ManagerBean/childBeanUsingDeploymentDesrciptor</ejb-ref-name>
                <local>my.package.model.ParentLocal</local>
                //doesn`t work
                <!--<local>my.package.model.ChildBLocal</local>--> 
                //doesn`t work
                <ejb-link>ChildBBean</ejb-link> 
            </ejb-local-ref>
        </session>
    </enterprise-beans>
</ejb-jar>

resources/META-INF/ibm-ejb-jar-bnd.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd" version="1.0">
    <session name="ManagerBean">
        //doesn`t work
        <ejb-ref name="my.package.manager.ManagerBean/childBeanUsingDeploymentDesrciptor" binding-name="ejb/session/ChildBBean"/> 
    </session>
</ejb-jar-bnd>

In WebServlet I inject ManagerBean and call it`s method to print the inner bean name
MainServlet.java

@WebServlet(urlPatterns = "/my_app")
public class MainServlet extends HttpServlet {
    @EJB
    ManagerLocal elementMngr;
    //...
    String childName = elementMngr.getChildNameUsedDeploymentDescriptor();
}

All my child implementations are in the separate modules which I put into the ear. IBM WebSpehere 8.5.5 shows me the following error when I try to start a servlet:

Error 500: javax.ejb.EJBException: The EJB reference in the war-main-servlet.war module of 
the earManager application could not be resolved; nested exception is: 
com.ibm.ejs.container.EJBNotFoundException: EJB with interface my.package.model.ChildBLocal 
not present in application earManager.

UPD

Error 500: javax.ejb.EJBException: The EJB reference in the war-main-servlet.war module of 
    the earManager application could not be resolved; nested exception is: 
    com.ibm.ejs.container.EJBNotFoundException: EJB with interface my.package.model.ParentLocal
    not present in application earManager.

How does the attribute beanInterface duplicated in ejb-jar.xml or(and) ibm-ejb-jar-bnd.xml?

1

There are 1 answers

3
Tracy On

The DD equivalent of beanInterface is <local> (or <remote>) and the equivalent of beanName is <ejb-link>.

The problem with this example appears to be that the <session> element in the ejb-jar.xml has nothing to tie it to the specific EJB. XML elements are considered an override of annotations when the EJB names match. Since @Stateless does not contain a name, the default will be ManagerBean, and thus the XML should contain:

<enterprise-beans>
    <session>
        <ejb-name>ManagerBean</ejb-name>
        <ejb-local-ref>
            <ejb-ref-name>my.package.manager.ManagerBean/childBeanUsingDeploymentDesrciptor</ejb-ref-name>
                <local>my.package.model.ChildBLocal</local> 
            </ejb-local-ref>
        </session>

<ejb-name>

Or, instead of <local> you may use <ejb-link>ChildBBean</ejb-link>.

Since all of the beans are in the same application, an ibm-ejb-jar-bnd.xml file is not needed. However, if you do want to use a binding file, the syntax specified here seems correct, so perhaps the binding-name value is incorrect. There would need to be another ibm-ejb-jar-bnd.xml file that configure the ChildBBean to be bound to the same location.