Using Dependency Injection in Struts2 for stateless EJBs part 2

This is the second, and last part of the Using Dependency Injection in Struts2 for stateless EJBs series of posts. In this post I will present a utility class that can be used to make the creation of Guice bindings for EJB3s easier.

Introducing EjbBinder

Our goal is to make an easier API, specifically for creating bindings of EJB3s, and make the specification of the JNDI name optional, when possible. The below code is a new version of the EjbModule class that uses a new class, called EjbBinder, that we are going to present in this post.

public class EjbModule implements Module {

  public void configure(Binder binder) {
    // Bind Context to the default InitialContext.
    binder.bind(Context.class).to(InitialContext.class);

    EjbBinder ejbs = new EjbBinder(binder, new GlassfishEjbJndiNameStrategy());
    ejbs.bindRemote(CurrencyManagerRemote.class);
    ejbs.bind(DatesManagerRemote.class, "com.tzavellas.dates.ejb.DatesManagerBean");
  }
}

EjbBinder contains two methods named bind and bindRemote. The bind method receives as arguments the expected class and JNDI name and simply uses Binder and JndiItegration to create a binding. The bindRemote method takes as an argument the remote interface of a sesion EJB3 and creates a binding using a JNDI name retrieved from the EjbJndiNameStrategy, that is specified in the EjbBinder constructor (BTW the CurrencyManagerRemote EJB interface in the above code does not relate with the application that we developed in the previous post and it is here to illustrate the bindRemote method).

The definition of the EjbJndiNameStrategyinterface:

public interface EjbJndiNameStrategy {

  String interfaceToJndiName(Class<?> beanInterface);
}

The implementation of EjbBinder:

import com.google.inject.Binder;
import com.google.inject.binder.ScopedBindingBuilder;
import static com.google.inject.jndi.JndiIntegration.fromJndi;

public class EjbBinder {

  private Binder binder;
  private EjbJndiNameStrategy jndiNameStrategy;

  public EjbBinder(Binder binder, EjbJndiNameStrategy nameStrategy) {
    this.binder = binder;
    this.jndiNameStrategy = nameStrategy;
  }

  public <T> ScopedBindingBuilder bindRemote(Class<T> beanInterface) {
    return bind(beanInterface,
                jndiNameStrategy.interfaceToJndiName(beanInterface));
  }

  public <T> ScopedBindingBuilder bind(Class<T> beanInterface, String jndiName) {
    return binder.bind(beanInterface)
                 .toProvider(fromJndi(beanInterface, jndiName));
  }
}

Application Server Specific Naming Strategies

When you create a new EJB and you do not specify a JNDI name, the application server assigns a default name for you. So, if you have an implementation of EjbJndiNameStrategy that uses the naming rules of your application server you could avoid the need to specify a JNDI name when creating the EJB and when creating the binding of the EJB to Guice.

Below we have two implementations of the EjbJndiNameStrategy that can infer the JNDI name of an EJB’s remote client interface using the remote interface’s class for the Glassfish and JBoss application servers.

For the Glassfish application server the default global JNDI name of an EJB with a remote interface is the fully qualified name of the remote interface.

public class GlassfishEjbJndiNameStrategy implements EjbJndiNameStrategy {

  public String interfaceToJndiName(Class beanInterface) {
    return beanInterface.getName();
  }
}

For the JBoss application server the default JNDI name for the remote interface of an EJB is earName/beanName/remote.

//WARNING: Not tested!
public class JbossEjbJndiNameStrategy implements EjbJndiNameStrategy {

  private String earName = "";

  public JbossEjbJndiNameStrategy() { }

  public JbossEjbJndiNameStrategy(String earName) {
    if (earName != null && "".equals(earName.trim()))
      this.earName = earName + "/";
  }

  public String interfaceToJndiName(Class<?> beanInterface) {
    return earName + interfaceToBeanName(beanInterface) + "/remote";
  }

  protected String interfaceToBeanName(Class<?> beanInterface) {
    String name = beanInterface.getSimpleName();
    if (name.endsWith("Remote"))
      name = name.replace("Remote", "");
    return name + "Bean";
  }
}

