What's New in EJB 2.1

Java Development News:

What's New in EJB 2.1

By Richard Monson-Haefel

01 Jul 2002 | TheServerSide.com

Column 1: What's New in EJB 2.1
Column 2: EJB 2.1 Web Services
Column 3: EJB 2.1 Web Services (Part 2)
Column 4: EJB 2.1 The Timer Service
Column 5: EJB 2.1 Adds New Funtionality to EJB QL
Column 6: EJB 2.1 The Enhanced Message-Driven Bean

Welcome to the first installment of a new column on Enterprise JavaBeans technology I'll be writing for TheServerSide.com. Unlike my book, Enterprise JavaBeans, 3rd Edition (O'Reilly 2001), this column assumes that readers are already familiar with basic EJB concepts. Another difference: in this column I'm plan to indulge an editorial bent, so in addition to providing you with facts and objective analysis, expect me to get up on my soap box now and then. Of course you should regard opinions expressed in this column as my own, and take them with appropriate amounts of salt.
-- Richard Monson-Haefel


Introduction

Richard Monson-Haefel is the author of Enterprise JavaBeans, 3rd Edition, Java Message Service and one of the world's leading experts on Enterprise Java. He is co-founder of OpenEJB, an open source EJB container used in Apple Computer's WebObjects, and an independent consultant.

The first public draft of the Enterprise JavaBeans 2.1 specification was released on June 19th, 2002. The spec is only in draft, and not final, so remember: the specification will almost certainly change! There, I said it. Maybe everything in this article will still be correct when the spec is final, or maybe some of it will be different. It's hard to tell at this point.

The changes in EJB 2.1 focus primarily on Web services based on SOAP and WSDL. It includes two new Web services APIs (JAX-RPC and JAXM) that can be used to communicate with other Web services and allow stateless and message-driven beans to act as Web services. The bottom line is that EJB has become a Web-services platform.


