Getting Started with JEE 6 – Creating an EJB

In the previous part we created a simple little application that comprised just a single bean and a JSF page. The page called the bean and asked for a quote which was then displayed. Under the hood though there was a lot of stuff going on and it’s best to have at least an idea of what that stuff is…

The beans.xml file causes the CDI system system to be started which then registers the QuoteBean using the @Named annotation in the Weld EL Resolver. When the page is rendered “quoteBean” is looked up in various JSF expression resolvers and is found in the Weld resolver which returns an instance. The naming of beans in this way is only necessary when using EL expressions (typically in JSF pages) there are better ways of doing general injection. The @Named annotation created a default name for the class of “quoteBean” – the default name is just the class name with a lowercase first letter. You could also specify your own name if you wanted.

Creating an EJB

What we have developed so far works well but it would be much better if we delegated the task of creating / loading quotes to an EJB and used the bean for dealing with interacting with the client / page. Creating an EJB couldn’t be simpler with EJB 3.1 all you need to do is annotate a POJO with @Stateless (or @Stateful – a topic for a later article). Create a new class called QuoteService as a peer of QuoteBean and add this code:

package example.simpleproject;

import javax.ejb.Stateless;

@Stateless
public class QuoteService {
	
	public String getQuote() {
		return "He who stops being better stops being good - Oliver Cromwell";
	}
	
}

As you can see the only thing that sets this class apart from a regular object is the annotation – note that I’ve also changed the quote so that you can see the hot deployment in action. Modify the QuoteBean class so that it looks like this:

package example.simpleproject;

import javax.inject.Inject;
import javax.inject.Named;

@Named
public class QuoteBean {
	
	@Inject
	private QuoteService quoteService;
	
	public String getQuote() {
		return quoteService.getQuote();
	}
	
}

The getQuote() method now calls the new quote service rather than providing the quotation directly and the QuoteService is injected into the bean using the @Inject annotation. This shows off two interesting things: firstly it shows off the new EJB 3.1 no-interface view and secondly it shows how CDI automatically finds the correct object to inject.

EJB 3.1 No Interface View

Prior to EJB 3.1 all EJBs had to implement a local interface if they were to be used by the locally. From a design point of view this is quite good as it separates the interface from the implementation and allows the developer to quickly switch in an alternative implementation. In reality however many applications only had a single implementation of a given interface so the interface and that wasn’t likely to ever change so the interface was essentially clutter. To get around this the EJB 3.1 specification defined a no interface view of an EJB in which all the public methods are considered to be part of the local interface. Any session bean that doesn’t implement any interfaces and doesn’t define any local or remote views is automatically given a no interface view. The main difference between using an explicit local view and a no interface view is the type of the object you get when performing an injection or JNDI lookup. With the local view you get the interface with the no  interface view you get the actual type but this shouldn’t make any difference in the real world. Obviously you shouldn’t use “new” to create EJBs even though that would be possible with a no interface view.

Injection Magic

One of the things that makes the CDI system so powerful is the fact that it understand object typing. Simply by annotating the member variable for the QuoteService with @Inject Weld was able to head off and find the correct object to inject into the QuoteBean. Since we are using class types rather than names for the injection there is no danger of accidently injecting the wrong type of object and causing a runtime train wreck in the system. In the next article I’ll look at what happens when we have more than one implementation of a particular interface and how CDI deals with that.