Archive for the ‘Web Services’ Category

Dependency Injection in JBoss 4.2: Hold Your Excitement

For the last little while I have been pushing my company to migrate our Enterprise Beans to EJB3 (most of our beans are of the 2.1 variety) and Dependency Injection (DI) has been one of the EJB3 features that I have been very excited to see getting used throughout our middle tier.

DI is a great new addition to the EJB spec which gives the ability to ‘inject’ an EJB reference in another bean simply by using the @EJB annotation:

MyBeanInterface myBeanReference;

At run-time, the container populates the field with the appropriate bean reference, thus saving the developer some manual JNDI lookup code. For a more thorough discussion of DI, check out Debu Panda’s article.

The biggest selling point for us was that EJB references can also be injected with a bean setter methods, e.g.

void setMyBean(MyBeanInterface myBean){
this.myBean = myBean;

which can make a bean easily unit-testable with the setter used to pass in a mock object during the test set up.

However when we started using DI with the latest stable version of JBoss (4.2.2) we found that DI of EJB references has limited support. Namely it is only supported for objects inside the EJB container. This means that while beans can refer to each other with the @EJB annotation, other managed objects like servlets and non-EJB web services must still use JNDI lookup to access any Enterprise Beans.

To quote from the JBoss docs:

“JBoss Application Server 4.2.2 implemented EJB3 functionality by way of an EJB MBean container running as a plugin in the JBoss Application Server. This had certain implications for application development. The EJB3 plugin injects references to an EntityManager and @EJB references from one EJB object to another. However this support is limited to the EJB3 MBean and the JAR files it manages. Any JAR files which are loaded from a WAR (such as Servlets, JSF backing beans, and so forth) do not undergo this processing”

So even though the JEE 5 specification stipulates a wider scope of the @EJB annotation, JBoss 4.2.2 doesn’t support it. In fact JBoss 4.2.2 is a ‘bridge’ version that doesn’t claim full JEE 5 compliance. And while I am grateful for the many other JEE 5 features JBoss currently does provide, I hope this post saves people out there the time and effort of trying in vain to make @EJB references work for servlets, web services or other WAR components.

Calling a stateful Web Service with JBossWS

Although Web Services are usually described as stateless and involving distributed applications exchanging one-off messages here and there, stateful web services are not that uncommon. I recently spent some time trying to invoke a stateful .Net service from JBoss (using JBossWS) and I thought I’d post the code for that here.

The .Net service required login before further methods on it are invoked. This scenario is probably quite common out there as more and more 3rd party server-side components that require authentication get exposed as web services. A web service can be made stateful by using the SOAP header to stuff state information or by setting cookies in the HTTP session. The web service I was invoking used cookies, so I will talk about that here.

The following enables cookie support on the the web service client side:

Service service = Service.create(wsdlURL, serviceQName);
ServiceInterface proxy = (ServiceInterface)service.getPort(ServiceInterface.class);
((BindingProvider)proxy).getRequestContext().put( BindingProvider.SESSION_MAINTAIN_PROPERTY, true);

However, doing this in itself IS NOT ENOUGH! Because of a bug in JBossWS, only versions of JBossWS 2.0.1 and newer have the above working correctly. JBossWS 2.0.1 was released fairly recently – the release date is listed as 17 Aug 2007. JBossWS comes with JBoss, however it is only since JBoss 4.2.2 GA that JBossWS 2.0.1 is included (older versions of JBoss have JBossWS 1.x instead).

Basically to make the above work you will need the latest versions of JBossWS or JBoss (as of the time of this writing) because versions from as recently as a few months ago won’t work.