Enterprise Java Development@TOPIC@
In this section we will remove the specification of the JNDI lookups from the EJB bean class and perform injections indirectly through the JNDI ENC context populated by one of the XML deployment descriptors. We will again...
Inject Value Resources
Inject Persistence Context
Inject Administered Resources
We will primarily be working with the following files
src/test/java/.../ENCAuditorIT.java
src/main/java/.../ENCAuditorEJB.java
src/main/resources/META-INF/ejb-jar.xml
src/ |-- main | |-- java | | `-- org | | `-- myorg | | `-- encconfig | | `-- ejb | | `-- ENCAuditorEJB.java | `-- resources | `-- META-INF | `-- ejb-jar.xml `-- test |-- java | `-- org | `-- myorg | `-- encconfig | `-- auditor | `-- ejb | `-- it | `-- ENCAuditorEJBIT.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 ENCAuditorEJBIT
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 11: activate this testcase
@Ignore
public class ENCAuditorEJBIT 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 the value
from the JNDI ENC placed there by the META-INF/ejb-jar.xml
<session>
<ejb-name>ENCAuditorEJB</ejb-name>
<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>
</env-entry>
...
</session>
Follow that up by injecting the the ENC name into the publishJMS
property in the ENCAuditorEJB
. We would have encountered
a deployment error if this was not defined first.
@Stateless
public class ENCAuditorEJB extends AuditorBase
...
//TODO enc-config 12: define a resource value ENC injection
//@Resource(name="val/publishJMS")
private Boolean publishJMS;
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 the persistence
context from the JNDI ENC placed there by the META-INF/ejb-jar.xml
<persistence-context-ref>
<persistence-context-ref-name>jpa/em</persistence-context-ref-name>
<persistence-unit-name>encconfig-lab</persistence-unit-name>
</persistence-context-ref>
The value is injected within ENCAuditorEJB
using the @javax.persistence.PersistenceContext
annotation
@Stateless
public class ENCAuditorEJB extends AuditorBase
...
//TODO enc-config 13: define a persistence context ENC injection
//@PersistenceContext(name="jpa/em")
private EntityManager em;
Notice how the EJB class now knows less about the specific name of the persistence unit and simply accepts whatever is assigned to the logical name in the ENC. Now that we have this information in an XML file -- this opens up the possibility to change this assignment at build time through the manipulation of the XML file during the resource copy.
In the previous chapter we injected a PersistenceContext using its direct persistence unit name ("encconfig-lab"). In this case we are using an indirect ENC name ("jpa/em") and leaving it up to the assembler to register the appropriate persistence unit at that location.
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 the JMS topic
from the JNDI ENC placed there by the META-INF/ejb-jar.xml
<resource-env-ref>
<resource-env-ref-name>jms/topic</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
<lookup-name>java:/topic/test</lookup-name>
</resource-env-ref>
This element uses a resource-env-ref since it is a value and not an object the container will communicate with.
The assembler of this application is assigning a server-specific JNDI name ("java:/topic/test") to a logical ENC name ("jms/topic") the EJB will depend upon.
The value is injected within ENCAuditorEJB
using the @javax.annotation.Resource
annotation
@Stateless
public class ENCAuditorEJB extends AuditorBase
...
//TODO enc-config 14: define a resource-env ENC injection
//@Resource(name="jms/topic")
private Topic topic;
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 the JMS connection
factory from the JNDI ENC placed there by the META-INF/ejb-jar.xml
<resource-ref>
<res-ref-name>jms/cf</res-ref-name>
<res-type>javax.jms.ConnectionFactory</res-type>
<lookup-name>java:/JmsXA</lookup-name>
</resource-ref>
This element uses a resource-ref since it is an object the container will communicate with.
The value is injected within ENCAuditorEJB
using the @javax.annotation.Resource
annotation
@Stateless
public class ENCAuditorEJB extends AuditorBase
...
//TODO enc-config 15: define a resource ENC injection
//@Resource(name="jms/cf")
private ConnectionFactory cf;
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 last issue by activating the EJB's
@PostConstruct method so that it gets called after the resources
have been injected. The method is activated within ENCAuditorEJB
using the @javax.annotation.PostConstruct
annotation
@Stateless
public class ENCAuditorEJB extends AuditorBase
...
//TODO enc-config 16: activate this method after injection
//@PostConstruct
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 associated with this test case should now be passing.
You have finished injecting resources into your EJB bean using resources
populated in the JNDI ENC using the META-INF/ejb-jar.xml
.
In this chapter you successfully injected a value, persistence context, and administered resources into the EJB using the JNDI ENC. This technique allowed the actual JNDI names be abstracted away from the Java class and moved into an XML deployment descriptor where it can either be defined or form an override for the value in the Java class. Next we will take a look at a more programmatic way to access the JNDI ENC values that can make them available to any class within the EJB bean's scope.