Using Dependency Injection in Struts2 for stateless EJBs part 1

In this post I will present a way to use dependency injection of stateless session beans in Struts 2 actions using Guice. I will only write about EJB3, because they have simpler client lookup code, but you might be able to change the presented code to cover older versions of EJB.

We will use off the shelf Struts 2 and off the shelf Guice (with the Guice Struts 2 plug-in). No extra “glue” code is required to inject stateless EJBs into a Struts actions with Guice. In the next post I will tweak the presented code and make the binding of EJBs in Guice modules simpler.

This post is divided in two sections. In the first section we will create a simple, complete, hello-world type application using Struts 2. The application will consist of only one action that when called will print the current date in a JSP page. Then we will write a stateless session EJB and use Guice to inject the EJB into the action. If you are already familiar with Struts 2 you might want to skip the first section and go directly to the second.

A basic Struts 2.x application

Below you will find a series of steps with all code for our mini application.

1. Project setup

With your favorite IDE create an enterprise project. You need to create an enterprise project (ear based deployment) and not a web project (war based deployment) because we will create an EJB in the next section.

Now add a web module into your enterprise project and add the following jars to WEB-INF/lib: commons-logging-1.1.jar, freemarker-2.3.8.jar, ognl-2.6.11.jar, struts2-core-2.0.8.jar and xwork-2.0.3.jar.

Although I am a happy Eclipse user I have to admit that Eclipse has very basic support for Java EE 5, so for the code of this post I used Netbeans 6.0 M9 with Glassfish 2 Beta as the application server. Netbeans IMHO is not so good for Java editing but has decent support for the latest Java EE standards. Please keep in mind that the code is only tested with Glassfish 2 Beta.

2. Edit web.xml

The below code is the minimum web.xml needed for a Struts 2 application. It contains the Struts 2 filter definition (FilterDispatcher) and a welcome file (index.html) that it is used to redirect the user to the default Struts 2 action.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

3. Create struts.xml

Now we need to create the struts.xml file. This file is located at the root of your classpath. The below code has some basic configuration parameters and includes the dates Struts package that will contain our action.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
  <constant name="struts.enable.DynamicMethodInvocation" value="false" />
  <constant name="struts.devMode" value="false" />
  <!-- Include the package with our actions -->
  <include file="dates.xml"/>
</struts>

4. Create the dates Struts package

