EJB reference resolvers

Purpose of this document:

 

This wiki briefly explains the EJB reference resolvers in the JBoss EJB3 project.

 

Background

 

Assuming a @EJB has to injected into a component or a component has a ejb-ref, this reference needs to be resolved to a JNDI name. The JNDI name can then be used by various service providers (like EJB containers, Weld or any other framework which does the injection) to lookup the proxy of the reference EJB.

 

A short example:

 

@Stateless
public class A
{ 

     // local business interface view of B bean
     @EJB
     private BLocal otherBeanLocal;
     
     // remote business interface view of B bean
     @EJB
     private BRemote otherBeanRemote;
     
     // no-interface view of B bean
     @EJB
     private B nointerfaceViewOfSomeOtherBean;
     
     ....
}

 

 

@Stateless
@LocalBean
@Local(BLocal.class)
@Remote (BRemote.class)
public class B 
{ 

     
     ....
}

 

 

As can be seen above, the "A" SLSB is being injected with various different views of "B" bean. Each of these @EJB will internally have to be resolved, by containers, to a jndi-name to inject the appropriate proxies.

 

Details:

 

Each of the @EJB, above, can be represented as a EjbReference. The EjbReference can then be passed to a EjbReferenceResovler to resolve the jndi-name. The EjbReferenceResolver has one simple method:

 

package org.jboss.ejb3.ejbref.resolver.spi;

import org.jboss.deployers.structure.spi.DeploymentUnit;

/**
* EjbReferenceResolver
*
* @author ALR* @version $Revision: $
*/
public interface EjbReferenceResolver
{

   // --------------------------------------------------------------------------------||
   // Contracts ----------------------------------------------------------------------||
   // --------------------------------------------------------------------------------||

   /**
     * Returns the JNDI Name of the proxy described by the specified
     * arguments.
     *
     * @param du The DeploymentUnit in question
     * @param reference The EJB reference used
     * @throws UnresolvableReferenceException If the reference cannot be resolved within scope
     * @return
     */
   String resolveEjb(DeploymentUnit du, EjbReference reference) throws UnresolvableReferenceException;

}

 

As can be seen the "resolveEjb" method accepts the EjbReference and a org.jboss.deployers.structure.spi.DeploymentUnit. The org.jboss.deployers.structure.spi.DeploymentUnit represents a deployment unit in a MC based deployment framework. Implementations ot EjbReferenceResolver can use the passed deployment unit to resolve the jndi name of the EjbReference.

 

Out-of-box implementations:

 

  • EJB 3.0:

     

     

 

The above 2 EjbReferenceResolver implementations are meant for EJB 3.0 deployments. These resolvers have no notion of EJB3.1 nointerface views (or for that matter any EJB3.1 specific semantics). As such these resolvers cannot be used to resolve the jndi-name for the EjbReference of a no-interface view of a bean. Specifically, in the previous code example, these 2 resolvers wont be able to resolve:

 

     // no-interface view of B bean
     @EJB
     private B nointerfaceViewOfSomeOtherBean;        

 

  • EJB 3.1:

     

     

 

(Even though the resolver classnames are the same, note the difference in the package names for EJB 3.0 and EJB 3.1).

 

These 2 EJB3.1 EjbReferenceResolver implementations can be used for both EJB3.0 and EJB3.1 deployments. As such these resolvers can be used to resolve even the EjbReference of no-interface views of beans. So in the previous code example, these 2 resolvers will be able to resolve the jndi-name of all those @EJB references.

 

Usage example:

 

@Stateless
public class A
{ 

     // local business interface view of B bean
     @EJB
     private BLocal otherBeanLocal;
     
     // remote business interface view of B bean
     @EJB
     private BRemote otherBeanRemote;
     
     // no-interface view of B bean
     @EJB
     private B nointerfaceViewOfSomeOtherBean;
     
     ....
}

 

 