In addition to its support for Web services, EJB 2.1 enhances EJB-QL, correcting many of the weaknesses I discussed in the most recent edition of my book, Enterprise JavaBeans, 3rd Edition (O'Reilly 2001). The message-driven bean (MDB) has also been improved. The MDB programming model has been extended beyond the Java Message Service to support just about any kind of messaging system. In addition, a new timer service, which allows enterprise beans to register for timed events, as well as a message-linking facility, which allow deployers to manage the flow of messages between components, have been added.

The new features introduced by EJB 2.1 are too extensive to cover in a single article, so this first installment will provide an overview of new features. In the coming months this column will describe many of these features in more detail, including Web services, the new MDB programming model, and EJB QL enhancements.


Support for Web Services

The major driving force behind EJB 2.1 is support for Web services. EJB 2.1 allows developers to expose stateless session beans and message-driven beans (MDBs) as SOAP-based Web services, making them accessible to any SOAP 1.1-compliant client. For example, using SOAP it's possible to invoke methods of a stateless session bean from other Web service platforms like Microsoft's .NET, Perl, Apache Axis, and many other languages and platforms. The new Web services facilities in EJB 2.1 provide a level of cross-platform interoperability that simply wasn't available before.

EJB 2.1's new Web-services facilities are based on two new J2EE SOAP toolkits defined by the Java Community Process (JCP), JAX-RPC and JAXM.


JAX-RPC and EJB

JAX-RPC (the Java API for XML-RPC) is essentially Java RMI over SOAP. It's similar to "native" Java RMI (Java RMI-JRMP) and Java RMI-IIOP, but uses SOAP as the protocol. A vendor's implementation of JAX-RPC must, at the very least, support RPC encoding of SOAP over HTTP, but vendors may also support other encoding styles, messaging styles, and Internet protocols. JAX-RPC can be used from session, entity, and message-driven beans to invoke operations of Web services. For example, a stateless session bean might use JAX-RPC to call a method of a .NET Web service.



Figure 1 JAX-RPC can be used to access Web Services on other platforms



JAX-RPC is also the foundation for a new component interface called the endpoint interface, which allows a stateless session bean to act as a Web service. An endpoint interface simply implements the javax.rmi.Remote interface (there is no EJB object type) and abides by the rules established in the JAX-RPC specification. Deploying a stateless session bean as a Web service is really simple: Just define the bean class and a remote interface, then use the vendor tools to deploy it. Once the Web service is deployed, its methods can be invoked by any SOAP-compliant toolkit from any language or platform: .NET, Perl, Apache Axis, C, C++, and others.



Figure 2 Any SOAP-compliant client can invoke methods of a stateless session bean Web service.




JAXM and EJB

JAXM (Java API for XML Messaging) is a SOAP messaging API analogous to JMS (Java Message Service). Just as JMS is an API for sending and receiving messages via message-oriented middleware, JAXM is an API for sending and receiving messages via Web services.

JAXM is document-oriented; it exchanges SOAP messages as XML documents. JAXM clients assemble, receive, and manipulate SOAP messages using SAAJ (SOAP with Attachments API for Java), which models the actual XML structure of a SOAP message This mechanism is very different from that of JAX-RPC, which uses method-call semantics and hides SOAP messaging behind a Java RMI proxy. With JAX-RPC you see a remote interface consisting only of methods, parameters, and return values. With JAXM, you deal with the SOAP protocol directly and assemble your own messages. Like JAX-RPC, JAXM can be used to exchange SOAP messages with any SOAP-compliant Web service. For example, an enterprise bean might use JAXM to exchange SOAP messages with a Web service written in Perl.

EJB 2.1 vendors can use JAXM as the foundation for a new kind of message-driven bean, the JAXM-based message-driven bean (JAXM-MDB). The JAXM-MDB consumes SOAP messages and acts as a Web service. A JAXM-MDB can implement a one-way interface, which makes it asynchronous, like a JMS-based message-driven bean, or it can implement a request/reply interface, which makes it a synchronous Web service. The new JAXM-MDB is possible because the message-driven bean component has now been generalized to support any kind of message system, not just JMS. The powerful capabilities that result are the subject of the next section.



Figure 3 JAXM-MDBs can be asynchronous or synchronous.



JAX-RPC and JAXM allow enterprise beans to access Web services on other platforms and serve as the foundation for Web services built with stateless and message-driven beans. These APIs are flexible and well suited for extending EJB into the Web services paradigm.


Extending Message-Driven Beans

EJB 2.0 introduced the message-driven bean, which can process asynchronous messages from JMS (Java Message Service) providers concurrently. In its design, the message-driven bean is, in my opinion, the most elegant of components and the most powerful. MDBs introduced the EJB community to the power of asynchronous messaging and changed the way many people think about server-side programming.

EJB 2.1 extends the elegant programming model of the message-driven bean beyond JMS to any messaging system. While vendors must still support JMS-based message-driven beans (JMS-MDBs), other types of messaging systems are also allowed. For example, most, if not all, vendors will support the JAXM-based message-driven bean. I can also envision other types of message-driven beans supporting SMTP for e-mail, SNMP for device control, peer-to-peer protocols, instant messaging, and many other open and proprietary messaging systems. In addition, the message-driven bean has become an elegant option for serving connections to legacy OLTP systems like CICS, IMS, openUTM, and others.

What is really exciting about the new message-driven bean component is that a component of any messaging system can be portable across EJB vendors if it's based on the new J2EE Connector Architecture (JCA 1.5), which defines a portable programming model for supporting enterprise information systems. For example, if a vendor creates a new message-driven bean component for SMTP that is based on JCA 1.5, that component will be portable across all EJB 2.1-compliant servers.



Figure 4 Message-driven beans and JCA 1.5 allows for new portable MDBs.




Destination Linking

An interesting new feature of EJB 2.1 that may not catch the spotlight is destination linking. Simply put, destination linking allows the EJB container to direct the output of a messaging service (e.g. JMS or JAMX) to a destination that is the input for another service or message-driven bean. As an example, consider a stateless session bean that uses JMS to send an asynchronous message to some destination. At deployment time, the developer can link that destination to a JMS-based message-driven bean deployed in the same container system. Destination linking allows developers to define message flow at deployment time, and thus model a workflow within an enterprise platform.


Timer Service

The Time Service is a scheduling system that is built into the EJB container. A stateless session or entity bean can register itself with the Timer Service, and request notification at a particular point in time or when a specified period of time has elapsed.

The Timer Service uses a fairly simple programming model. The stateless or entity bean must implement the TimedObject interface.

 public interface javax.ejb.TimedObject { public void ejbTimeout(Timer timer); }

When the bean's timer goes off, the container will call its ejbTimeout() method. You can put any kind of business logic you like in ejbTimeout(). For example, an entity bean that represents an invoice might have a timer that activates after 45 days. When the timer goes off, the container calls the ejbTimeout() method. The Invoice entity bean might then send a JMS message to alert an accounts-receivable application that payment is overdue, or send the customer an e-mail requesting payment.

The Timer object that is passed to ejbTimeout( ) includes features that allow you to cancel a timer, find out how much time is left before it goes off, or obtain a handle to make it persistent. In addition, when you establish a Timer object you can associate it with any serializable object, and thus store application-specific information with it. Then when the timer goes off you can access that information and use it to determine how to process the timed event.

The EJB container's Timer Service can be accessed by enterprise beans via the TimerService interface. Entity and stateless session beans must use the it to set their own timers, first gaining access to it by calling the EJBContext.getTimerService() method.


 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(); }


