Enterprise Java Development@TOPIC@
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/test/java/.../JNDIAuditorIT.java
src/main/java/.../XMLAuditorEJB.java
src/main/resources/META-INF/ejb-jar.xml
src/main/resources/META-INF/jboss-ejb3.xml
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
Start JBoss. If you run JBoss within Eclipse, you may want to start it in debug mode.
Deploy the EJB module to JBoss using the maven cargo plugin
$ mvn pre-integration-test ... [INFO] --- cargo-maven2-plugin:1.4.3:redeploy (cargo-prep) @ encconfig-labex-ejb --- ... [INFO] BUILD SUCCESS
Run all IT tests within Eclipse or at the command line. They should all pass, but if you look closely -- many are still being ignored until we fix some things.
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 {
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>
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.
It registers the property at the ENC name "val/publishJMS"
It injects the property directly into the EJB class variable
<!-- 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.
Re-deploy the EJB module using the maven cargo plugin
$ mvn pre-integration-test
Re-run the IT tests. The test you addressed above should now pass.
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.
The schema ordering for ejb-jar.xml#persistence-context-ref
is not the same order we follow for the exercise. For that reason
you will find the XML elements to enact to be out of order in the
deployment descriptor.
Re-deploy the EJB module using the maven cargo plugin
$ mvn pre-integration-test
Re-run the IT tests. The test you addressed above should now pass.
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>
Re-deploy the EJB module using the maven cargo plugin
$ mvn pre-integration-test
Re-run the IT tests. The test you addressed above should now pass.
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>
Re-deploy the EJB module using the maven cargo plugin
$ mvn pre-integration-test
Re-run the IT tests. The test you addressed above should now pass but now the audit test is still in failure mode.
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());
}
Re-deploy the EJB module using the maven cargo plugin
$ mvn pre-integration-test
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.