Comment lines: Roland Barcia: Examining the EJB 3.0 Simplified API specification

A look at the latest draft of the EJB™ 3.0 Simplified API specification, what it may offer developers, and where there is still room for improvement.

Roland Barcia (barcia@us.ibm.com), Consulting IT Specialist, IBM

Roland BarciaRoland Barcia is a Consulting IT Specialist for IBM Software Services for WebSphere in the New York/New Jersey metro area. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration.


developerWorks Master author level
        2

23 February 2005

From the IBM WebSphere Developer Technical Journal.

A couple of weeks ago, the Java™ Community Process (JCP) released an early second draft of the Enterprise JavaBeans™ (EJB) 3.0 specification under JSR 220, divided into three documents:

  • EJB 3.0 Simplified API: Defines the new simplified API used to code Enterprise JavaBean Components, specifically session beans and message-driven beans.
  • Enterprise JavaBeans Core Contracts and Requirements: Defines the EJB contracts between the Bean and the EJB container.
  • Persistence API: Defines the new Entity Bean model for persistence.

In this column, I thought I would highlight some of the features in the EJB 3.0 Simplified API, and comment a bit on where I think improvements can be made. Since I will be addressing only the Simplified API, when speaking of EJB components, I will be referring to session beans and message-driven beans, not entity beans, since persistence is not covered under the Simplified API.

The EJB specification has many goals, most of which I will not cover, but in brief: the EJB 3.0 specification is in-line with the overall goal of the J2EE™ 5.0 specification, which is to simplify the J2EE programming model. As such, this part of the specification is more along the lines of a cosmetic makeover rather than a set of functional enhancements. However, there are still a few things that the new programming model adds for developers, and I will mention these as we look at certain features.

This article assumes some knowledge of the current EJB specification.

POJO and annotations

"POJO" (Plain Old Java Objects) is a term that has been thrown around a lot lately. It refers to code written as plain Java classes. Because EJB programs make you extend specific classes, provide several interfaces, and write deployment descriptors, they are viewed as overloaded Java objects that are no longer plain. Instead, a developer needs a J2EE container to run and test them. I agree that coding POJOs without tools makes EJB development difficult. In the EJB 3.0 specification:

  • EJB components no longer require home interfaces. In addition, EJB components are no longer required to provide different interfaces or extend any specific EJB specific classes.
  • J2SE 5.0 annotations are now a major facilitator for implementing EJB 3.0 components. By specifying special annotations, developers can create POJO classes that are EJB components. The class will be run through an annotations processor and the underlying container will provide the plumbing.
  • EJB 3.0 introduces the notion of a Business Interface. An example is shown below:

    public interface Stock
    {
    	public double getQuote(String symbol);
    }

    Your Bean class can implement the interface:

    @Stateless public class StockBean implements Stock
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    @Stateless annotation, above, means that this class is now a stateless session bean, and the business interface is used to invoke it. The early draft talks about allowing the possibility for the generation of Business Interfaces from the Bean class. A Stateless Session Bean can be coded without implementing a specific interface and annotation. An example is shown below:

    @Stateless public class StockBean
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    The annotation processor will then generate the Business Interface. By default, all methods that are public and not injection methods are included in the Business Interface unless methods are specifically annotated. For example, if I specify at least one method with @BusinessMethod, then only the ones that are specified with @BusinessMethod are included in the Business Interface:

    @Stateless public class StockBean
    	@BusinessMethod public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    Now that we have one interface, how do we specify whether a method is remote or local? Of course, we can use an annotation:

    @Stateless public class StockBean
    	@Remote public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    You can annotate either the Business Interface or the Bean class itself. Enabling the annotation on the Bean class is useful when you choose to generate the Business Interface. How to specify whether or not a method should be invoked as a Web service is not mentioned in this EJB specification draft; this is instead being delegated to JSR 181, which defines annotations for Web services.


Container services

EJB components are popular because of the implicit support for transaction management and security. The EJB 3.0 specification will use annotations to apply container services. Here is an example of how you would specify a transactional attribute on a stateless session bean:

@Stateless public class StockBean
{

@TransactionAttribute(TransactionAttributeType.REQUIRESNEW)
	 public double getQuote(String symbol)
	{
		return 100.33;
	}
}

The annotation means that the method will be run in a new transaction. Read the specification for more details on specific syntax and semantics of the different annotations. Container services can also be applied using deployment descriptors, although the current draft did not show how that would be specified. However, if both are used, the deployment descriptor would override the annotation.

The final form of the specific annotations may change in future drafts. For example, certain annotations that are relevant to the J2EE specification as a whole may be factored out of EJB.


Callbacks

What about callbacks? Prior to the EJB 3.0 specification, developers had to implement callback methods such as ejbCreate() on the Bean class; Bean classes had to implement all the methods whether they used them or not. In most cases, these method implementations were empty.

Callbacks are now handled through annotations. There are two mechanisms: callback methods and callback listener classes. Here is an example of how you would write code to respond to a callback using callback methods:

