Java Development News:

New Features in EJB 3.1 - Part 5

By Reza Rahman

01 Oct 2008 | TheServerSide.com

This series of articles is a preview of the changes the EJB 3.1 expert group is working on for the next version of the Java EE specification. The idea is to give you a heads up on the changes as well as gather your feedback early so the expert group has the best chance of getting it right. EJB 3.0 brought simplicity to Java EE 5 by moving away from a heavyweight programming model. EJB 3.1 aims to build on those successes by moving further down the path of simplicity as well as adding a handful of much-needed features.

In the first four articles of this series, I covered optional interfaces for Session Beans, Singleton Beans, EJB Timer Service enhancements, simplified packaging, asynchronous Session Bean invocation, EJB Lite and WebBeans/EJB 3.1 integration. In this last article of the series, I will talk about standardized global JNDI names for Session Beans and EJB 3.1 Embeddable Containers for Java SE environments. Remember, none of this has been finalized yet. All of this is really just a peek into the inner workings of the JCP so that you have a chance to provide feedback.

Standardized Global JNDI Names

As you might already know, all Session Beans are automatically registered with a JNDI context. Whether through dependency injection or lookup, clients get references to beans from the JNDI context. The name under which a bean is registered with the container’s JNDI context is commonly referred to as the “global JNDI name”. Historically application server vendors have had a great deal of latitude in what JNDI name they automatically assign to a Session Bean.

This means that any code that depends on vendor assigned JNDI names is not portable. This is not an issue while using EJB 3.0 style dependency injection because the container is responsible for resolving the dependency metadata in a @EJB annotation to a JNDI name. The problem is that it is not always possible to use dependency injection. For example, you must use direct JNDI context look-up in non-managed objects such as JSPs and simple unit tests (a very interesting case I ran across recently is getting reference to a Session Bean from a JPA Entity).

Let’s take a quick look at code to clarify the problem. Here is a Session Bean example from EJB 3 in Action:

@Remote
public interface PlaceBid {
    void addBid(Bid bid);
}

@Stateless(name="PlaceBid")
public class PlaceBidBean implements PlaceBid {
    @PersistenceContext
    private EntityManager entityManager;

    public void addBid(Bid bid) {
        entityManager.persist(bid);
    }
}

Let’s assume that the global JNDI name that the container assigns the PlaceBidBean is “chapter2/PlaceBid/remote". The “chapter2” part could be the Java EE application name; the “PlaceBid” part could be derived from the name attribute of the @Stateless annotation; while the “remote” part could denote the @Remote interface implemented by PlaceBidBean. Here is a Servlet using the Session Bean:

public class PlaceBidServlet extends HttpServlet {
    @EJB(beanName="PlaceBid")
    private PlaceBid placeBid;

    public void doGet(
        HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
        ...
        placeBid.addBid(bid);
        ...
    }
}

The container automatically resolves the @EJB annotation to the PlaceBidBean JNDI name using the beanName attribute that matches the @Stateless name attribute as well as the PlaceBid remote interface class annotated by @EJB and implemented by PlaceBidBean. While this is perfectly portable code using DI, the following simple unit test is not because it depends on the vendor-specific global JNDI name:

public class PlaceBidClient {
    public static void main(String[] args) throws Exception {
        Context context = new InitialContext();
   PlaceBid placeBid = (PlaceBid)  
            context.lookup("chapter2/PlaceBid/remote"); // Non-portable
   placeBid.addBid(new Bid("rrahman", 10059, 200.50));
    }
}

All code written to a vendor-specific JNDI name like the above will break as soon as we move from one application server to another. This can be very troublesome if you use one application server for development and another for production like many of the Java EE development shops that use traditional commercial vendors. To make matters worse, most vendor global JNDI naming schemes vary wildly, making writing some kind of lookup utility to handle portability difficult. To illustrate, Table 1 shows the names that various application servers would assign to PlaceBidBean if it was packaged in an EJB-JAR named “action-bazaar-ejb” inside a Java EE application EAR named “action-bazaar” (lets assume the name attribute is not set on the @Stateless annotation since that’s what usually happens—in these cases, the bean name is defaulted to the bean class name).

JBoss global JNDI name

action-bazaar/PlaceBidBean/remote

GlassFish global JNDI name

PlaceBid

WebSphere Community Edition global JNDI name