Create the dates.xml file at the root of your classpath as we specified in the above struts.xml. In this file we define a package named dates and mapped under <context-root>/dates/* URL.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
  <package name="dates" namespace="/dates" extends="struts-default">
    <action name="CurrentDate" class="com.tzavellas.dates.web.CurrentDateAction">
      <result>/WEB-INF/jsp/date.jsp</result>
    </action>
    <!-- Add more actions here -->
  </package>
</struts>

The package contains our only action, named CurrentDate and mapped to the URL <context-root>/dates/CurrentDate.action.

5. Create the welcome file

Now we will create our welcome file that redirects the user to the Struts action. This is a simple HTML page named index.html (as defined in web.xml) and located under the context root. The page uses a meta tag to redirect to the URL of the action .

<html>
  <head>
    <meta http-equiv="Refresh" content="0;URL=dates/CurrentDate.action">
  </head>
  <body>
    <p>Loading ...</p>
  </body>
</html>

6. Code the action

Finally it’s time for some Java code. The below code is a simple Struts 2 action that when called will set the value of the currentDate property to the current date.

package com.tzavellas.dates.web;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;

public class CurrentDateAction extends ActionSupport {

  private Date currentDate;

  @Override
  public String execute() throws Exception {
    currentDate = new Date();
    return SUCCESS;
  }

  public Date getCurrentDate() {
    return currentDate;
  }
}

Note that unlike Servlets or Struts 1 actions, in Struts 2 for every HTTP request a new action instance is created so it is safe to mutate an action property (like the currentDate above) with request specific data.

7. Create the view

As we defined in the dates package (dates.xml) the view for the CurrentDateAction is a JSP file localed in WEB-INF/jsp/date.jsp. The below code, for the date.jsp page, uses the Struts 2 tag library to display the value of the currentDate property of the action.

<%@ page contentType="text/html" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>The current date</title>
  </head>
  <body>
    <h1>The current date is: <s:property value="currentDate"/></h1>
  </body>
</html>

We’ve just created a simple application with Struts 2. In the next section we are going to define a stateless session EJB3 and wire it with the above action using Guice.

For more information about the Struts 2 web framework visit the Struts 2 wiki pages.

The EJB and the integration with Guice

8. Create the stateless session EJB3

With your favorite IDE add an EJB module to the enterprise project we created in step 1.

Below we define the SLSB with a remote interface and one method that returns the current date. The bean is mapped to the global JNDI name com.tzavellas.dates.ejb.DatesManagerBean.

package com.tzavellas.dates.ejb;
import java.util.Date;
import javax.ejb.Stateless;

@Stateless(mappedName="com.tzavellas.dates.ejb.DatesManagerBean")
public class DatesManagerBean implements DatesManagerRemote {

  public Date currentDate() {
    return new Date();
  }
}
package com.tzavellas.dates.ejb;
import java.util.Date;
import javax.ejb.Remote;

@Remote
public interface DatesManagerRemote {
  Date currentDate();
}

9. Add the Guice jars in the classpath

Add guice-1.0.jar and guice-struts2-plugin-1.0.1.jar in WEB-INF/lib directory of your web module. The jar file guice-1.0.jar contains the core Guice implementation and the guice-struts2-plugin-1.0.1.jar file contains the Guice’s Struts 2 integration code.

10. Edit struts.xml to include the Guice plug-in

Struts 2 is a very flexible framework. One of Struts’ many extensions is the ObjectFactory plug-in interface. The responsibility of an ObjectFactory is to create the objects managed by Struts. An ObjectFactory is usually a dependency injection container like Spring, Pico and Guice.

To define Guice as the ObjectFactory of our Struts 2 application we have to set the struts.objectFactory property to guice in the struts.xml file and Guice will then be responsible for instantiating all the Struts managed objects (actions, interceptors, etc) .

To continue add the following lines in struts.xml.

<!-- Use Guice as the ObjectFactory for this application -->
<constant name="struts.objectFactory" value="guice" />
<!-- When wiring actions use Guice bindings defined in the below module -->
<constant name="guice.module" value="com.tzavellas.dates.web.EjbModule"/>

11. Code the EjbModule

In the above struts.xml we defined two properties, struts.objectFactory and guice.module. To explain the guice.module property and the concept of Guice modules we have to explain the basics of Guice.

Guice is a, Java 5 based, dependency injection container that does constructor, field and setter injection (Guice also has features like support for AOP Alliance interceptors that we are not going to talk about in this post). To configure Guice you create a set of modules. A module implements the com.google.inject.Module interface and contains bindings. Bindings are created with the com.google.inject.Binder that is passed to the configure(Binder) method of a module. A binding is a pair composed of a type (key) and an implementation. An implementation can be an object, a class or a provider (factory). The bindings are consulted by the Guice Injector when doing dependency injection.

In the Guice Struts 2 plug-in the Guice ObjectFactory creates an Injector that then reads the module from the guice.module property in the struts.xml file and uses the bindings that are specified in that module to do dependency injection in Struts 2 actions and interceptors.

All we have to do to enable our EJB to be injected into an action is to create a binding for the client interface of the bean. We can’t create a binding to a class or instance, because the EJB’s instances must be instantiated by the EJB container and not by Guice, so we will use a provider that will lookup the EJB from JNDI. The Guice library includes a JNDI provider that we are going to use that it is located in the com.google.inject.jndi.JndiIntegration class.

The below code is the implementation of the EJBModule, which has only two bindings. The first binds the javax.naming.Context type to the javax.naming.InitialContext implementation. This means that when the Guice Injector finds a field or parameter of type javax.naming.Context, that needs to be injected (marked with the @Inject annotation), it will create a new object of type javax.naming.InitialContext and inject it. This binding is needed by the JNDI provider that we are going to use in the next binding.

The second binding binds our EJB’s remote interface to the JNDI provider. The JNDI provider is returned from the call to the static JndiIntegration.fromJndi(Class, String) method. To get a JNDI provider we have to specify the expected class and JNDI name. This binding tells the Guice Injector that when it finds a field or parameter of type com.tzavellas.dates.ejb.DatesManagerRemote, that needs to be injected (marked with the @Inject annotation), it should call the provider’s get() method to retrieve an instance to inject.

package com.tzavellas.dates.web;
import com.google.inject.Binder;
import com.google.inject.Module;
import static com.google.inject.jndi.JndiIntegration.fromJndi;
import com.tzavellas.dates.ejb.DatesManagerRemote;
import javax.naming.Context;
import javax.naming.InitialContext;

public class EjbModule implements Module {

  public void configure(Binder binder) {
    // Bind Context to the default InitialContext.
    binder.bind(Context.class).to(InitialContext.class);
    // Bind the remote interface to the JNDI name using the JNDI Provider
    binder.bind(DatesManagerRemote.class)
          .toProvider(fromJndi(DatesManagerRemote.class, "com.tzavellas.dates.ejb.DatesManagerBean"));
  }
}

For more information on how to do dependency injection with Guice see the Guice User’s Guide.

12. Change the action to use the EJB

Now that Guice instantiates our actions we can use the normal Guice @Inject annotation to mark an injection point in the action class. We can use any of the constructor, setter and field injection mechanisms. The below code uses field injection because it might be more familiar to EJB3 developers.

package com.tzavellas.dates.web;
import com.google.inject.Inject;
import com.opensymphony.xwork2.ActionSupport;
import com.tzavellas.dates.ejb.DatesManagerRemote;
import java.util.Date;

public class CurrentDateAction extends ActionSupport {
  // Guice field injection of the SLSB
  @Inject DatesManagerRemote bean;

  private Date currentDate;

  @Override
  public String execute() throws Exception {
    currentDate = bean.currentDate();
    return SUCCESS;
  }

  public Date getCurrentDate() {
    return currentDate;
  }
}

Conclusion

We are done. We’ve just coded a simple Struts 2 application that uses Guice to inject stateless session EJB3s to Struts actions. You can follow the instructions outlined above to do the same into your applications.

Appendix: Quick summary of all the steps

Assuming that you have a working Struts 2 application, below you will find a series of steps you could follow to do dependency injection of your stateless EJB3s into your Struts 2 actions.

For your project:

  1. Include the Guice jars in the WEB-INF/lib directory.
  2. Define a Guice module that will contain the bindings for your EJBs.
  3. Edit the struts.xml to define Guice as your ObjectFactory and include the above module.

For every EJB that you want to inject into your Struts actions:

  1. Inside the module, define a binding for the EJB using the Guice Provider from com.google.inject.jndi.JndiIntegration class, by specifying the bean’s client interface and the global JNDI name of the bean (or an ejb-ref if you have one defined in web.xml).
  2. Use the @Inject annotation in the Struts actions where you want the EJBs injected.

Dynamic Delegate

Dynamic Delegate is my new pet project.

Dynamic Delegate is a small library that allows you to create objects that implement the Business Delegate design pattern on the fly. You don’t have to code a Business Delegate. All you need to do, is make your EJBs implement the Business Interface design pattern and use DynamicDelegateFactory to create a Business Delegate that will implement the Business Interface of the EJB.

You can see an example of Dynamic Delegate here.

Book Review: Core J2EE Design Patterns 2nd edition

Core J2EE Design Patterns

I read the Core J2EE Design Patterns 2nd edition in July 2005. Below I have written a review for this important book.

Core J2EE Design Patterns is one of the most important books on the traditional J2EE application architecture. If you are programming J2EE systems that are heavily based on EJB 2.x then this book is a must read for you. On the other hand if you are programming J2EE (without EJB :-)) with more lightweight tools, like Spring, don’t rush to go without considering to read this book. This book, no matter which technology you use to implement enterprise applications provides good information on object oriented design and layering.

Of course, as many people have said before, a lot of the core J2EE design patterns are not really patterns but they just provide ways to overcome several limitations in some of the J2EE technologies. Examples of “pseudo-patterns” include Composite Entity and Data Transfer Object which try to address some limitations of the EJB Entity Beans. I believe that the reader can also learn a lot from these “pseudo-patterns”. For example the Data Transfer Object can be seen as a way to decouple two layers or as a more general pattern for distributed computing where you aggregate all the information that you want to pass between the nodes in transfer objects and not just as a way with acceptable performance to get multiple fields from an Entity Bean. For example if for some reason you have a physically separated business tier and you use a technology like Hibernate for persistence you will probably need to have a remote facade that will return transfer objects with all the information that you need in the presentation tier in order to avoid any LazyInitializationException exceptions. I find almost everything in the book useful and educative.

For me a book on design patterns is useful if it has lots of code to illustrate how the patterns can be implemented. The Core J2EE Design Patterns not only provides implementations for all the patterns but also provides and analyzes various implementation strategies. You can see multiple ways to implements most of the patterns, learn the trade-offs of each implementation strategy and also get a deeper understanding of the various J2EE technologies.

The UML diagrams in the book are very good and very helpful since they help you visualize the interactions in the design pattern and you better understand the responsibilities of the participant objects.

I’d like to note two things that are specific to the second edition. First the existence of Web Service Broker, a pattern on how to implement web services in J2EE 1.4, tells us the important role of web services in the J2EE 1.4 update. Second the existence of Business Object tells us that the procedural style of EJB applications made J2EE programmers forget the basics of object oriented programming. You cannot create a rich in behavior domain model with Entity Beans cause they don’t support inheritance and they are not reentrant (if Entity Bean “A” calls Entity Bean “B” then in the same call stack B cannot call back to A). So J2EE programmers implemented all the business logic inside a service layer (with Session Beans), with anemic domain models using Entity Beans. A service layer can be good for things like transaction management, security and other infrastructure services but when you have complex business logic and an anemic domain model you can easily end up with lots of duplicate code. The Business Object is a back to the basics design pattern that acknowledges the importance of rich in behavior domain models.

I would also like to comment on the Composite Entity design pattern. I have very limited knowledge of Entity Beans. I have used Entity Beans in only one project. Most of the projects that I worked on were using Hibernate or JDBC. While reading this pattern I felt very strange since it is very awkward for me to program with Entity Beans. I believe that if you have an exposure to tools like Hibernate and you go back to implement persistence using Entity Beans you are continuously asking yourself “Why things have to be so hard to do and so restrictive?”. I am so glad to see the new EJB 3.0 Entity Beans specification, things are so much better now.

On the other hand, the Domain Store is a welcomed addition to the J2EE patterns. This pattern provides a good explanation for the generic POJO persistence frameworks like Hibernate, JDO and EJB 3.0 (JSR 220).

For me, the Core J2EE Design Patterns 2nd edition was a very pleasant reading since I expanded my knowledge of J2EE and also cleared some things in my mind. I was aware of most of the patterns in this book but reading them from this book made them more clear in my mind. From my experience a lot of J2EE programmers do not really understand most of the core J2EE design patterns and misuse them.

My conclusion for Core J2EE Design Patterns 2nd edition is that it is a very well written book that is a must read for every J2EE developer since not only does it provide valuable information about programming J2EE applications with the traditional architecture but it also defines a widely used vocabulary for common J2EE patterns and idioms.

Caching in Service Locator implementations

Here you can find an article by Bobby Woolf that describes why caching inside a Service Locator in J2EE 1.3 applications may have unexpected behavior.

The article also provides a nice explanation of the EJB resource reference mechanism.

Update (19/9/2005):

BTW this is why the Adventure Builder (the sample application developed by SUN for J2EE 1.4) has two implementations for the Service Locator design pattern.

The first implementation is for the EJB tier and does not have caching to avoid the problem explained in the article.

The second implementation is for the web tier and uses caching since resource references in the web tier are the per web application and it is safe to cache them in a static variable.