Looking up an EJB from a Web Service under JBoss 4.x

EJB injection in Web Services does not work with JBoss (yet), so when you want to use an EJB from your @WebService annotated POJO you have no choice but to look it up yourself.

This can get a little tricky, because each J2EE container can use its own JNDI naming convention when registering the EJB in the global naming context. Here I document how I configured JBoss to register my EJB with a name that I choose, and how I mapped a proper EJB name to that JNDI name.

Naming the EJB

Give your EJB a reasonably unique name in its annotation:

@Stateless(name=”MyServiceBean”)
@Local(SomeInterface.class)
public class ServiceBean implements SomeInterface {

}

Tell JBoss what JNDI name to register it under

Include the following in your jboss.xml file:




MyServiceBean
myapp/MyJNDIName


Tell JBoss to map an EJB name to the JNDI name

In your WAR, configure your jboss-web.xml file to include this:



ejb/MyEJBName
myapp/MyJNDIName

Lookup the EJB from your Web Service

You can now lookup the EJB directly from your Web Service:

@WebService
public class MyWebService {
private SomeInterface getMyBean() {
try {
return (SomeInterface) new InitialContext().lookup(“java:comp/env/ejb/MyEJBName”);
} catch (NamingException e) {
throw new EJBException(e);
}
}
}

Don’t unit test JavaBeans

Should unit tests cover JavaBeans just to get a higher code coverage?

These days I am working on a payment processing application that exposes its main interface as a SOAP web service. The API requires the client to build a wrapper object that packages the information needed for processing, for instance, a credit-card debit authorization: customer name and address, credit card number and so on.

I wrote the application code-first, and let the web service stack automatically generate the WSDL and other artefacts needed by the calling client software. From that WSDL and the generated XML schemas, the client can then generate the required Java supporting code to use the web service (almost) transparently.

This requires that I define those wrapper objects with a default no-args constructor, and that I define getters and setters for all its fields (the so-called JavaBean convention. Personally I dislike this kind of programming for a variety of reasons, but it was forced upon me by the web service stack.

When the time came to write unit tests, I actually had more time available than I had planned for, so I thought I should try to increase my test code coverage as much as possible. That led to several refactorings that overall helped the code’s testability, improved the test coverage, and probably improved the overall design.

But then I noticed that several of the wrapping objects’ get/setters had not been exercised by the test code. I first thought of writing unit tests for these classes, but then I realized how stupid that would be. Come one, writing unit tests for getters and setters?

A much better approach is to understand why the unit tests did not cover these methods in the first place. Upon investigating I discovered that I had not written unit tests that covered certain, very special logic branches&emdash;the very ones that needed those unexercised get/setters.

I duly wrote unit tests for these special cases, and after a few more minutes like this my test code coverage reached more than 80%, or twice what it was when I started out.

Lessons learned:

  • Write unit tests. Always.
  • Do not unit test JavaBeans. Unit test the methods that use the JavaBean methods instead.
  • Monitor your test code coverage. Tools such as Cobertura make this trivial.
  • Improve your test code coverage through relentless refactoring. Not only will your coverage improve, but so will probably your design.
Reblog this post [with Zemanta]