action-bazaar-ejb/PlaceBidBean/PlaceBid

Oracle Application Server (OC4J) global JNDI name

PlaceBidBean

Table 1: Vendor-specific global JNDI names

Standardized global JNDI names solve this portability issue by specifying exactly how a JNDI name should be assigned by the container. The current thought is to make Session Bean JNDI names as explicit as possible so that it is unique across the application server. It incorporates the application name, module name, bean name and bean interface in the following pattern:

java:global[/<application-name>]/<module-name>/<bean-name>#<interface-name>

As you can see, the application name is optional in case the EJB is not deployed as part of an EAR but is simply deployed as an EJB-JAR or as part of a WAR. The module name, on the other hand, would be derived from the EJB-JAR or WAR. In this scheme, the standardized global name for PlaceBidBean would be java:global/action-bazaar/action-bazaar-ejb/PlaceBidBean#PlaceBid. Of course, you may have already noticed that the interface name is not actually needed to guarantee uniqueness in this case since PlaceBidBean just has one remote interface! Since this is a very common scenario, a short “alias” in addition to the “full name” for the bean is registered with JNDI. If the EJB has just one interface or no interfaces at all, the interface name is omitted in this standardized short alias. So a short alias that will be assigned to PlaceBidBean would be java:global/action-bazaar/action-bazaar-ejb/PlaceBidBean.

Do you think this shortened alias is useful? Are there pitfalls to this? How about the idea of standardizing the global JNDI names in general? Can you think of additional uses of the idea behind having centralized global JNDI names?

EJB 3 Embeddable Containers on Java SE

Most people immediately associate EJB with full-scale Java EE application servers like WebLogic or WebSphere. This assumption is not necessarily true. There are a number of open source embeddable EJB 3 containers that can run in non-Java EE environments such as in unit tests. The list of such embeddable containers includes OpenEJB (the EJB 3 container for Apache Geronimo and WebSphere Community Edition), EasyBeans (extracted from the JOnAS application server) and Embedded JBoss. Even GlassFish has added embedded container support recently.

This enhancement will essentially standardize embeddable EJB 3 containers that can run in any Java SE environment. The enhancement is primarily geared towards unit testing, but embeddable containers could just as easily be used for “offline” batch processing, utilizing EJB 3.1 services such as distributed transactions, messaging, scheduling or asynchronous processing in desktop applications or adding EJB 3.1 support to Servlet containers like Tomcat. Figure 1 depicts the high-level concept behind embeddable EJB 3.1 containers (note, Java SE includes the JNDI and RMI APIs that EJB 3.1 depends on).

Figure 1: EJB 3.1 Embeddable Containers Concept

From the developer’s point of view, the embeddable container is very transparent. Here is how code using an EJB 3.1 embeddable container might look like:

public class PlaceBidClient {
    public static void main(String[] args) throws Exception {
        EJBContainer container = 
            EJBContainerFactory.createEJBContainer();
        Context context = container.getContext();

   PlaceBid placeBid = (PlaceBid)  
            context.lookup("java:global/action-bazaar/PlaceBid");
   placeBid.addBid(new Bid("rrahman", 10059, 200.50));

        container.close();
    }
}

This code will start an embeddable EJB 3 container in the same JVM process as the command-line application. The EJBContainer.getContext() method provides a handle to the JNDI context of the embeddable container. Note the EJBContainer.close() method call is not strictly necessary but it is a good idea anyway. Currently, embeddable containers are only required to support EJB Lite, although most embeddable containers will likely support all EJB features (the existing non-standard ones certainly do).

What do you think about the embeddable container support enhancement? Can you think of any other use-cases besides the mentioned here? One possible feature that is closely related to embeddable containers is support for injecting EJBs into non-managed unit test classes. However, this enhancement will need to be specified at the Java EE 6 level and is difficult to achieve solely in the EJB 3.1 expert group. Do you think that would be valuable? It could make unit test code like the following possible:

@RunWith(EmbeddableEJB3Runner.class)
public class PlaceBidTest {
    @EJB
    private PlaceBid placeBid;

    @Test
    public void testAddBid() {
        placeBid.addBid(new Bid("rrahman", 10059, 200.50));
    }
}

Some Food for Thought

