Autowiring EJB 3.0 in Tomcat from remote JBoss

To be honest I’ve never fully understood EJB 2.x or written an application using that specification. Well, I’ve written some EJBs, but it was just following an example of different EJB in the same project. Even though we used Spring at that time nothing seemed simple and straightforward. Every time I wanted to use an EJB I had to modify several XML files to be able to inject EJB into some bean. Not funny at all.

Now that I know Spring and it’s @Autowired annotation everything seems far more usable. Even Java EE 5 has its own annotations like @EJB.

So, here’s my problem. My application is going to be used simultaneously by many users, up to several hundred at the same time. So I need to have scalable architecture. I chose EJB for the logic tier and JSF for the web tier. Of course in each of those tiers, I can use Spring for dependency injection via @Autowired. But then, what about EJB? Every place I’ve looked, people were either deployed single WAR on JBoss or Glassfish, that contained EJB and all web stuff or used sophisticated XML configurations that did all the magic with injecting EJBs. I wanted something more. I didn’t want any defining EJBs in XML, one entry per one EJB, and then, on the web side, one entry per one injection.

Well, Spring comes in handy in such situations. So, in logic tier I have annotated session bean:

@Stateless(mappedName = "sth/SessionService")
public class SessionServiceEJB implements SessionService {

All that it does is saying that this is a stateless session bean (SessionService is its remote interface) and will be mapped in JNI under the name sth/SessionService.

Then in web beans I have:

@EJB(mappedName = "sth/SessionService")
private SessionService sessionService;

Which means that sessionService should be injected with EJB mapped under the name sth/SessionService.

As web tier is put on Tomcat, which doesn’t understand @EJB annotation, I used Spring to do the magic, it understands this annotation and injects EJBs properly. But where from get those EJBs? Well, we have some really interesting features in Spring like SimpleJndiBeanFactory. So my application requires applicationContext.xml file with a bean defined something like that:

<bean id="simpleJndiBeanFactory" class="org.springframework.jndi.support.SimpleJndiBeanFactory">
  <property name="jndiEnvironment">
    <props>
      <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
      <prop key="java.naming.factory.url.pkgs">org.jboss.naming.client</prop>
      <prop key="java.naming.provider.url">jnp://localhost:1099</prop>
    </props>
  </property>
</bean>

So what does it do? First of all, this creates a new Spring I define bean factory which will be the source of our injected EJBs. Then, in jndiEnvironment I define a source where this bean factory should look for EJBs.

Primary objective completed, I can insert via Spring any EJB deployed on an application server without defining this EJB anywhere. Unfortunately, secondary objectives are not there (yet). First of all, I would like to skip this mappedName parameter, at least in the web tier. Second, as you can see above configuration requires JBoss, it’s not universal. If you want to use Glassfish, Apache Geronimo or some other application server, you’ll need to configure JNDI source by yourself. Third, there’s localhost in the address, which would certainly be wrong in a production environment. But I believe that host can be configured in a different way, although I didn’t look for any. Do you have any solutions to that?