You already know that you can set a timer to go off once, after a certain amount of time or at a specific date. You can also set it to go off more than once, at regular intervals. For example, an Invoice entity bean's ejbCreate() method might set a timer that goes off every 30 days. A stateless or entity bean can set multiple timers, but all will be processed by the same ejbTimeout( ) method. The method can use the serializable information object to distinguish the different timers.


Enhancements to EJB QL

EJB 2.1 includes two enhancements to EJB QL, namely the addition of an ORDER BY clause and some new functions, which are welcome improvements.


ORDER BY clause

In the third edition of my book on EJB, I pointed out a few of EJB QL's shortcomings. At the top of that list was the omission of an ORDER BY clause. I'm happy to report that this failing has been corrected. EJB QL now allows the developer to specify an ORDER BY clause on EJB QL queries. For example, for an A/R application you can create a query that fetches all Invoice beans, and orders them first by date, in descending order, and then by invoice number:


 SELECT OBJECT( I ) FROM Invoice as I ORDER BY I.date DESC, I.number


This kind of query can be used with either finder or select methods of the Invoice EJB (remote or local). Notice that both identifiers in the ORDER BY clause are path expressions, which terminate in container-managed persistent fields (cmp-field). It's important to understand that the ORDER BY clause can be applied only to cmp-fields of the EJB that is selected. You can use DESC or ASC to specify descending or ascending order. (Ascending order is the default.)

You can also use the ORDER BY clause when fetching cmp-fields in select methods. For example, this query fetches the names of customers that have outstanding invoices, ordered by name:


 SELECT DISTINCT I.customer.name FROM Invoice as I WHERE I.paid = FALSE ORDER BY I.customer.name


When an EJB QL query selects a cmp-field (as opposed to an entity bean) the ORDER BY clause may be applied only to the cmp-field that appears in the SELECT clause. For example, you could not select the customer name, as above, and then order the results by the invoice EJB's creation date.


New Funtions

EJB QL adds a new function to the WHERE clause and five new functions to the SELECT clause.

In addition to the CONCAT, SUBSTRING, LOCATE, LENGTH, ABS, and SQRT functions that EJB 2.0 defined for the WHERE clause, EJB 2.1 adds a MOD function.

EJB 2.1 also makes five new aggregate functions available to the SELECT clause: AVG, COUNT, MAX, MIN, and SUM. These work like the corresponding functions in SQL-92. While AVG and SUM can be applied only to numerical types, the COUNT, MAX, and MIN functions can be applied to any cmp-field, including those of Date and String types. COUNT can also be applied to a cmr-field or EJB identifier.

For example, you can define a query that gets a count of all unpaid invoices. Notice that the COUNT function refers directly to the identifier; it doesn't use the OBJECT( ) operation:


 SELECT COUNT( I ) FROM Invoice as I WHERE I.paid = FALSE


You can also get the SUM of unpaid Invoice EJBs:


 SELECT SUM( I.total ) FROM Invoice as I WHERE I.paid = FALSE


In addition to providing useful new capabilities, EJB 2.1 closes some loopholes concerning the impact of null fields on queries, something that was not clearly defined in the EJB 2.0.


Recommended Improvements to EJB 2.1

As a member of the EJB 2.1 expert group it's been my responsibility and pleasure to review changes to the specification, point out errors, and recommend improvements to the specification before it becomes final. Every member of the expert group has his or her own agenda, and I'm no exception. EJB 2.1 already meets two of my primary objectives, support for Web services and improvements to EJB QL, but I believe that the specification can be improved in a few other areas as well. It should include support for autogenerated primary keys, extend timer support to message-driven beans, and make at least two more improvements to EJB QL.


Autogenerated Primary Keys

Since EJB 1.0 was announced I have complained, in private and in public, about the lack of support for autogenerated primary keys in container-managed persistence (CMP). Although the CMP programming model has changed twice since EJB 1.0, the specification still ignores the need for autogenerated primary keys.

When creating an entity bean, the client must provide the primary key value as a parameter of the ejbCreate() method or it must be manually generated by the developer in the ejbCreate() method. Although developers have access to several design strategies for generating primary keys (see EJB Design Patterns: Advanced Patterns, Processes, and Idioms by Floyd Marinescu, Wiley 2002), why should this burden fall on the developer rather than the EJB container?

What is most bewildering about this gaping hole is that lots of vendors already include support for autogenerated primary keys, and in most cases it's seamless and based on key-generating mechanisms supported by the underlying database. Autogeneration of primary keys is a fundamental necessity and the failure of the EJB specification to address it is simply ridiculous.

In my opinion the spec should support two types of autogenerated keys: numerical sequences for Integer and Long types, and UUIDs for String-type primary keys. Many databases already support numerical sequences, and some vendors already support them in their proprietary key-generating facilities. UUIDs are used in a variety of technologies and the algorithms for generating them are well understood. Support for UUIDs would require that the specification settle on a specific algorithm for UUIDs and mandate support for that algorithm.


