Enterprise Java Development@TOPIC@

Chapter 58. Configuring EJB using Injected Resources from XML

58.1. Setup
58.2. Inject Resources
58.3. Summary

In this last chapter we will use a technique of injection that leaves the EJB bean class ignorant of the entire configuration process. The XML descriptor(s) will be responsible for populating the ENC and injecting the value from the ENC into the class. This technique permits a pure POJO class to be converted to a Session EJB without prior knowledge of EJB. For example, you can easily turn a POJO Data Access Object (DAO) into a Stateless Session EJB.

The first thing to notice is that our EJB starts out as a pure POJO.

public class XMLInjectAuditorEJB extends AuditorBase 

    implements AuditorRemote {
...    
    public void init() {
...

It is assigned EJB properties through elements in the META-INF/ejb-jar.xml. The is the "old school" way of identifying EJBs prior to @Annotations.


<session>
    <ejb-name>XMLInjectAuditorEJB</ejb-name>
    <business-remote>org.myorg.encconfig.ejb.AuditorRemote</business-remote>
    <ejb-class>org.myorg.encconfig.ejb.XMLInjectAuditorEJB</ejb-class>
    <session-type>Stateless</session-type>
...

During this portion of the exercise we will also leverage the additional META-INF/jboss-ejb3.xml file. The META-INF/ejb-jar.xml file is standard JavaEE/EJB and can be used across different server implementations and different server configurations. Each individual vendor has an equivalent to META-INF/jboss-ejb3.xml and we can use this file during this exercise to host vendor-specific JNDI names for administered resources.

We will primarily be working with the following files

src/
|-- main
|   |-- java
|   |   `-- org
|   |       `-- myorg
|   |           `-- encconfig
|   |               `-- ejb
|   |                   `-- XMLInjectAuditorEJB.java
|   `-- resources
|       `-- META-INF
|           |-- ejb-jar.xml
|           `-- jboss-ejb3.xml
`-- test
    |-- java
    |   `-- org
    |       `-- myorg
    |           `-- encconfig
    |               `-- auditor
    |                   `-- ejb
    |                       `-- it
    |                           `-- XMLInjectAuditorEJBIT.java
  1. Activate the XMLAuditorEJBIT test case. Since this test case extends the same base class as the previous test case (where we activated all the test methods) all test methods will immediately become active.

    //TODO enc-config 23: activate this test case 
    
    @Ignore
    public class XMLInjectAuditorEJBIT extends AuditorCheckerITBase {
  2. Re-run the IT tests for the EJB module. The test case you just activated above will fail with several errors

    java.lang.AssertionError: publishJMS value not injected
    java.lang.AssertionError: persistence context not injected
    java.lang.AssertionError: topic not injected
    java.lang.AssertionError: connection factory not injected
    java.lang.AssertionError: EJB not properly initialized expected:<2> but was:<0>
  3. Correct the first issue by injecting a value into the publishJMS Java attribute from the META-INF/ejb-jar.xml deployment descriptor. This performs two (2) functions with the identified property.

    
    
    <!-- TODO enc-config 24: activate this injection 
    <env-entry>
        <env-entry-name>val/publishJMS</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>true</env-entry-value>
        <injection-target>
            <injection-target-class>org.myorg.encconfig.ejb.XMLInjectAuditorEJB</injection-target-class>
            <injection-target-name>publishJMS</injection-target-name>
        </injection-target>
    </env-entry>
    -->

    Since you are injecting directly into the EJB class -- no code changes need to be made to the EJB class.

  4. Re-deploy the EJB module using the maven cargo plugin

    $ mvn pre-integration-test
  5. Re-run the IT tests. The test you addressed above should now pass.

  6. Correct the first issue by injecting a persistence context into the em Java attribute from the META-INF/ejb-jar.xml deployment descriptor.

    
    
    <!-- TODO enc-config 25: activate this injection
    <persistence-context-ref>
        <persistence-context-ref-name>jpa/em</persistence-context-ref-name>
        <persistence-unit-name>encconfig-lab</persistence-unit-name>
        <injection-target>
            <injection-target-class>org.myorg.encconfig.ejb.XMLInjectAuditorEJB</injection-target-class>
            <injection-target-name>em</injection-target-name>
        </injection-target>
    </persistence-context-ref>
    -->

    The persistence unit name comes from an element in the persistence.xml within our application. We do not have to make any server-specific references for this resource.

  7. Re-deploy the EJB module using the maven cargo plugin

    $ mvn pre-integration-test
  8. Re-run the IT tests. The test you addressed above should now pass.

  9. Correct the next issue by injecting a JMS topic into the topic Java attribute from the META-INF/ejb-jar.xml deployment descriptor.

    
    
    <!-- TODO enc-config 26: activate this injection 
    <resource-env-ref>
        <resource-env-ref-name>jms/topic</resource-env-ref-name>
        <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
        <injection-target>
            <injection-target-class>org.myorg.encconfig.ejb.XMLInjectAuditorEJB</injection-target-class>
            <injection-target-name>topic</injection-target-name>
        </injection-target>
    </resource-env-ref>
    -->

    In this chapter we have moved the specification of vendor-specific and configuration-specific JNDI names for administered resources to the META-INF/jboss-ejb3.xml file. The META-INF/ejb-jar.xml file defines the injection. The META-INF/jboss-ejb3.xml file defines where to get the injected resource from.

    
    <?xml version="1.0"?>  
    <jboss:ejb-jar 
    ...
        <enterprise-beans>
            <session>
                <ejb-name>XMLInjectAuditorEJB</ejb-name>
                 ...
                <resource-env-ref>
                    <resource-env-ref-name>jms/topic</resource-env-ref-name>
                    <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
                    <jndi-name>java:/topic/test</jndi-name>
                </resource-env-ref>
            </session>
        </enterprise-beans>
    </jboss:ejb-jar>
  10. Re-deploy the EJB module using the maven cargo plugin

    $ mvn pre-integration-test
  11. Re-run the IT tests. The test you addressed above should now pass.

  12. Correct the next issue by injecting a JMS connection factory into the cf Java attribute from the META-INF/ejb-jar.xml deployment descriptor.

    
    
    <!-- TODO enc-config 27: activate this injection 
    <resource-ref>
        <res-ref-name>jms/cf</res-ref-name>
        <res-type>javax.jms.ConnectionFactory</res-type>
        <injection-target>
            <injection-target-class>org.myorg.encconfig.ejb.XMLInjectAuditorEJB</injection-target-class>
            <injection-target-name>cf</injection-target-name>
        </injection-target>
    </resource-ref>
    -->

    The source of the injection can be supplied in either a lookup element or in the META-INF/jboss-ejb3.xml file.

    
    <?xml version="1.0"?>  
    <session>
        <ejb-name>XMLInjectAuditorEJB</ejb-name>
        <resource-ref>
            <res-ref-name>jms/cf</res-ref-name>
            <res-type>javax.jms.ConnectionFactory</res-type>
            <jndi-name>java:/JmsXA</jndi-name>
        </resource-ref>
    ...
    </session>
  13. Re-deploy the EJB module using the maven cargo plugin

    $ mvn pre-integration-test
  14. Re-run the IT tests. The test you addressed above should now pass but now the audit test is still in failure mode.

  15. Correct the initialization issue by activating a callback to the class' init() method using the post-construct element of the META-INF/ejb-jar.xml.

    
    
    <!-- TODO enc-config 28: activate this injection
    <post-construct>
        <lifecycle-callback-class>org.myorg.encconfig.ejb.XMLInjectAuditorEJB</lifecycle-callback-class>
        <lifecycle-callback-method>init</lifecycle-callback-method>
    </post-construct>
    -->

    This will cause the following method to be called of our EJB class -- which will distribute the injected resources to locations within the deployment.

    <?xml version="1.0"?>  
    
        public void init() {
            super.setLog(log);
            super.setConnectionFactory(cf);
            super.setEntityManager(em);
            super.setTopic(topic);
            super.setPublishJMS(isPublishJMS());
        }
  16. Re-deploy the EJB module using the maven cargo plugin

    $ mvn pre-integration-test
  17. Re-run the IT tests. All tests within the current test case should now pass.

You have completed injecting your EJB classes with resources using XML injection.

In this chapter you successfully injected resources into your EJB class using a specification in the XML deployment descriptor files. You also specified an initialization method to be called after resources were injected so the class could complete any initialization steps that relied on those resources. The META-INF/ejb-jar.xml could have expressed the JNDI names within a lookup element. However, we chose to move that functionality to a vendor-specific META-INF/jboss-ejb3.xml file since the JNDI names were for administered resources and contain values that are specific to JBoss and this configuration of JBoss.