@Stateless
@LocalBean
@Local(BLocal.class)
@Remote (BRemote.class)
public class B 
{ 

     
     ....
}

 


import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.ejb3.ejbref.resolver.ejb31.impl.FirstMatchEjbReferenceResolver;
import org.jboss.ejb3.ejbref.resolver.spi.EjbReference;
import org.jboss.ejb3.ejbref.resolver.spi.EjbReferenceResolver;

public class Usage
{

     public void resolveEjbReferenceForDeployment(DeploymentUnit du)
     {
     
          // Note, the process of getting hold of the DeploymentUnit is out of scope
          // of this article.
          
          // Let's just assume that the passed DeploymentUnit corresponds to a .jar
          // containing the A and B beans show above
          
          
          // 1. Let's first resolve the jndi-name for:
          // local business interface view of B bean
          // @EJB
          // private BLocal otherBeanLocal;
          
          // first let's create the EjbReference for the BLocal ejb reference
          EjbReference ejbRefToBLocal = new EjbReference(null, BLocal.class.getName(), null);
          
          // now let's use the (EJB3.1) FirstMatchEjbReferenceResolver to resolve the ejb reference
          EjbReferenceResolver ejbRefResolver = new FirstMatchEjbReferenceResolver();
          String jndiNameToBLocal = ejbRefResolver.resolve(du,ejbRefToBLocal);
          
          // just print out the jndi-name
          System.out.println("jndi-name for @EJB to BLocal is: " + jndiNameToBLocal);
          
          
          // 2. Let's now resolve the jndi-name for:
          // remote business interface view of B bean
          // @EJB
          // private BRemote otherBeanRemote;          
          
          // first let's create the EjbReference for the BRemote ejb reference
          EjbReference ejbRefToBRemote = new EjbReference(null, BRemote.class.getName(), null);
          
          // Let's use the same (EJB3.1) FirstMatchEjbReferenceResolver to resolve the ejb reference
          String jndiNameToBRemote = ejbRefResolver.resolve(du,ejbRefToBRemote);
          // just print out the jndi-name
          System.out.println("jndi-name for @EJB to BRemote is: " + jndiNameToBRemote);
          
          
          // 3. Let's now resolve the jndi-name for:
          // no-interface view of B bean
          // @EJB
          // private B nointerfaceViewOfSomeOtherBean;
          
          // first let's create the EjbReference for the no-interface view of the ejb reference
          // Note that for the no-interface view, the second parameter (i.e. the beanInterfaceName) to EjbReference
          // is the fully qualified class name of the EJB implementation class
          EjbReference ejbRefToBNoInterfaceView = new EjbReference(null, B.class.getName(), null);
          
          // Let's use the same (EJB3.1) FirstMatchEjbReferenceResolver to resolve the ejb reference
          String jndiNameToBNoInterfaceView = ejbRefResolver.resolve(du,ejbRefToBNoInterfaceView);
          // just print out the jndi-name
          System.out.println("jndi-name for @EJB to B (no-interface view) is: " + jndiNameToBNoInterfaceView);
          
     }

 

Maven co-ordinates:

 

The EjbReference and EjbReferenceResolver SPI reside in org.jboss.ejb3.ejbref.resolver:ejbref-resolver-spi artifact. The EJB3.0 implementations reside in org.jboss.ejb3.ejbref.resolver:ejbref-resolver-ejb30-impl artifact. The EJB3.1 implementations reside in org.jboss.ejb3.ejbref.resolver:ejbref-resolver-ejb31-impl artifact.

 

 

Outdated references

 

Before the org.jboss.ejb3.ejbref.resolver project was created, similar EjbReference resolution resided in org.jboss.ejb3:jboss-ejb3-common artifact. The EjbReference, EjbReferenceResolver and the implementations from org.jboss.ejb3:jboss-ejb3-common are now deprecated and will not be supported in the long term. JBoss EJB3 and other projects are encouraged to use the new org.jboss.ejb3.ejbref.resolver:* artifacts.