What's New in EJB 2.1?
The draft specification of EJB 2.1 includes Web services support as one of its major enhancements
by Tarak Modi
Technology advances can be uneven, with some functionalities leapfrogging ahead of others. Enterprise JavaBeans (EJBs) and the advent of Web services seem to be a good example of this phenomenon. Since the release of EJB 2.0, Web services and associated standards such as Simple Object Access Protocol (SOAP); Web Services Description Language (WSDL); Universal Description, Discovery, and Integration (UDDI); and Electronic Business Extensible Markup Language (ebXML); among others, have gained tremendous momentum. So it should come as no surprise that the draft specification of EJB 2.1 (which Sun released in June 2002 for public review) includes Web services support as one of its major enhancements. Other enhancements in EJB 2.1 allow you to access stateless session beans as Web services and extend message-driven bean component types to other messaging types. The new spec also includes a container-managed timer service. Let's see what these changes will mean
for you.
Web Services in EJB 2.1
It's about time that Sun added official support for Web services in the EJB specification. Most commercial application server vendors (such as BEA and IBM) have supported Web services through proprietary extensions for more than a year. For example, BEA Weblogic provides custom Ant tasks that generate and compile all the necessary code to expose the desired EJBs as Web services.
Earlier versions of the EJB spec had a standard way to expose EJBs as Web services. In EJB 2.1, stateless session beans may be exposed as Web services through what the specification calls the "Web service endpoint interface," which is a special interface defined by the Bean Provider that follows the rules shown in the sidebar "Interface Rules."
The EJB 2.1 deployment descriptor includes a new element called service-endpoint that contains the fully qualified name of the enterprise bean's Web service endpoint interface. This element is a child of the session-beanType element. Only stateless session beans can have the service-endpoint element in their deployment descriptor. The Web service endpoint is exposed only if it is referenced by a Web service deployment descriptor through the service-endpoint element. If this is done correctly during deployment, the container will generate the appropriate classes that implement the Web service endpoint interface. The specification mandates that the generated implementation must call the corresponding methods on the stateless session bean for the actual work.
The specification also states that if a stateless session bean throws an application exception from one of the methods on its Web service endpoint interface, it is the responsibility of the container to map the exception to an appropriate SOAP fault element that corresponds to the SOAP 1.1 specification. As an EJB developer, assembler, or deployer, this is all the error handling you need to support Web services.
The Web Service endpoint interface facility is available only for stateless session beans. That is, entity beans (container- and bean-managed), stateful session beans, and message-driven beans cannot be made available as Web services. In a way this makes sense because all Web services standards today are meant to support synchronous, stateless Web services, which map very nicely to stateless session beans. As we all (should) know, an entity bean should almost always have a session façade in front of it for client access (see Resources).
Both Java and non-Java clients can access stateless session beans as Web services. A client that is written in Java may access the Web service by means of the Java API for XML-based RPC (JAX-RPC) client APIs, which is part of the Java Web Service Pack release. And of course, all clients can access the Web service through SOAP 1.1 messages over HTTP(S). SOAP messages over other protocols (such as Simple Mail Transfer Protocol [SMTP]) are not yet supported, although such support is included in the SOAP 1.1 specification. To support Web service interoperability, the EJB 2.1 specification requires compliant implementations to support XML-based Web service invocations using WSDL 1.1 and SOAP 1.1 over HTTP 1.1 in conformance with the requirements of JAX-RPC.
Timer Service
Have you ever had the need for a reliable timer (one that could survive an EJB or container crash) to time events or callbacks in your EJBs? The EJB specification does not allow you to spawn a thread; otherwise you could have accomplished this fairly easily.
EJB 2.1 may have a solution for you with the timer service, which is a reliable and transactional container-provided service that allows the bean provider to register enterprise beans for timer callbacks to occur at a specified time, after a specified elapsed time, or at specified intervals. Because the service is reliable, timers survive container crashes and the activation/passivation and load/store cycles of the enterprise beans that are registered with them. I'll explain the meaning of "transactional" a little later.
The EJB container implements the timer service. The timer service is accessible through the (newly added) getTimerService() method of the EJBContext interface, which returns an object that implements the TimerService interface:
public interface javax.ejb.TimerService { public Timer createTimer( long duration, java.io.Serializable info); public Timer createTimer( long initialDuration, long intervalDuration, java.io.Serializable info); public Timer createTimer( java.util.Date expiration, java.io.Serializable info); public Timer createTimer( java.util.Date initialExpiration, long intervalDuration, java.io.Serializable info); public Collection getTimers(); }p>The interface allows the creation of different timers to support timer callbacks to occur at a specified time, after a specified elapsed time, or at specified intervals.
The bean class of an enterprise bean that uses the timer service must implement the javax.ejb.TimedObject interface. In EJB 2.1, only stateless session beans and entity beans may be registered for timer callbacks. This functionality may be extended to other bean types in a future release of the specification. The javax.ejb.TimedObject interface has a single method, the timer callback method ejbTimeout():
public interface javax.ejb.TimedObject { public void ejbTimeout( Timer timer); }
When the time specified at timer creation elapses, the container invokes the ejbTimeout() method of the bean. A bean may cancel the timer before it expires by calling the cancel method on the Timer, which is part of the Timer interface:
public interface javax.ejb.Timer { public void cancel(); public long getTimeRemaining(); public java.util.Date getNextTimeout(); public javax.ejb.TimerHandle getHandle(); public java.io.Serializable getInfo(); }
If a timer is cancelled, the ejbTimeout() method is not called.
The getHandle() method of the Timer interface returns a Serializable handle object that can be persisted. This handle implements the TimerHandle interface:
public interface javax.ejb.TimerHandle extends java.io.Serializable{ public javax.ejb.Timer getTimer(); }
Later on, the persisted handle can be "unserialized" and the timer can be retrieved by calling the getTimer() method on the handle. Because timers are local objects (an object that makes sense only in the context in which it was created), a TimerHandle must not be passed through a bean's remote interface or Web service interface.
The timer service is a transactional service, which means that:
Although the APIs of the Java 2 Standard Edition (J2SE) platform and hence the timer service APIs express timer durations in millisecond units, it is expected that most timed events will correspond to hours, days, or longer. The timer service is intended for the modeling of long-lived business processes. It is not intended for the modeling of realtime events.
Message Support
EJB 1.0 and 1.1 did not have a concept of asynchronous request processing. Java Message Service (JMS) could be used, but only for publishing messages; subscribing could be accomplished, but to do it correctly was cumbersome. EJB 2.0 introduced the much-needed message-driven bean, which is an asynchronous message consumer. The bean is invoked by the container as a result of the arrival of a message at the destination or endpoint that is serviced by the message-driven bean. A message-driven bean has neither a home nor a component interface. The EJB 2.0 specification supported only JMS message-driven beans. The EJB 2.1 specification extends the message-driven bean contracts to support other messaging types in addition to JMS. This is accomplished with the Java Connector Architecture (JCA), which is also a part of J2EE.
A message-driven bean is defined for a single messaging type, in accordance with the message listener interface it employs. For example, the message-driven bean class's implementation of the javax.jms.MessageListener interface distinguishes the message-driven bean as a JMS message-driven bean, and the message-driven bean class's implementation of the javax.xml.messaging.OnewayListener or javax.xml.messaging.ReqRespListener interface distinguishes the message-driven bean as a JAXM (Java API for XML Messaging) message-driven bean. The type of message supported by a given message-driven bean is specified in the deployment descriptor by a set of activation configuration properties. Such properties include information about message acknowledgement modes, message selectors, and expected destination or endpoint types.
A Step in the Right Direction
EJB support for Web services could not have come any later. Being able to create message-driven beans that can process messages other than JMS messages could prove to be beneficial as well, especially because this ability is built on JCA. The market for JCA-compliant adapters is already booming, and I'm sure that most of these adapters could be used either directly or adapted to use with minimal work. The timer service would be weak if it weren't reliable and transactional.
One thing still missing from the EJB 2.1 draft, though, is the ability to make asynchronous calls on EJBs such as entity and session beans. Message-driven beans provide asynchronous processing ability, but clients do not interact with a bean; they interact with an endpoint (such as a JMS Topic or Queue). It would be nice if clients could invoke a call on a regular bean either synchronously or asynchronously. For example, when a salesperson is offline (such as in an airplane), calls are asynchronous and will be replayed when the salesperson connects with the server. If the salesperson is online, the calls are synchronous without any replay required. This is possible today, but (as when developers used JMS and EJBs together before the existence of message-driven beans) the process is cumbersome and lots of custom code is required. Maybe this need will be addressed in EJB 3.0.
About the Author
Tarak Modi has been architecting scalable, high-performance, distributed applications for more than seven years and is a senior specialist with North Highland, a management and technology consulting company. He's been a hardcore C++ and Java/J2EE programmer; and he's worked with COM, MTS, COM+, and CORBA. He has written many articles and is the coauthor of Professional Java Web Services by Wrox Press. Visit his personal Web site at www.tekNirvana.com.