Casey Stengel said “Never make predictions, especially about the future.” As futile as attempts at predicting the future are, they are useful as thought experiments—so here goes. There are a number of things that I think are on the horizon for EJB as a technology beyond the EJB 3.1/Java EE 6 time-frame. I’ll briefly mention some of them here as food for thought (in fact, folks have already asked me questions on some of these):

  1. EJB 3 and Spring Integration: I believe there is tremendous potential for EJB 3 and Spring integration, just as there is tremendous potential for WebBeans/EJB 3 or Seam/EJB 3 integration. This is already possible with EJB 3.0 and Spring 2.5, particularly through EJB 3 embeddable containers. However, this type of integration can be taken to the next level by adding native EJB 3 support on top of the Spring framework/application platform itself, along the lines of the Pitchfork project initiated by BEA.
  2. JAX-RS Integration: As you might already know, JAX-RS is the new Java EE API for REST-based web services. Just as EJB has excellent support for JAX-WS (the SOAP counter-part of JAX-RS), I believe EJB should have excellent support for JAX-RS as well. Indeed, there is a chance that this might happen in the EJB 3.1 time-frame since the JBoss JAX-RS implementation, RESTeasy, already supports this and the JAX-RS reference implementation, Jersey, is in the process of building such as integration point.
  3. OSGi Interoperability: OSGi interoperability is on the horizon for EJB and Java EE. As such, I think the interoperability points are relatively clear for Java EE, in terms of treating deployable artifacts as OSGi bundles. It looks like vendors such as Sun, IBM and JBoss will pave the way through their application servers before this is finalized through the standards.
  4. EJB 3 and RIA: Unlike many other server-side component development models, EJB is agnostic of HTTP. This fact is perhaps most apparent with Stateful Session Beans as they are capable of managing state on the server-side without any reliance on client HTTP sessions. It also has a long-standing strength in supporting robust remoting, including support for transparent remote propagation of client security and transaction contexts. These attributes make EJB a great choice for RIA applications that closely resemble pure client-server architectures. Such a technology combination can be materialized very effectively though either robust EJB/RMI binding support on the RIA client or extending EJB remoting capabilities to add a highly efficient binary protocol utilizing HTTP port tunneling that is specifically designed for RIA clients. I hope to see such a scenario supported by emerging RIA technologies like JavaFX.

What are your thoughts on the above? In particular, I’d love to hear some feedback on an initiative to add native EJB 3.1 support in the Spring framework/application platform.

Your Help is Needed!

First of all, many thanks to all the folks that sent in comment and suggestions in response to this series. It is truly encouraging and I hope you will continue to be actively engaged! You can send your feedback directly to the expert group at jsr-318-comments@jcp.org. Do feel free to copy me at reza@rahmannet.net.

I also urge you to look at the EJB 3.1 public draft. Some parts of the specification can be a little dry since it is primarily geared towards folks implementing EJB 3.1. However, there is also a wealth of interesting material there that you might not find elsewhere. There may also be some features that are added which I could not cover in this series, since there are still a few months left until the specification is finalized.

Even after the specification is finalized, a great way to be heard is through feedback mechanisms like public issue trackers that many open source Java EE vendors support. As is often said in software development, the best ideas come from users!

Finally, wish all of us in the expert group good luck in producing a successful next version of the EJB specification.

That’s all folks!

References

  1. New Features in EJB 3.1, http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesinEJB3-1.
  2. New Features in EJB 3.1 - Part 2, http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31.
  3. New Features in EJB 3.1 - Part 3, http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31-3.
  4. New Features in EJB 3.1 – Part 4, http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesinEJB3-Part4.
  5. JSR 316: Java EE 6, http://jcp.org/en/jsr/detail?id=316.
  6. JSR 318: Enterprise JavaBeans 3.1, http://jcp.org/en/jsr/detail?id=318.
  7. EJB 3.1 Public Draft, http://jcp.org/aboutJava/communityprocess/pr/jsr318/index.html.
  8. OpenEJB, http://openejb.apache.org.
  9. EasyBeans, http://www.easybeans.net.
  10. Embedded JBoss, http://wiki.jboss.org/wiki/EmbeddedJBoss.
  11. Embedded GlassFish, https://embedded-glassfish.dev.java.net.
  12. Spring Pitchfork, http://www.springsource.com/pitchfork.
  13. JBoss RESTeasy EJB integration, http://wiki.jboss.org/wiki/RESTeasyEJBIntegration.