@Stateless public class StockBean implements Stock
	public double getQuote(String symbol)
	{
		return 100.33;
	}

	@PostConstruct initializeCache()
	{
	}
}

The above code will now enable you to implement code after a bean instance is created. If I wanted to use a callback listener, I would create a Callback Listener class:

public class MyCallbackListener
{
	@PrePassivate public clearCache(Object obj)
	{
		Stock stock = (Stock) obj;
		//perform logic
	}
}

A callback class that is not part of the Bean class has to take in a java.lang.Object parameter. The container will then pass the bean instance. A Bean class adds the callback listener class by using a special callback annotation at the Bean class level:

@CallbackListener MyCallbackListener
@Stateless public class StockBean implements Stock
	public double getQuote(String symbol)
	{
		return 100.33;
	}
}

Callbacks are nice because the inclusion of them in your code is conditional, unlike when you implement interfaces. The same could have been accomplished by adding a special abstract class with empty callbacks. In Appendix A of the specification, there is mention of providing special base classes for developers who wish to continue using the EJB 2.x style of development.


Interceptors

A nice addition to the EJB specification is the use of interceptors. One thing that was missing from EJB components is the ability to do pre/post-processing, much like servlet filters do for servlets. A developer can develop an Interceptor class and apply it to a bean. Here is an example of an interceptor that audits invocations of the StockBean class:

public class StockRequestAudit {
	@AroundInvoke
	public Object auditStockOperation(InvocationContext inv) throws
	Exception {
		try {
			Object result = inv.proceed();
			Auditor.audit(inv.getMethod().getName(), inv.getParameters[0]);
			return result;
		} catch (Exception ex) {
			Auditor.auditFailure(ex);
			throw ex;
		}
	}
}

The Interceptor above intercepts the call to the target EJB method, then calls the proceed() method on the InvocationContext. This will enable the call to flow through to the actual EJB method that was invoked. After the target EJB method returns, it will use the metadata in the InvocationTarget to get the method name and parameters of the target EJB component that was called. The Interceptor can then be applied to the Bean class:

@Stateless @Interceptors({StockRequestAudit})
public class StockBean implements Stock
	public double getQuote(String symbol)
	{
		return 100.33;
	}
}

Additionally, you can choose to develop interceptor methods that are implemented inside the Bean class, and also specify multiple interceptors, in which case the order in which they are called is specified by the order they are defined in the Bean class.


Dependency injection

What makes EJB development testing difficult are EJB code dependencies on thing slike data sources, as well as how EJB components are invoked by EJB clients. The EJB 3.0 specification introduces dependency injection as a mechanism to alleviate these difficulties. Instead of using JNDI lookups, an EJB can define a resource reference by injecting code. Below is an example of an EJB bean that needs to call another EJB component and use a data source to do JDBC work:

@Stateless public class StockBean implements Stock
{
@EJB(name="MarketBean", businessInterface="Market")
Market market;

@Resource(name="StockDB, resourceType="javax.sql.DataSource")
DataSource stockDS

	public double getQuote(String symbol)
	{
		Connection con = stockDS.getConnection();
		//DO JDBC work

			return market.getCurrentPrice(symbol);
	}
}

Dependency injection can occur in a variety of ways, for example, via a setter method or a class variable. See the specification for more details.


Annotations or deployment descriptors?

This current early draft of the EJB 3.0 specification has empty sections marked for the use of deployment descriptors as an alternative to annotations. But is the annotation approach better? Consider the name "deployment" descriptor, which implies that it describes elements of the application relevant to deployment. I can argue that many of the elements in the current EJB deployment descriptor are development artifacts, not deployment artifacts. So what elements would be better off in deployment descriptors?

  • Elements that are likely to change when deployed, such as the mapping of a resource reference to an actual resource.
  • Elements that apply globally to a group of EJB components. Annotations do a good job of specifying elements for a specific class, but elements that apply to many beans should be described outside. For example, I may want to apply a generic security role to a set of EJB components rather than an individual EJB component. Having one place to specify this is more productive than defining an annotation on every single EJB Bean class.

Certain elements (transaction demarcation comes to mind) should be removed from deployment descriptors because they are not relevant to deployment. Allowing a deployer to override things such as transaction semantics would be quite dangerous. The JCP should keep these facts in mind for future iterations.


Conclusion

The second draft of the simplification API portion of the EJB specification is still very empty; the contracts portion of the specification is also missing from this early draft. I expect the core contracts will define things such as how a resource reference defined in an annotation will get "mapped" to an actual data source defined on an application server, what happened to the Timer Service, and so on. Without seeing the core contracts, it is difficult to comment, so we'll save that for a future review.

What should developers do today? Continue to use the current EJB specification, which will be fully supported by your J2EE application server vendor for quite some time. If you follow best practices, such as layering your application, changes can be applied with minimal effort.


Acknowledgements

Thanks to Wayne Beaton and Bobby Woolf for their suggestions for this commentary.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=48778
ArticleTitle=Comment lines: Roland Barcia: Examining the EJB 3.0 Simplified API specification
publish-date=02232005