Frank Sommers: The Enterprise JavaBeans 3.0 specification, JSR 220, is actually a set of three specifications. What are these documents, and why have three separate specifications?
Linda DeMichiel: There are three documents in the EJB specifications, but there are actually two specifications: EJB 3 core, and the Java Persistence API. When we started work on EJB 3, the Java Persistence API was at first strongly coupled with the EJB 3 specification, as it was intended to provide an ease-of-use alternative for the entity beans of EJB 2.0 and 2.1.
When we released the first early draft of the EJB 3 spec, we got considerable feedback suggesting that what we were doing with persistence in EJB 3 should have a broader scope [than entity beans]. We received feedback that that part of the spec should also be made available for persistence within other parts of the Java EE platform, such as the web tier, and that it would be useful outside Java EE containers, namely in Java SE environments.
In EJB 3.0, entity beans continue to be supported in their earlier form, but the Java Persistence API provides a POJO-based light-weight persistence technology, along the lines of other object-relational mapping technologies that had evolved in the industry. Some of those O/R technologies, and the communities around them contributed many of the ideas and constructs used in the Java Persistence API.
As the work on the specification evolved, the scope of the persistence work grew to the point where it became appropriate for it to become a separate specification document—also reflecting the fact that the persistence API was available for use outside EJB 3 containers. That explains why we have a separate Java Persistence API document, even though it is part of the Enterprise JavaBeans 3.0 release.
The EJB 3 Simplified API document is only 59 pages, and is basically a guide to the simplified EJB API. A year ago or so when I was producing the EJB Core Contracts document, the Expert Group agreed that it would be useful for developers to have a document that summarized the new simplified EJB API in a concise form so they didn't have to wade through the 500 pages of a document intended more for container implementers in order to extract information about the ease-of-use features of EJB 3.
What you find in the EJB Simplified API document is subsumed in the Core Contracts document—the "big" spec. Some of that information is redundant also because it captures functionality and annotations that originated within the scope of EJB 3, but which were adopted into the Java EE APIs. Some of the annotations for injection, for instance, were adopted into JSR 250, the Common Annotations JSR, so they could be used by other technologies. I left those in the EJB Simplified API document for convenience so that EJB developers would be able to get an overview of the new EJB 3.0 APIs more readily without having to download other specifications.
The simplified document is a good way for developers to get started learning about EJB 3, and then they can go on to the persistence [API] document, because the persistence document does not overlap with the Simplified API document.
Frank Sommers: Among the stated goals of EJB 3 was to simplify the developer's job in creating EJB applications. Could you please tell us about some of the EJB 3 features that make that possible?
Linda DeMichiel: In its genesis, the idea of EJB technology—and this predates my participation in EJB—was to provide an environment that offloaded some of what developers needed to do to develop enterprise Java applications onto the EJB container. If you think of the services the container provides—for example transaction management, security management, pooling, portable environment access—all of those were there in the original EJB work, in EJB 1.1, and some even in the 1.0 specs. But they were there in a form that was fairly awkward to use. When EJB was first introduced, it was perceived as a simplification. But we've grown more sophisticated, and learned that these APIs were rather clumsy and hard to understand.
What we tried to do with EJB 3 is to preserve all the good things about the EJB architecture for the management of applications, but make that [functionality] available in a much more easy-to-use form. In a sense, it's been more a transformation of how developers use this technology than a radical change to what the underlying services are.
We introduced new features to the API to achieve that: EJB did not have dependency injection before, for instance. Interceptors are also new to this release, which is functionality available to advanced developers. And we now use annotations to simplify functionality that had been there in a different form.
Also, in prior EJB versions, you had to program to predefined EJB interfaces, which were there more for the sake of the container than to facilitate the task of the developer. With EJB 3, we tried to offload more of that work to the container. As a result we eliminated the requirement for the home interfaces and the EJB component interfaces, and instead substituted more natural Java language constructs—business interfaces, which are just ordinary Java interfaces.
Frank Sommers: One of the things the specification no longer requires is deployment descriptors, but the EJB 3 specs still allow their use. What guidelines can you give us for deciding when to use annotations and when to use a deployment descriptor?
Linda DeMichiel: The EJB specifications don't give such guidelines, but I'll give you some of mine. Annotations are very useful for things that are semantically part of the application. As an example, consider dependencies that your application has on an environment resource. That's intrinsic to your application: If that dependency is not satisfied, then your application isn't going to run. So that's a declaration of a dependency. Dependency on another EJB with a particular interface type is another such dependency. Those dependencies will have to be satisfied in the deployment environment, but are also intrinsic to the semantics of the application.
I would argue that the transactional structure of an application is also quite intrinsic to the behavior of that application: If you're using user transactions [UserTransaction API] versus container-managed transactions, that's not something that can be changed later in the deployment cycle. That's something that would be appropriate for annotations, as are the transaction attributes.
Some other aspects of an EJB application are more amenable to later binding. An example is the exact configuration of what security roles are allowed to invoke what methods. You might want to use a deployment descriptor for that to externalize that information so that [security] might be more readily configurable per deployment environment. Except for such cases—where you would want late binding—what was [specified] in the earlier deployment descriptors is now appropriately expressed in annotations.
You would also use a deployment descriptor for default interceptors. These are interceptors that apply to all of the components in an EJB JAR. Using Java language annotations, there is currently no way to express through the annotation mechanism that an annotation applies to an application, not just to some smaller scope, such as a method or a variable or even a package. Given the absence of application-scoped metadata annotations, you'd use the deployment descriptor for that.
I want to make another point here about the use of XML with the Java Persistence API's O/R mapping configurations. Again, with Java Persistence, some annotations are expressing semantics that are intrinsic to the application: for example, relationships—what's a related entity, what is the cardinality of that relationship, or what an ID field is. These are, basically, logical-level annotations.
There is another set of annotations that are generally separate from the logical ones. These have to do with the physical mapping to a relational database, such as table and column, join column, or secondary table annotations. These are often specific to the database that is being mapped to. If you wanted your application to be deployed across different database systems with different configuration properties, you might want to externalize these O/R mapping annotations to XML. If you externalize annotations that deal with the column and table-level mapping, in particular, you could potentially define alternatives that are each tailored to a particular database system.
Frank Sommers: Is it possible in the EJB 3 APIs to mix and match annotations and external deployment descriptors?
Linda DeMichiel: Yes, it is possible in both APIs [the EJB 3 Core and the Java Persistence API]. You can use a combination of annotations and XML, and you can use XML as an overriding mechanism. You have considerable flexibility in the configuration.
For instance, you are permitted to override certain annotations in XML. That way, you could have part of your metadata in the form of annotations, and part in the form of XML and combine them in an overriding way. In addition, you can use XML as a complete alternative to annotations. By the way, it's possible also in the Java EE 5 platform in general to specify that you want only the XML to be used as definitive rather than a combination of XML and annotations.
Frank Sommers: What changes were made to the home and remote interfaces in EJB 3?
Linda DeMichiel: We simplified what in the earlier specification was called the component interface—the
EJBObject or the
EJBLocalObject interface—and we now term that a business interface. It's not an
EJBObject interface any more, just a Java interface exposed as the business interface of a component. That interface can be remote or local. By default it's local, but you can specify it as remote either by annotation of the interface or the bean class, or using XML.
In addition to not being an EJB object interface, another difference is that the business interface's methods are no longer required to throw a
RemoteException. If you [still] wanted to expose a
RemoteException, you are permitted to do that, but it is no longer required.
Frank Sommers: What are the semantics of network failure in a remote interface?
EJBExceptions are thrown. If needed, the developer can unwrap those
EJBExceptions to expose whatever the protocol-level exception was, and handle that exception in an appropriate way.
Frank Sommers: What changes were made to the home interfaces?
Linda DeMichiel: These were an interesting case. We need to distinguish between stateless and stateful session beans here. In the stateless session bean case, in the earlier EJB specs, the home interface was a placebo because it didn't really create the instance. The container was permitted to create the instance in advance, [or] to pool it and use a pooled instance when a stateless session bean was needed. Basically,
ejbCreate() did not necessarily create the stateless session bean instance.
Because this [type of] bean is stateless, there wasn't a need for a
ejbCreate() method. Instead, by simply pushing more work onto the container, the creation could be handled at the time of the business method invocation. That is, if you needed an instance [of a stateless session bean] to delegate the business invocation to, you could either create such a bean, or retrieve one from the pool. It was not necessary to maintain the home interface API to do that.
Stateful session beans are a little more interesting because the stateful session bean
ejbCreate() method in the 2.X APIs performed the useful function of initialization. When it came time to simplify stateful session beans, we wanted to simplify them in much the same way as we did [with stateless session beans]. There is no reason the initialization step could not be handled by a business method rather than a special
ejbCreate() method. By regarding initialization as part of the application API, we could eliminate the requirement for home interfaces for stateful session beans as well.
Frank Sommers: Did any of the EJB bean lifecycles change?
Linda DeMichiel: Bean lifecycles are basically the same, but lifecycle callbacks are simpler. In earlier EJB versions, a stateless session bean was required to implement the
SessionBean interface. That interface had the
ejbPassivate() methods on it, which were never used for stateless session beans. On stateless session beans, these methods were always empty, and that was just not a good situation. I always thought that stateless session beans should be unencumbered by these methods.
Again, we leveraged Java metadata annotations so developers can use annotations to specify lifecycle callback methods when, and where, such callbacks are useful. Instead of implementing to the interface, you just specify what you need. That can either be done in a method on the bean class, or you can factor that out of the bean class and place such callbacks on an interceptor class. You don't need to have such callbacks in your main-line code.
Next week, in the concluding segment of this interview, Linda DeMichiel will discuss the role of interceptors, talk about the Java Persistence API, and share her thoughts about future directions for the EJB standard.
If you'd like to receive a weekly newsletter announcing new articles at Artima.com, please subscribe to the Artima Newsletter.
The EJB 3.0 specifications, including the simplified document mentioned in this article, are available at the following URL:
Frank Sommers is a Senior Editor with Artima Developer. Prior to joining Artima, Frank wrote the Jiniology and Web services columns for JavaWorld. He is an elected member of the Jini Community's Technical Advisory Committee.