The Timer MDB

The Timer Service is a handy addition to the Enterprise JavaBeans platform, but it should be extended to include timers for message-driven beans and deployment-time scheduling. Timer Service's biggest limitation now is that enterprise beans must set their own timers. This arrangement can be useful, but in many cases the developer knows the timing of an event (whether one-time or recurring) at deployment, and should have the capability to schedule it at that stage. If developers had the option to schedule timers at deployment, the timer service could support pre-configured scheduling, as Cron jobs are scheduled in UNIX.

One solution is to define a new type of message-driven bean that implements the TimedObject interface and responds to timed events that are configured at deployment time. This "timed message-driven bean" (Timer MDB) would allow application developers to schedule timed events like periodic batch jobs, audits, and other pre-configured processes. The Timer Service does not currently support pre-configuring a timed component, so a developer cannot create a timed process without activating a stateless or entity bean, by creating it or by accessing it. Consequently, application developers are obliged to write code that accesses a stateless or entity bean for no other purpose than to trigger logic that sets a timer. An unnecessary nuisance.

Note: It might have occurred to you that the setSessionContext() method of a stateless session bean offers a solution to this problem. Alas it doesn't, because some containers may not call this method until a client actually accesses the first bean of that deployment type.


EJB QL

With the addition of the ORDER BY clause, new functions, and clarifications on the handling of null values, EJB QL is more powerful than ever, but it still has some defects I would like to see addressed: We should do away with the OBJECT() operator and provide better support for the java.util.Date type. I raised these objections in the third edition of my EJB book, and summarize them here.


The OBJECT( ) Operator

The use of the OBJECT() operator is unnecessary and cumbersome, and provides little or no value to the bean developer. It's trivial for EJB vendors to determine when a return value is of an abstract schema type, so the OBJECT() operator doesn't help query translation significantly.

In addition, the rules for using OBJECT() are haphazard. It's required when the return type is an abstract schema identifier, but not when a path expression of the SELECT clause ends in a CMR field. Both return an EJB object reference, so the use of OBJECT() in one scenario and not the other is illogical and confusing.

When questioned about this in 2001, Sun replied that several vendors had requested the use of the OBJECT() operator because it will be included in the next major release of the SQL programming language. EJB QL was designed to be similar to SQL because SQL is the query language most familiar to developers, but there was never any intention to duplicate every SQL feature in EJB QL, and there is no reason to include functions and operations that have no real meaning in Enterprise JavaBeans.


Support for the Date class

EJB QL's utter lack of native support for the java.util.Date class is simply not acceptable. It should be possible, for example, to compare Date CMP fields, literals, and input parameters with the usual comparison operators (=, >, >=, <, <=, <>). It's odd that these operators can't be used with Dates, but the new MAX and MIN functions can -- why the inconsistency?

It should also be possible to introduce common date functions so that comparisons can be done at different levels, such as comparing the day of the week (DOW()), the month (MONTH()), etc. Of course, including Date as a supported type in EJB QL is not trivial and problems with interpretation of dates and locales would need to be considered, but the failure to address Date as a supported type is a significant omission.


Final Words

I have to give credit to Microsoft and IBM for leading the way in Web services. I am grateful that Sun has decided to make Web services the primary focus of J2EE 1.4. It's a big part of EJB 2.1 and I imagine that, as the entire field of Web services matures (there's lots of room for maturity!), subsequent versions of EJB will expand its role as a Web-services platform.

The new definition of timer beans was a bit of a surprise. Although scheduling is a common design problem, I would have thought that other areas such as autogenerated primary keys would have been more important. Still I'm excited about the new timer service and I do hope it expands to include message-driven beans. One vendor did express privately some concern about entity beans as timers. Because each entity identity can have its own timer the possibility of an avalanche of timer events is a bit scary. Entity beans can be prolific (account, customer, address, ...), and a misguided application could set timers in a way that resulted in literally thousands of timers going off at once, or a barrage of hundreds of timer events every second for prolonged periods. Of course, we shouldn't dumb down the design just to protect a few developers from making errors of this kind.

I was pleased to see the ORDER BY clause added to EJB QL -- at last. It's so basic to queries. How did we get along without it? Except for the few minor adjustments I already mentioned I'm pretty happy with EJB QL. There is always room for improvement but it's a pretty good feature, all things considered.


What's in Store Next Month

Next month I plan to cover EJB Web Services in more detail. In particular I'll be covering JAX-RPC and JAXM, as well as the Web service components, the stateless endpoint and the JAXM-MDB. A lot of this material will be derived from drafts of the fourth edition of my EJB book and a new book on J2EE Web Services, both of which I'm working on now.




 

copyright notice (c) Copyright 2002 Richard Monson-Haefel. All rights reserved.


PRINTER FRIENDLY VERSION

Related Resources