Dependency Injection

To facilitate test driven development, the EJB 3.0 specification allows you to use annotations to inject dependencies through annotations on fields or setter methods. Instead of complicated XML ejb-refs or resource refs, you can use the @EJB and @Resource annotations to set the value of a field or to call a setter method within your session bean with anything registered within JNDI. You can use the @EJB annotation to inject EJB references and @Resource to access datasources.

Open up ShoppingCartBean uses the Calculator stateless session EJB to do calculations. The example shows two ways to get access to the Calculator EJB. One is:

   private Calculator calculator;

When the ShoppingCartBean instance is created, the EJB container will set the calculator field using the jndiName of that particular referenced EJB.

You are not limited to injecting dependencies on fields. You can also use @EJB on a setter method. The below example from ShoppingCartBean uses the @EJB annotation to inject the reference to the Calculator session bean:

   private Calculator set;

   public void setCalculator(Calculator c)
      set = c;

The @javax.annotation.Resource annotation allows you to inject resources.

   private javax.sql.DataSource ds;

In JBoss, whenever the mappedName() attribute is specified (@Resource, @EJB), jboss will use that as the GLOBAL jndi name to look it up.

The @Resource annotation is used to inject these singletons as well.

   @Resource javax.ejb.SessionContext ctx;
   @Resource javax.ejb.TimerService timer;
   @Resource javax.ejb.UserTransaction ut;

@EJB and @Resource also create an entry within the JNDI ENC of the bean. So, the above @EJB injection will create an entry for the reference calculator bean under "java:comp.ejb3/env/ejb/calculator". Note, the ENC name SHOULD be "java:/comp/env", but the JBoss Application server is currently being refactored in this area, so an EJB3 specific namespace is being used.

Building and Running

To build and run the example, make sure you have ejb3.deployer installed in JBoss 4.0.x and have JBoss running. See the reference manual on how to install EJB 3.0.
Unix:    $ export JBOSS_HOME=<where your jboss 4.0 distribution is>
Windows: $ set JBOSS_HOME=<where your jboss 4.0 distribution is>
$ ant
$ ant run

     [java] Buying 1 memory stick
     [java] 2004-10-06 19:37:16,869 INFO org.jboss.remoting.InvokerRegistry[main] - Failed to load soap remoting transpo
rt: org/apache/axis/AxisFault
     [java] Buying another memory stick
     [java] Buying a laptop
     [java] Print cart:
     [java] 2     Memory stick
     [java] 1     Laptop
     [java] Checkout

The INFO message you can ignore. It will be fixed in later releases of JBoss 4.0.

Jar structure

EJB 3.0 beans must be packaged in a JAR file with the suffix .jar. Running the ant script above creates a JAR file within the deploy/ directory of JBoss. All that needs to be in that jar is your server-side class files. So basically just the ShoppingCartBean and the interfaces it implements. JBoss will automatically browse the JAR file to determine if any EJBs are annotated by any classes within it. THere is no precompilation step.