Steve Hostettler

JEE and test automation

Fakes, Stubs, Dummy, Mocks, Doubles and All That…

| Comments

In this post, I look at the different kind of objects used for test purposes. By this, I mean objects that are used to make a test running. This article focuses on component testing, a.k.a. unit testing (I do not like the term unit testing because it is too often misunderstood with the technology behind, e.g., JUnit, testNG). Although there already exists a great number of resources on that subject, it was very difficult to me to understand the differences between the different kinds of test objects. This is partly due to the fact that different authors use different terms for the same object and the same term for different objects [1]. To be as didactic as possible, I also chose to add some blocks of code. Please note, that these blocks are only here for the sake of clarity. This is not the way I would recommend to do stubbing, faking, and mocking. Consider Mockito and PowerMockito for that. These are amazing tools to that purpose. They deserve a post on their own to discuss good practices. This post is in no way an exhaustive state of the art, I only tried to select the terms that, in my opinion, are clear and are consensual enough. To that end I used a number of sources that can be found in the bibliography section.

Here are the main reasons to use different objects during the test phase and in production:

  • Performances: the actual object contains slow algorithms and heavy calculation that may impair the test performances. A test should always be fast to not discourage regular run and therefore to identify problems as soon as possible. The worst case being the one in which the developer must deploy and run the entire application to test a single use case.

  • States: sometimes the constellation under test happens rarely. This is for instances that occur with a low probability such as race conditions, network failure, etc..

  • Non-deterministic: this is the case of components that have interactions with the real-world such as sensors.

  • The actual object does not exist: for instance, another team is working on it and is not yet ready.

  • To instrument the actual dependency: for instance to spy the calls of the CUT to one of its dependencies.

Doubles objects

Test double is the generic term that groups all the categories of objects that are used to fulfill one or several of the previous requirements. The term comes has been coined by Gerard Meszaros in [2] In rough terms, test doubles look like the actual object they double. They satisfy, to different extends the original interface and propose a sub-set of the behaviors that is expected by the specification. This helps to isolate the problem and reduce the double implementation to the strict minimum.

There exists different kind of test doubles for different purposes. The have in common that they can be use instead of the actual component without breaking the contract syntactically.

The next figure describes a simple test setup that do not use test doubles. To test the Component Under Test (CUT), the following test setup uses its actual dependencies (another component). This setup phase is trivial as there is nothing to do. The exercise phase calls the CUT with the proper parameters (direct inputs) that in turn calls it dependency (indirect outputs). Another Component returns its result to the CUT (indirect inputs) that uses it to complete the work and then finally returns the overall result (direct outputs). The terms “direct inputs”, “indirect outputs”, and so on come from [2].

Overview of a test setupOverview of a test setup

Now let us say that “AnotherComponent” is either too complex, not already implemented or has a non-deterministic behavior. In those cases, it is easier to use another implementation of “AnotherComponent” that behaves exactly has expected for a specific scenario.

Hereafter, a simple example to illustrate the rest of the post. The class CUTImpl that realizes the contract CUT implements the component under test. The CUT uses a component that realizes the interface AnotherComponent. For the sake of clarity, the following example injects the dependencies through the constructor. To improve loose coupling, it is possible to rely on dependency injection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package ch.demo.business.service;

public class CUTImpl implements CUT {
  
  AnotherComponent component;

    public CUTImpl(AnotherComponent c) {
        this.component = c;
    }

  @Override
  public String doBusiness(String param, Integer delta) {
      return component.inc(Integer.valueOf(param)).toString();
  }
}
1
2
3
4
5
package ch.demo.business.service;

public interface CUT {
  public String doBusiness(String string, Integer delta);
}
1
2
3
4
5
package ch.demo.business.service;

public interface AnotherComponent {
  Integer inc(Integer param);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package ch.demo.business.service;

public class AnotherComponentImpl implements AnotherComponent {

    public Integer inc(Integer param) {
        if (param == null) {
            throw new IllegalArgumentException("Param must be not null!");
        } else if (param == Integer.MAX_INTEGER) {
            throw new IllegalStateException("Incrementing MAX_INTEGER will result in overflow!");
        } else {
            return param + 1;
        }
    }
}

The following test uses real implementations of the the different components.

1
2
3
4
5
6
7
8
9
package ch.demo.business.service;

public class CUTTest {

    public void testInc() {
        Assert.assertEquals("inc(3) != 4", 4, new CUTImpl(new AnotherComponentImpl()).inc(3, 1));
    }

}

The question is what if:

  1. AnotherComponentImpl is not ready yet
  2. AnotherComponentImpl depends itself on external services or specific hardware resources
  3. AnotherComponentImpl has non-deterministic behaviors.

Dummy objects

Dummy objects are meant to satisfy compile-time check and runtime execution. Dummies do not take part to the test scenario. Some method signatures of the CUT may require objects as parameters. If neither the test nor the CUT care about these objects, we may choose to pass in a Dummy Object. This can be a null reference, an empty object or a constant. Dummy objects are passed around (to dependencies for instance) but never actually used. Usually they are just used to fill parameter lists. They are meant to replace input/output parameters of the components that the CUT interacts with.

In the current example, the parameter delta of the doBusiness method can be set to null or any Integer value without interfering with the test. Of course, this might be different for another test.

1
2
3
4
5
6
7
8
9
package ch.demo.business.service;

public class CUTTest {

    public void testInc() {
        Assert.assertEquals("inc(3) != 4", 4, new CUTImpl(new AnotherComponentImpl()).inc(3, null));
    }

}

Stub objects

Stub objects provide simple answers to the CUT invocations. It does answer to scenarii that are not foreseen by the current test. In other terms it is a simplified fake object. Stub objects may trigger paths in the CUT that would otherwise not been executed.

The next figure presents a test that relies on a test stub. First, the test case setups a stub object. This object responds to the expected CUT invokation in order to enact a given scenario. This is very useful to check indirect inputs with seldom values.

Test setup that uses a test stubTest setup that uses a test stub

Back to the example, the following program illustrates how to use a stub to check specific indirect inputs. This stub shows that the CUT relies on the fact that AnotherComponent does not return null, as it would otherwise raise a NullPointerException.

1
2
3
4
5
6
7
8
9
package ch.demo.business.service;

public class AnotherComponentStub implements AnotherComponent {

    public Integer inc(Integer param) {
        return null;
    }

}
1
2
3
4
5
6
7
8
9
10
package ch.demo.business.service;

public class CUTTest {

    public void testIncWhenAnotherComponentReturnsNull() {
        //Without any modification of the CUT implement, this would raise an exception
        Assert.assertEquals("inc(3) != 4", 4, new CUTImpl(new AnotherComponentStub()).inc(3, 1));
    }

}

Fake objects

Fake objects have working implementations, but they may simplify some behaviors. This makes them not suitable for prime time. The idea is that the object actually displays some real behavior but not everything. While a Fake Object is typically built specifically for testing, it is not used as either a control point or an observation point by the test. The most common reasons for using fake objects is that the real component is not available yet, is too slow or cannot be used during tests because of side effects.

Test setup that uses a fakeTest setup that uses a fake

The following fake simulates most of the behaviors except for the limits (MAX_INTEGER, null, etc…)

1
2
3
4
5
6
7
8
9
package ch.demo.business.service;

public class AnotherComponentFake implements AnotherComponent {

    public Integer inc(Integer param) {
        return param + 1;
    }

}

As the fake covers many scenarios, it can be used to test the general behavior of the CUT.

1
2
3
4
5
6
7
8
9
10
package ch.demo.business.service;

public class CUTTest {

    public void testIncWhenAnotherComponentIsFake() {
        CUT cut = new CUTImpl(new AnotherComponentFake());
        Assert.assertEquals("inc(3) != 4", 4, cut.inc(3, 1));
        Assert.assertEquals("inc(123) != 124", 124, cut.inc(123, 1));
    }
}

Mock objects

Partially implements the interface and provides a way to verify that the calls to the mock objects validate the specification. Mock objects are pre-programmed with expectations that form a specification of the calls they are expected to receive. In fact mocks are a certain kind of stub or fake. However, the additional feature mock objects offer on top of acting as simple stubs or fakes is that they provide a flexible way to specify more directly how your function under test should actually operate. In this sense they also act as a kind of recording device: They keep track of which of the mock object’s methods are called, with what kind of parameters, and how many times.

Whenever the assertions are made on the fake object and not the CUT, then it is a mock.

Test setup that uses a mockTest setup that uses a mock

The following example uses Mockito to provide easy Mocking. Note that the last assertion Mockito.verify checks whether the mock was called with a given parameters. In other words, we check that the CUT did not filter the input parameter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package ch.demo.business.service;

public class CUTTest {

  @Mock
  AnotherComponent ac;
  
  @InjectMocks
  CUT cut = new CUTImpl();

    public void testIncWhenAnotherComponentReturnsNull() {
      Mockito.when(ac.inc(Integer.MAX_INTEGER)).thenReturn(Integer.MAX_INTEGER + 1);
      Mockito.when(ac.inc(3)).thenReturn(3);
      Mockito.when(ac.inc(123)).thenReturn(124);
      
        Assert.assertEquals("inc(Integer.MIN_INTEGER) != Integer.MIN_INTEGER + 1",
                Integer.MIN_INTEGER + 1, cut.inc(Integer.MIN_INTEGER, 1));
        Assert.assertEquals("inc(3) != 4", 4, cut.inc(3, 1));
        Assert.assertEquals("inc(123) != 124", 124, cut.inc(123, 1));

        //Verifies that the method inc of AnotherComponent was called with parameter Integer.MAX_INTEGER
        Mockito.verify(ac).inc(Matchers.eq(Integer.MAX_INTEGER));
        //Verifies that the inc method has been called three times.
        Mockito.verify(ac, Mockito.times(3)).inc(anyInt());
    }
}

Test Spy

According to Meszaros [2], a test spy is basically a recorder that is able to save the interactions between the CUT and the spy for later verifications.

Test setup that uses a test spyTest setup that uses a test spy

On the other hand, Mockito considers that a spy is an real implementation in which you change only some specific behaviors. Instead of specifying every behavior one by one, you take an existing object that does most of it and you only change very specific behaviors.

Conclusion

To sum up:

  • A dummy is just there to enable compilation and is not supposed to be part of the test.
  • A fake is a partial implementation that can be used either in a component test or in a deployed setting.
  • A mock is a partial implementation that enables asserting on the component interactions.
  • A spy is either a recorder for later use or a proxy on a real implementation that is used to override some specific behaviors.

Bibliography

JEE6 Tutorial

| Comments

I hereby start a series of tutorial on the major (IMHO) JEE 6 features. As a lecturer, I teach the JEE stack at the University of Geneva. This tutorial represents most of the topics that I cover during the EJB, CDI, and JPA lessons.

There already exists a bunch of very complete tutorials and books on the subject. Let me cite the excellent Oracle JEE tutorial and Antonio Goncalvez’s books that are available both in English and in French. For advanced JEE developers, Adam Bien’s Real World Java EE Night Hacks is a must read.

As the EJB 3.1 specification is rather well written, I encourage people to read it or at least to look at specifics when needed.

To support this tutorial you can find a JEE6-Demo on GitHub. It contains a simple enterprise application that demonstrates many of the aspects I discuss hereafter. The first step of this tutorial is to prepare the environment:

1) Install GlassFish and integrate it to your favorite development environment (eclipse in my case). You can get GlassFish from here. Grab the zip version and install it by unzipping the archive.

2) Run GlassFish and check that it works. Locate the script named asadmin in the bin directory, start it and at the prompt, execute the command start-domain. This starts the GlassFish instance.

1
2
3
4
5
6
7
8
9
10
localhost:bin ~$ ./asadmin
Use "exit" to exit and "help" for online help.
asadmin> start-domain
Waiting for domain1 to start ...
Successfully started the domain : domain1
domain  Location: ~/Applications/glassfish3/glassfish/domains/domain1
Log File: ~/Applications/glassfish3/glassfish/domains/domain1/logs/server.log
Admin Port: 4848
Command start-domain executed successfully.
asadmin> 

Now the server is started and it listens to the ports 8080 and 4848. The first being the application port while the second is the administrative console.

Start a browser and navigate to http://localhost:4848/common/index.jsf. Depending of the server configuration, you may have to log in.

3) Do a Git checkout of the jee6-demo project that is available here.

4) Perform a mvn clean install at the project root

This compiles the project and builds the artifacts. It should end up in something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] jee6-demo ......................................... SUCCESS [0.480s]
[INFO] Service Layer ..................................... SUCCESS [3.650s]
[INFO] Presentation Layer ................................ SUCCESS [1.725s]
[INFO] Application ....................................... SUCCESS [0.663s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.923s
[INFO] Finished at: Sun Jan 06 16:41:29 CET 2013
[INFO] Final Memory: 19M/81M
[INFO] --------------------------------------------------------------------

5) In the GlassFish installation directory, there is a javadb directory that contains, Derby, a Java-based database. Starts the network server:

1
2
3
4
5
>$ pwd
/~/Applications/glassfish3/javadb/bin
localhost:bin ~$ ./startNetworkServer
Mon Jan 07 06:02:54 CET 2013 : Security manager installed using the Basic server security policy.
Mon Jan 07 06:02:54 CET 2013 : Apache Derby Network Server - 10.8.1.2 - (1095077) started and ready to accept connections on port 1527

The database server listens to the port 1527.

Now that the database is started. It is time to populate the database with the database creation scripts as well as some data. In the project, under the ejb components, there is a sql file that initializes the database structure as well as some data.

Derby provides a command line tool called ij to connect to the database and to execute sql scripts:

1
2
3
4
5
localhost:bin ~$ pwd
~/Applications/glassfish3/javadb/bin
localhost:bin ~$./ij ~/git/jee6demo/jee6-ejb/src/main/resources/sql/createStudentsDB_DERBY.sql
...
ij> QUIT;

Now the database is ready to use.

6) Create a datasource in GlassFish that points to the database server that has been started previously:

First, let us create a connection pool:

1
2
3
4
5
asadmin> create-jdbc-connection-pool  --datasourceclassname=org.apache.derby.jdbc.ClientDataSource40 --restype=javax.sql.DataSource --property user=DEV:DatabaseName=StudentsDB:Password=DEV:ServerName=localhost:PortNumber=1527:create=true StudentsDB
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
222JDBC connection pool StudentsDB created successfully.
Command create-jdbc-connection-pool executed successfully.

The connection pool provides a … pool of connection that is managed by the application server. A major benefit being that the developer does not have to open and close connections. The server opens n connections and allocate them on demand. It ensures that there will not be 1000 open connections to the database thus improving the performances. Then, we create a datasource that uses the previous connection pool:

1
2
3
4
5
asadmin> create-jdbc-resource --connectionpoolid StudentsDB --enabled jdbc/StudentsDS
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
JDBC resource jdbc/StudentsDS created successfully.
Command create-jdbc-resource executed successfully.

7) Configure the messaging resources.

The tutorial uses JMS (Java Messaging Service) to implement the publish/subscribe pattern. The following script builds a connection factory for JMS queues.

1
2
3
4
5
asadmin> create-jms-resource --restype javax.jms.QueueConnectionFactory --enabled  MyConnectionFactory
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
Connector resource MyConnectionFactory created.
Command create-jms-resource executed successfully.

The following snippet declares the JMS queue. That is the message endpoint.

1
2
3
4
5
asadmin> create-jms-resource --restype javax.jms.Queue MyQueue
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
Administered object MyQueue created.
Command create-jms-resource executed successfully.

8) Configure the security

Authentication and authorization is another major feature that is provided by the application server. First let us create the realm with two groups user and manager.

1
2
3
4
asadmin> create-auth-realm --classname com.sun.enterprise.security.auth.realm.file.FileRealm  --property assign-groups=manager,user:file=jee6-tutorial-file-realm:jaas-context=fileRealm jee6-tutorial-file-realm
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
Command create-auth-realm executed successfully.

Then, we add a user that belongs two groups: user and manager.

1
2
3
4
5
6
asadmin> create-file-user --authrealmname jee6-tutorial-file-realm --groups user:manager user1
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
Enter the user password> 
Enter the user password again> 
Command create-file-user executed successfully.

The second user only belongs to the group user.

1
2
3
4
5
6
asadmin> create-file-user --authrealmname jee6-tutorial-file-realm --groups user user2
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
Enter the user password> 
Enter the user password again> 
Command create-file-user executed successfully.

9) Deploy the application

1
2
3
4
5
asadmin> deploy ~/git/jee6demo/jee6-ear/target/jee6-demo-ear-1.0.0-SNAPSHOT.ear
Authentication failed with password from login store: ~/.asadminpass
Enter admin password for user "admin"> 
Application deployed with name jee6-demo-ear-1.0.0-SNAPSHOT.
Command deploy executed successfully.

10) Test the application

Once deployed, serve to http://localhost:8080/jee6-demo-web/facade/studentService/all and you should get: You must log yourself with one of the use that you created at step 8).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<studentsDto xmlns:ns2="http://ch.demo.app">
  <students>
      <id>0</id>
      <last_name>Doe</last_name>
      <firstName>John</firstName>
      <birthDate>1965-12-10T00:00:00+01:00</birthDate>
      <phoneNumber>
      <areaCode>0</areaCode>
      <countryCode>0</countryCode>
      <number>0</number>
      </phoneNumber>
      <address>
          <number>22</number>
          <street>wisteria street</street>
          <city>Downtown</city>
          <postalCode>34343</postalCode>
      </address>
  </students>
  <students>
      <id>1</id>
      <last_name>Doe</last_name>
      <firstName>Jane</firstName>
      <birthDate>1985-12-10T00:00:00+01:00</birthDate>
      <phoneNumber>
      <areaCode>0</areaCode>
      <countryCode>0</countryCode>
      <number>0</number>
      </phoneNumber>
      <address>
          <number>22</number>
          <street>wisteria street</street>
          <city>Downtown</city>
          <postalCode>34343</postalCode>
      </address>
  </students>
</studentsDto>

Now you are ready to follow me in the EJB world.

The tutorial is organized in three parts. First, in this post, we will look at the EJB stack. In following posts, we will cover both the Context and Dependency Injection and the Java Persistence API.

EJBs

The EJB API provides useful non-functional services to Java Enterprise Applications such as transactionality, security, pooling, and thread-safety. Server side components that implement this API and wrap up business logic are called Enterprise Java Beans (EJBs). While the first versions were infamously known for the boilerplate code as well as their low testability, EJB 3.x are rather easy to use thanks to a new design paradigms called Convention over Configuration. The idea is to specify unconventional aspects rather than everything. This dramatically reduces the boilerplate code and improves readability.

Furthermore, the massive usage of annotations instead of XML descriptor greatly improves the productivity. In the sequel, I mostly rely on annotations. Nevertheless, every annotation has its counterpart in a configuration descriptor that is called ejb-jar.xml.

In case there is two different value for the same property, remember that one from the ejb-jar.xml always overrides the annotation.

Enterprise Java Beans are of three kinds:

  • Session Beans: components whose execution is triggered by a client call. The call can be local (within the JVM) or remote (by another JVM).
  • Message Beans: execution is triggered by a message and the business logic is processed asynchronously. Please note that, since JEE6 there are other (simpler) ways to process logic asynchronously. Nevertheless, Message Beans remain very useful to implement bus and/or publish-subscribe patterns and to enforce loose coupling between the client and the server component.
  • Entity Beans: I will not discuss entity beans as they have been replaced by the JPA 2.0 specification.

Session Beans

As mentioned previously, session beans (merely) react on client invocation. Henceforth, the bean can either take the client session into account (thus it shares a state between multiple client invocations) or it can treat each call as unrelated. In the first case, the EJB is called Stateful while in the latter it is called Stateless.

Stateless Session Beans

Let us start with a Stateless bean. The following Java class describes a Stateless EJB. The most important part is the annotation @Stateless at the top of the class. This marks the class as an EJB. When the container instantiates this class, it knows that it is a so-called Managed Bean. By this, it means that the container manages the bean’s lifecycle (e.g., instantiation, passivation). Furthermore, as an EJB, it has access to the container services such as security and transactionality.

The following snippet describes a Stateless Session bean that computes a grade distribution. The method is secured and only authorized to client that have the role user through the @RolesAllowed({ "user" }) annotation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Stateless
public class StudentServiceJPAImpl implements StudentService {
...
    @Override
    @RolesAllowed({ "user" }) // This a role-based security.
    public final Integer[] getDistribution(final int n) {
      numberOfAccess++;
        Integer[] grades = new Integer[n];

        for (Student s : this.getAll()) {
            grades[(s.getAvgGrade().intValue() - 1) / (TOTAL / n)]++;
        }
        return grades;
    }
 ...
}

Please note that the previous EJB implements an interface. An EJB can be local (invokable from within the container), remote (invokable from another JVM) or both. In the previous case, it is a local interface and therefore the bean is only invokable locally.

1
2
3
4
5
6
7
8
9
@Local
public interface StudentService extends Serializable {
  /**
  * @return an array that contains the distribution of the grades. It
  *         partitions the grades in "n" parts.
  * @param n : number of parts
  */
  int[] getDistribution(final int n);
}

Adding a remote invocation to the implementation amounts to add an interface that is annotated @Remote. Of course, the interface may be different and may exposes different services locally and remotely.

1
2
3
4
5
6
7
8
9
10
11
@Remote
public interface StudentServiceRemote extends Serializable {

    /**
     * @param lastname
     *            of the student
     * @return the student with the given lastname.
     */
    Student getStudentByLastName(String lastname);

}

The implementation must be changed as follow to be remotely invokable:

1
2
3
@Stateless
public class StudentServiceJPAImpl implements StudentService, StudentServiceRemote {
...

To use this EJB, we need a client code. The easiest possible interaction is either via a JAX-RS service or via a servlet. In the JEE6-Demo, under the JEE6-WEB project the JAX-RS facade is called StudentFacade.java. It implements a JAX-RS facade over the StudentService.

The method getDistribution() uses the student service that is injected via @EJB in the facade. Dependency injection is now a first class citizen in the JEE6 stack.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@ApplicationScoped // This sets the scope to application level
@Path("/studentService")
public class StudentServiceFacade implements Serializable {
...
  @EJB
  StudentService studentService;

  @GET
  @Produces({ "application/xml", "application/json" })
  @Path("distribution")
  public Response getDistribution() {
      Integer[] distrib = studentService.getDistribution(10);
      return Response.ok(new DistributionDto(distrib)).build();
  }
}

The following snippet illustrates the injection of a Stateless EJB into a Servlet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@WebServlet("/student")
public class StudentServlet extends HttpServlet {

  private static final long serialVersionUID = 1L;

  @EJB
  StudentService studentService;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      response.getOutputStream()
              .println("There are #" + studentService.getAll().size() + " students in the database");
  }

  @Override
  protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
      this.doGet(arg0, arg1);
  }

}

As you can see, implementing EJBs (and invoking them) is rather easy. So far, we did not talk much about transactionality and security so you might wonder why using EJBs for such simple business services. The answer is pooling and thread-safety. As the container manages a pool of EJBs, it handles the invocation queue and you do not have to manager re-entrance and thread-safety.

Remember that there is a one to many relationship between a stateless session bean and the clients. In other words, one instance may manage different clients. Hence, there must be not field that represent a client state in a Stateless EJB because there is no guarantee that a given client will get the same SLSB accross two invokations. Nevertheless, within a given invokation the client is guaranteed to be the only user.

Consider the following exercises.

Exercise 1: Add a new method to the StudentService service that computes the standard deviation and use this method in the JAX-RS facade.

Exercise 2: Add a counter that is incremented each and every time a method is invoked. Print out the thread-id (and if possible the session-id) and explain why the so-called stateless beans must be without state. Add a rest service to interface this method.

Transactionality

Transactions are important concepts when dealing with enterprise applications. It is of vital importance that whenever something goes wrong, the transaction is roll-backed. This preserves the ACID properties. Managing database transactions with JDBC is complex to say the least. Remember that we often have to manage transactions over several databases and even between databases and messaging queues. If the processing of a message leads to a database exception, we might want to put the message back in the queue.

Lucky for us, JEE 6 manages (almost) everything by itself. By default a bean is transactional and each method either reuse a running transaction or creates a new one if necessary.

By default the transaction (or transaction context) is propagated to other business methods that are called from within a transactional method.

In JEE, there is two types of transaction management:

  • Bean Managed : In this case the bean is annotated with @TransactionManagement(TransactionManagementType.BEAN). In this mode, the developer must manage the transaction himself.

  • Container Managed: this is the default behavior and it corresponds to marking the bean @TransactionManagement(TransactionManagementType.CONTAINER). This mode is called Container Managed Transaction Demarcation. This idea is that every public method is transactional and is marked as @Required.

The following snippet shows how to use bean demarcation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@MessageDriven(mappedName = "MyQueue")
@TransactionManagement(TransactionManagementType.BEAN)
public class StudentRegistrationService implements MessageListener {

  @PersistenceContext
  EntityManager em;

  ...

  public void onMessage(Message inMessage) {
      TextMessage msg = null;

      em.getTransaction().begin();

      try {
          ...
          msg = (TextMessage) inMessage;
          logger.info("MESSAGE BEAN: Message received: " + msg.getText());
          logger.info(Thread.currentThread().getName());
          ...
      } catch (JMSException e) {
          em.getTransaction().rollback();
          ...
      }
      em.getTransaction().commit();
  }
}

and now the exact same class using container demarcation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@MessageDriven(mappedName = "MyQueue")
public class StudentRegistrationService implements MessageListener {

  @PersistenceContext
  EntityManager em;

  ...

  public void onMessage(Message inMessage) {
      TextMessage msg = null;
      try {
          ...
          msg = (TextMessage) inMessage;
          logger.info("MESSAGE BEAN: Message received: " + msg.getText());
          logger.info(Thread.currentThread().getName());
          ...
      } catch (JMSException e) {
          em.getTransaction().rollback();
          ...
      }
  }
}

Because the previous snippet relies on the default convention, it is equivalent to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@MessageDriven(mappedName = "MyQueue")
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class StudentRegistrationService implements MessageListener {

  @Inject // Let's ignore this for the moment
  private transient Logger logger;

  @PersistenceContext
  EntityManager em;

  @Resource // Let's ignore this for the moment
  private MessageDrivenContext mdbContext;

  public void onMessage(Message inMessage) {
      TextMessage msg = null;
      try {
          ...
          msg = (TextMessage) inMessage;
          logger.info("MESSAGE BEAN: Message received: " + msg.getText());
          logger.info(Thread.currentThread().getName());
          ...
      } catch (JMSException e) {
          em.getTransaction().rollback();
          ...
      }
  }
}

In other terms, it uses container managed transaction demarcation @TransactionManagement(TransactionManagementType.CONTAINER). Moreover, each and every public method either reuses an existing transaction or creates a new one if none has been started @TransactionAttribute(TransactionAttributeType.REQUIRED)

The @TransactionAttribute annotation can also be put directly on the method. Valid options are:

  • REQUIRED: if there is an existing transaction then it reuses it, otherwise it creates a new one.
  • REQUIRES_NEW: it always creates a new transaction
  • NEVER: if there is an existing transaction then it fails
  • MANDATORY: if there is an existing transaction then it reuses it, otherwise it fails
  • NOT_SUPPORTED: If there is a transaction then it suspends it and it does not propagate the transaction to other business methods, otherwise it does nothing.
  • SUPPORTS: If a transaction exists then it works as for REQUIRED, otherwise it works as for NOT_SUPPORTED.

Consider the following exercises.

Exercise 3: Test the different types of transaction attribute and observe their respective behavior.

Exercise 4: Are the snippets 1 and 2 semantically equivalent?

Exercise 5: Mix the two types of transaction management.

Security

Another great feature of EJBs is their ability for declarative authorization and the integration in the JAAS framework. JAAS is the Java Authentication and Authorization Service It provides unified services to access user directories for user authentication and their authorization. As the client is already authenticated, at the EJB level, only authorization matters.

After authentication, a principal (e.g., user name, role) is set in the context. This principal is used for authorization.

The main annotation is @RolesAllowed followed by a list of authorized roles. As an example, look at the method getDistribution of StudentServiceJPAImpl.java. The method is only allowed for client that belongs to the group/role user.

Sometimes, a method of an EJB is not executed in the context of an authenticated user or the authenticated user has not enough credentials. If it is still important to run the method, you can use the @RunAs annotation. This basically overrides the current security context (and the associated principal) similarly to sudo for UNIX.

In any EJB, it is possible to get the current client session and therefore the principal:

1
2
3
4
5
6
7
8
9
10
11
@Resource
SessionContext ctx;

public void doSomething() {
  // obtain the principal. 
  Principal principal = ctx.getCallerPrincipal();
  // obtain the name. 
  String name = callerPrincipal.getName();
  // Is the caller an admin?
  ctx.isCallerInRole("admin")
}

Exercise 6: Change the method getDistribution to only allow client that belong to the admin group. Log as a user and as an admin, check the servlet as well as the JAX-RS service. What do you observe?

Exercise 7: Add a new Role to the application, and use it. Warning, some configurations are vendor specific.

Exercise 8: Create a service that uses @RunAs to upgrade the credentials of a standard user in order to call another service that requires the admin level.

Callbacks and Interceptors

Interceptors are used to enhance the business method invocations and the beans’ lifecycle events. Interceptors implements the AOP paradigm.

Interceptors are of two kinds: - Lifecycle event interceptors such as @PostConstruct, @PostActivate, and @PrePassivate, and @PreDestroy enable to add logic when the bean is created or destroyed. - Call-based interceptors that relies on the @AroundInvoke annotation.

In the first case, adding the annotation before the method declaration is enough. It will then be called when the lifecycle event occurs. In the latter case, in addition to the annotation the developer must configure the ejb-jar.xml file.

Here is a simple interceptor that prints out the time consumed by a method call:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception
{
   long start = System.currentTimeMillis();

   try {
      Object value = context.proceed();
   } finally {
          StringBuilder str = new StringBuilder("******  ");
      str.append(context.getMethod().getName());
      str.append(" took :");
      str.append(System.currentTimeMillis() - start);
      str.append(" ms  ******");

      mLogger.info(str.toString());
   }
}

In addition to the interceptor declaration, it must be activated by mean of either an annotation on the target EJB or via the ejb-jar.xml file. If several interceptors are declared, then the order of declaration is the order of execution: the last is the most nested interceptor.

The following example presents the annotation based declaration.

1
2
3
@Stateless
@Interceptor({PerformanceEJBInterceptor.class})
public final class StudentServiceJPAImpl implements StudentService, StudentServiceRemote {

In the following snippet, the interceptor is applied to all methods whose name is like get* and EJB’s name is like Student*. It is also possible to specify the parameters’ type in case of overloading.

1
2
3
4
5
6
7
8
9
10
11
<assembly-descriptor>
 <!-- Default interceptor that will apply to all methods for all beans in deployment -->
 <interceptor-binding>
      <ejb-name>Student*</ejb-name>
      <method>
           <method-name>get*</method-name>
      </method>
      <interceptor-class>ch.demo.business.interceptors.PerformanceEJBInterceptor</interceptor-class>
   </interceptor-binding>
   ...
</assembly-descriptor>

Exercise 9: Add an interceptor that for all public methods of StudentServiceJPAImpl.java to increments an overall (common to all clients) usage counter using the annotation based approach.

Exercise 10: Do the same, but using the `ejb-jar.xml.

Timers

Some services are not directly linked to a client session. This is the case for batch processes that must run every x hours. To that end, EJB 3.1 provides the annotation @Schedule to specify how often a service method must be called. This is similar to the CRON feature on UNIX systems.

The following example runs the method doSomethingUseful every 30 minutes.

1
2
3
4
@Schedule(minute="*/30", hour="*")
public void doSomethingUseful() {
    ...
}

Exercise 11: Add a scheduler that runs a method every minutes to print out the number of students in the database.

Exercise 12: @Schedule is often used in conjunction with @RunAs. Why?

Asynchronous calls

Asynchronous calling means that the control is returned to the caller before the process has been completed. For instance, a batch job that loads 1000 customers description from one database, processes them and finally save them in another database. From a performances point of view, it is better to split the process in x batches and then to wait until every thing is finished. Firstly, if the asynchronous call is made to another EJB, it is possible to leverage the pool to have parallel treatments without managing multi-threading and race conditions. Secondly, as the different call may use different database connections, it will limit the database bottleneck.

To do this, JEE provides the @Asynchronous annotation. Any method that returns either nothing (void) or an instance of type Future<T> can be run asynchronously.

The Future interface exposes the method get that blocks until the job is over. The following class, exposes the method processJob that runs asynchronously.

The methods processJobs starts 10 times the method processJob and put the resulting Future<String> in an array. Then it iterates of the pool and wait until all calls have returned.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Stateless
public class BatchProcessor {

public void processJobs() {
  Future<String>[] pool = new Future<String>[10];
  for (int i = 0; i < 10; i++) {
      pool[i] = processJob("Job #" + i);
  }

  for (int i = 0; i < 10; i++) {
      pool[i].get();
  }    
}


@Asynchronous
public Future<String> processJob(String jobName) {

    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        Thread.interrupted();
        throw new IllegalStateException(e);
    }
    return new AsyncResult<String>(jobName);

}

Exercise 13: Create an EJB that invoke an asynchronous method that runs 100 times. The asynchronous method should wait a random time between 5 and 10 seconds before returning a the actual waiting time. Collect all the waiting times and compute the average.

Singleton Beans

Singleton beans (@Singleton) are special kind of EJBS that exist only in one instance in the container. This is for instance useful to initialize the application. Thus, @Singleton can be associated with @Startup to start the EJB during container’s startup.

As there is only one instance, it means the bean is meant to be shared. Therefore, it is important to specify the locking policy. There are two types of locking: - Container managed concurrency management @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER). This is the default behavior and it is highly recommended to stick to it. Annotating a method (or the class) with @Lock(LockType.READ) means that the method can be safely access concurrently. @Lock(LockType.WRITE) requires the calls to the method to be serialized. The methods are @Lock(LockType.WRITE) by default. - Bean managed concurrency management @ConcurrencyManagement(ConcurrencyManagementType.BEAN). This requires the developer to use synchronized and volatile to achieve good concurrency.

By default the class is marked as @Lock(LockType.WRITE), thus EVERY CALL is synchronized. This is probably not the expected behavior (at least most of the time) and produces a huge bottleneck. Make sure to set the proper lock policy on the class and to only put @Lock(LockType.WRITE) where needed.

The following bean initialize a shared variable during container startup and lock the access to the modification to only one thread (client) at a time.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Singleton
@Startup
@Lock(LockType.READ)
public class StatusBean {
  private String status;

  @PostConstruct
  void init {
    this.status = "Ready";
  }

  public String getStatus() {
    return this.status;
  }

  @Lock(LockType.WRITE)
  public void setStatus(String new Status) {
    this.status = newStatus;
  }

  @Lock(LockType.WRITE)
  @AccessTimeout(value=360000)
  public void doTediousOperation {
    ...
  }
}

Exercise 14: Write a singleton that reads the postal code from the database during startup, update them every 30 minutes. Take care of the concurrency aspects.

Stateful Session Beans

Unlike stateless session beans, stateful session beans maintain a state across several client invocation. This is because there is a one to one relationship between a client and a stateful session bean.

The following code snippet describes a stateful session bean that maintains a counter across several invocations. A stateful session bean is annotated with @Stateful. As it is stateful, it maintains a session state and it is therefore important to set a timeout. Otherwise, the number of open session will raise and it will consume the server memory. The timeout is defined using the @StatefulTimeout annotation.

Because there is no instance sharing among several client, Stateful session beans are more resource-demanding than stateless session beans. Therefore, they should be used with great care.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Stateful
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 30)
public class StudentStatisticsServiceImpl implements StudentStatisticsService {

  private Long numberOfAccess = 0l;

  @Override
  public String getStatistics() {
      return "The student service has been invoked #" + numberOfAccess
              + " in this session";
  }

  public void count() {
      numberOfAccess++;
  }
}

As a stateful session bean is not per se linked to an HTTP session, the application client code must ensure to remember which instance of the EJB is dedicated to which client. When used in conjunction with a Servlet, Stateful beans are often put in the HTTP session for further reuse.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      StudentStatisticsService statistics = (StudentStatisticsService) request.getSession().getAttribute(
              StudentStatisticsService.class.toString());

      if (statistics == null) {
          try {
              InitialContext ctx = new InitialContext();
              statistics = (StudentStatisticsService) ctx
                      .lookup("java:global/JEE6-EAR/JEE6-EJB-0.0.1-SNAPSHOT/StudentStatisticsServiceImpl");
              request.getSession().setAttribute(StudentStatisticsService.class.toString(), statistics);
          } catch (NamingException e) {
              throw new RuntimeException(e);
          }

      }

      statistics.count();

      response.getOutputStream().println("There are #" + studentService.getAll().size() + " students in the database");
      response.getOutputStream().println(statistics.getStatistics());
      response.getOutputStream().println(studentService.getStatistics());
}

Either the EJB is looked-up with JNDI and then put into the HTTP session or, when using CDI, the link is made based on the caller scope. The class StudentServiceFacade.java describes how the injection automatically links the correct instance of a stateful session bean to a given based on the @SessionScoped annotation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@SessionScoped
@Path("/studentService")
public class StudentServiceFacade implements Serializable {

  private static final long serialVersionUID = 1318211294294344900L;

  @EJB
  StudentService studentService;

  @EJB
  StudentStatisticsService studentServiceStatistics;


  @GET
  @Produces({ "application/xml", "application/json" })
  @Path("session")
  public Response getSessionStatistics() {
      return Response.ok(studentServiceStatistics.getStatistics()).build();
  }
  
  ...
}

Consider the following exercise.

Exercise 15: Show that two sessions share the same overall count but not the same per session count.

As the container does not share the stateful instances, it might run out of memory and therefore it will try to save the state of the bean on disk (or database). This operation is called Passivation. Afterwards, when the client comes back and requires its stateful instance, the container loads it from the disk. This operation is called Activation.

Some operations such as initializing/cleaning File, a socket connection, or a database connection can be made before activation and/or after activation using the following @PrePassivate and the @PostActivate annotations.

Consider the following exercises:

Exercise 16: Stop the server and observe that the bean has been passivated.

Exercise 17: Start the server and observe that the bean has been activated.

Whenever the user logs out and thus invalidate the HTTP Session, you might want to clean up the EJB state and release the resources. To achieve this, the client must call a method annotated with @Remove. As soon as the client call is over the container can garbage the bean. The idea is simply to get ahead of the timeout.

Exercise 18: Implements two methods with @Remove with two different behaviors. Check that both will discard the current instance. Hint: you can use @PreDestroy to check the bean’s destruction.

Message Driven Beans

Message driven beans (MDB) are very useful for asynchronous process and for decoupling the client from the processor. MDB implement a typical publish/subscribe architecture.

There are two kinds of objects, a MDB can listen to:

  • Topics: pure publish/subscribe semantics. A new message will be processed by every listeners.
  • Queue: more of a load balancer, once the message is consumed by one of the listeners, it is removed from the queue.

Although, there is, in JEE6, another mechanism for asynchronous processing, MDBs remain the best alternative if you do not want the client to be aware of the asynchronous logic and processor.

The idea is that there is a queue (or a topic) in between. Therefore, the client as no knowledge whatsoever of the message processor contract or semantics.

The first step is to configure a Queue Connection Factory as well as a Queue in the application server.

The following servlet gets the connection factory as well as the queue injected. As always with dependency injection, the same result can be achieved using JNDI lookups. For each request to the servlet 100 messages are generated and put in the Queue called MyQueue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@WebServlet("/registration")
public class RegistrationServlet extends HttpServlet {

  ...
      
  @Resource(mappedName = "MyConnectionFactory")
  private ConnectionFactory connectionFactory;

  @Resource(mappedName = "MyQueue")
  private Queue queue;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws  ServletException, IOException {

      try {
          Connection connection;
          connection = connectionFactory.createConnection();

          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
          MessageProducer messageProducer = session.createProducer(queue);

          TextMessage message = session.createTextMessage();

          for (int i = 0; i < 100; i++) {
              message.setText("This is message " + (i + 1));
              messageProducer.send(message);
          }
      } catch (JMSException e) {
          throw new RuntimeException(e);
      }
  }

}

The following MDB listens to MyQueue (thanks to the annotation @MessageDriven(mappedName = "MyQueue") and because it implements the MessageListener interface it takes a message when available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@MessageDriven(mappedName = "MyQueue")
public class StudentRegistrationService implements MessageListener {
    ...

  @Resource
  private MessageDrivenContext mdbContext;

  public void onMessage(Message inMessage) {
      TextMessage msg = null;

      try {
          if (inMessage instanceof TextMessage) {
              msg = (TextMessage) inMessage;
              logger.info("MESSAGE BEAN: Message received: " + msg.getText());
          } else {
              logger.warn("Message of wrong type: "
                      + inMessage.getClass().getName());
          }
      } catch (JMSException e) {
          mdbContext.setRollbackOnly();
          throw new RuntimeException(e);
      }
  }
}

Here is a sample output. As you can see, the messages are processed according to their input order but not necessarily by the same EJB (worker).

1
2
3
4
5
6
7
8
9
10
11
INFO: Sending message: This is message 1
INFO: Sending message: This is message 2
INFO: Sending message: This is message 3
INFO: MESSAGE BEAN: Message received: This is message 1
INFO: MESSAGE BEAN: Message received: This is message 2
INFO: Sending message: This is message 5
INFO: Sending message: This is message 6
INFO: MESSAGE BEAN: Message received: This is message 4
INFO: MESSAGE BEAN: Message received: This is message 5
...
INFO: MESSAGE BEAN: Message received: This is message 100

Consider the following exercises:

Exercise 19: Compare Message Driven Beans and Session Beans with asynchronous calls.

Exercise 20: Print out the thread-id. What do you observe?

Exercise 21: Create another MDB that consumes the same queue. What do you observe?

Exercise 22: Do the same (2 consumers) but using a Topic instead of a Queue.

Context Dependency Injection and the Rich Object Model

| Comments

[Rich object model] vs [anemic object model] is long running debate. While the latter encourages to use simple and stupid objects with little or no business in them, the rich object model advocates for a clean object design with inheritance, polymorphism and so on. The anemic object model is very popular among JEE partitioners because, in the past, the specification did not provide any mean to invoke services in business objects. Therefore, the anemic pattern uses so called “managers” that maintain references to other “managers”. A direct benefit is the clear separation of concerns between the different kind of objects. Basically, it splits processing and data. As this is anti-object oriented, the abstract design of such system is often very different from the actual implementation.

The portfolio example

As example, let us take a portfolio that contains a set of financial position. A financial position can be either a set of stock, or an amount in a given currency. To evaluate the actual portfolio value, we go through the positions and for each of them we ask the current quote for stock to the service QuoteService or the current value of a given currency to the CurrencyService. The next figure presents the “ideal” design.

An object oriented class diagram of the Portfolio management component.An object oriented class diagram of the Portfolio management component.

To achieve this, one need to access services from within business objects. Since EJB 3.1, Context and Dependency Injection (CDI) provides such a mechanism via the @Inject annotation. The only requirement is that the object that requires the service as well as the service to inject are so called “managed beans”. The trick is that not all objects are meant to be managed. Furthermore, having managed lists of object is very tricky to say the least. Fortunately, the EJB 3.1 and more specifically the CDI 1.0 specification provide a way to solve this. In CDI, the main component is the bean manager. This manager keeps track of the beans to inject via @Inject and other means. Instead of relying on annotations to provide injection, it is possible to use the good old Service Locator pattern. CDI 1.0 exposes the bean manager on JNDI with the name java:comp/BeanManager.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ServiceLocator {

  @SuppressWarnings("unchecked")
  public static <T> T getInstance(final Class<T> type) {
      T result = null;
      try {

          //Access to the current context.
          InitialContext ctx = new InitialContext();
          //Resolve the bean manager
          BeanManager manager = (BeanManager) ctx.lookup("java:comp/BeanManager");
          //Retrieve all beans of that type
          Set<Bean<?>> beans = manager.getBeans(type);
          Bean<T> bean = (Bean<T>) manager.resolve(beans);
          if (bean != null) {
              CreationalContext<T> context = manager
                      .createCreationalContext(bean);
              if (context != null) {
                  result = (T) manager.getReference(bean, type, context);
              }
          }
      } catch (NamingException e) {
          throw new RuntimeException(e);
      }
      return result;
  }
}

The client code is very simple. It consists in calling the ServiceLocatorwith the desired interface. For the sake of clarity, I did not show the ServiceLocator that takes a qualifier in addition to the interface. To add this feature, look at the getBeans(Type beanType, Annotation... qualifiers) method.

1
2
3
4
5
6
7
8
9
10
11
public class StockPos {

  private Long qty;
  private String stockId;

  Double evaluate() {
      StockQuoteService sqs = ServiceLocator.getInstance(StockQuoteService.class);
      return qty * sqs.getQuoteValue(stockId);
  }

}

Similarly, here is the code of the CurrencyPos object.

1
2
3
4
5
6
7
8
9
10
11
public class CurrencyPos {

  private Double amount;
  private String currencyId;

  Double evaluate() {
      CurrencyQuoteService sqs = ServiceLocator.getInstance(CurrencyQuoteService.class);
      return amount * sqs.getQuoteValue(stockId);
  }

}

Some thoughts on the Demeter law

Let me be clear, I do not recommend this approach everywhere. It is very important to not mix the objects responsabilities. Furthermore, in order to respect the Demeter law, a business must not directly call something outside of the current component. Calls to other components are always to be done through so-called consumers to have clear components boundaries. For instance, putting to much intelligence in JPA entities that can be detached and serialized may cause problems on the client side.

Conclusion

In this post, I showed a solution to consume services that are exposed via the CDI BeanManager. These services can be pure POJOs or EJBs. Nevertheless, this approach must be used with great care as it can blur the components boundaries and responsabilities.

Multi-Tenancy With EJB 3.1 and JPA 2.0

| Comments

Multi-tenancy is a recurrent non functional requirement. Indeed, many important IT-systems are meant to be shared among multiple tenants. The data are often distributed over several databases or schemas. This, for different reasons:

  • Security: The data belong to different customers and some level of isolation is required;
  • Performances: Distributing the data over multiple systems may help to master performance issues;
  • Legacy: Sometimes, old and new systems must cohabit for a (long) time;
  • Maintenability: A database or a schema can be updated without putting the rest of the application at risk.

Although data are distributed, the application code should remain tenant agnostic. Furthermore, choosing between the different tenants is often made at runtime based on credentials (e.g. user Joe has access to customer AAAA while user Jane sees data of customer BBB). Java EE 7 will address this problem and much more, but in the mean time here is the way that I use to address this problematic using EJB 3.1 and JPA 2.0

Overall architecture

First, let me start with the overall architecture as described below.

Multi-tenancy architecture with serveral datasourcesMulti-tenancy architecture with serveral datasources

In the above figure, the database is organized in schemas, with one application server datasource (DS) per schema and one persistence unit (PU) per datasource. It is also possible to use only one datasoure and to discriminate between schemas by setting the <property name="openjpa.jdbc.Schema" value="TenantX" /> property for each persistence unit (PU). This sets the default schema for the PU. Here is a persistence.xml file that provides one persistence unit per tenant.

The following code has been tested for Open-JPA but there is nothing specific to this implementation outside of the <provider>tag in the persistence.xmlfile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

  <persistence-unit name="Tenant1" transaction-type="JTA">
      <provider>
          org.apache.openjpa.persistence.PersistenceProviderImpl
      </provider>
      <jta-data-source>jdbc/Tenant1_DS</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
  </persistence-unit>


  <persistence-unit name="Tenant2" transaction-type="JTA">
      <provider>
          org.apache.openjpa.persistence.PersistenceProviderImpl
      </provider>
      <jta-data-source>jdbc/Tenant2_DS</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
  </persistence-unit>

</persistence>

The basic idea is that, instead of using @PersistenceContext, we inject our “own” multi tenant entity manager wraper. Then, at runtime, the multi-tenant entity manager loads the persistence context that corresponds to the current user context from JNDI. Please note that this only works for JTA-based persistence-units. Otherwise, the persistence context is not container-basd and therefore not exposed to JNDI. Moreover, without JTA, we loose container based transaction demarcation.

Let us first start with the client code. In other words, how to use the Multi-Tenant Entity manager.

Client Code

Here is the client code. In order to preserve thread-safety and transactionality, Data access objects are EJBs (@Stateless, @Stateful, @Singleton). The presented solution uses an entity manager that is wrapped and then injected using @Inject or @EJB. Thread-safety, transactionnality and performances are guaranted by the EJB 3.1 and JPA 2.0 specification as explained in the section Thread-safety and Transactionality. As shown below, the MultiTenancyWrapper delegates to a real entity manager and implements the EntityManager interface. Therefore, its use is very similar to a normal EntityManager injected via @PersistenceContext.

1
2
3
4
5
6
7
8
9
10
11
@Stateless
public class MyEJB implements MyEJBLocal {

  @Inject
  private MultiTenancyWrapper emWrapper;

  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void doSomething() {
      emWrapper.findAll(...);
  }
}

The Multi-Tenant EntityManager EJB

The MultiTenanEntityManagertWrapper simply wraps the entity manager that corresponds to the current user context. The trick is to configure it as an EJB in order to get the xml configuration feature via ejb-jar.xml. Another alternative would be to use the @PersistenceContexts and @PersistenceContext annotations. The main drawback being that, for each new tenant, not only the persistence.xml and ejb-jar.xml must be changed but also the Java code.

The JNDI context that is linked to the current request is injected in the MultiTenantEntityManager using the @Resourceannotation. As there is no creation of a new InitialContext the overhead is not significant. Actually, the @PersistentContext annotation does the exact same thing except that it is not specific to the user context. The MultiTenanEntityManagertWrapper implements the delegate pattern. This allows to use it (almost) transparently in client code. The main difference being the use of @Inject or @EJB over @PersistenceContext in the client code.

Using the session context that is specific to the caller bean (and thus the caller request/session) enables transparent support for thread-safety, security and transactionality.

1
2
3
4
5
6
7
package ejb;

import javax.persistence.EntityManager;

public interface MultiTenanEntityManagertWrapper extends EntityManager {

}

The method getMultiTenantEntityManager of the MultiTenanEntityManagertWrapperImpl extracts the EntityManager that corresponds to the current request from JNDI (we will see later how it has been put there). To that end, the method getMultiTenantEntityManagerfirst extracts the prinipal from the current EJB context (SessionContext). After what, the tenant that corresponds to the current user is used to obtain the JNDI name of the corresponding entity manager. MultiTenanEntityManagertWrapperImpl simple delegates every call to the this Request specific EntityManager.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Stateless
public class MultiTenanEntityManagertWrapperImpl implements MultiTenanEntityManagertWrapper {
  
  private static final String JNDI_ENV = "java:comp/env/persistence/";

  @Resource
  SessionContext context;

  
  private EntityManager getMultiTenantEntityManager() {
      //Extract the name of the current user.
      Principal p = context.getCallerPrincipal();

      //Lookup the tenant name for the current user
      //This is application specific
      Users u = Users.getUser(p.getName());

      //Produces either TENANT1 or TENANT2       
      String tenantName = u.getSite().toString();

      String jndiName = new StringBuffer(JNDI_ENV).append(tenantName).toString();
      //Lookup the entity manager
      EntityManager manager = (EntityManager) context.lookup(jndiName);
      
      if (manager == null) {
          throw new RuntimeException("Tenant unknown");
      }
      return manager;
  }


  //The delegates
  @Override
  public void persist(Object entity) {
      getMultiTenantEntityManager().persist(entity);
  }


  @Override
  public <T> T merge(T entity) {
      return getMultiTenantEntityManager().merge(entity);
  }


  @Override
  public void remove(Object entity) {
      getMultiTenantEntityManager().remove(entity);
  }

        ...
}

Now let us see how to put the entity manager references in JNDI. In order to avoid a lot of annotations (one per tenant) and therefore to be able to handle a huge number of tenans, I propose to use the ejb-jar.xml file to configure the EJB intead of the PersistenceContext annotation. The MultiTenantEntityWrapperEJB is configured as a stateless EJB. Ther persistence contexts are simply exposed to JNDI with the following pattern: java:comp/env/persistence/TENANTX. For more information please look at the EJB 3.1 specification chapter 16.11.1.

<persistence-unit-name>Tenant1</persistence-unit-name> is the name of the PU as defined in the persistence.xml file. <persistence-context-ref-name>persistence/TENANT1</persistence-context-ref-name>defines the name of the entity manager that is exposed via JNDI.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1">


  <enterprise-beans>
      <session>
          <ejb-name>MultiTenantEntityWrapper</ejb-name>   
          <ejb-class>ejb.MultiTenantWrapperImpl</ejb-class>
          <session-type>Stateless</session-type>

          <!-- Persistece contexts -->
          <persistence-context-ref>
              <description>Tenant 1</description>             
              <persistence-context-ref-name>persistence/TENANT1</persistence-context-ref-name>        
              <persistence-unit-name>Tenant1</persistence-unit-name>
              <persistence-context-type>Transaction</persistence-context-type>
          </persistence-context-ref>

          <persistence-context-ref>
              <description>Tenant 2</description>             
              <persistence-context-ref-name>persistence/TENANT2</persistence-context-ref-name>        
              <persistence-unit-name>Tenant2</persistence-unit-name>
              <persistence-context-type>Transaction</persistence-context-type>                
          </persistence-context-ref>
          
      </session>
  </enterprise-beans>

</ejb-jar>

Thread-safety and Transactionality

As this is compliant with both the EJB 3.1 and JPA 2.0 specification, thread-safety and transactionnaly are guaranteed by the container. For more details please look at the EJB 3.1 specification at chapters 16.10, 16.11 and the JPA 2.0 specification at chapter 7.6. Of course, the wrapper has to be an EJB in order to have access to the current JNDI context without having to create it. Furthermore, because the EntityManageris not per se thread-safe (JPA 2.0, chapter 7.2), the serialization of the invokations that is provided by the container for EJBs is essential the thread-safety aspect (EJB 3.1, chapter 4.10.13).

Conclusion

In this post, I showed how to leverage EJB 3.1 and JPA 2.0 standard features to provide multi-tenancy. The presented approach is thead-safe, it preserves transactionaly and does not induce a significant overhead.

About Sessions, Conversations, and the Garbage Collector

| Comments

A couple of days ago, I had a discussion with a developer about the notion of web conversation. More precisely, about its utility. During this discussion, we ran into some basic misconceptions that, IMHO, no web developer must do. Conversation (or flows) are good features of the recent frameworks (Spring, JSF) because they allow to save information across several user requests without putting them into the session. For instance, this can be very useful for wizards. Putting these information into the session asks for manual maintenance, and in particular for manual collection. This is usual error prone and should be avoided. The problem being that the user rarely logs out before closing the browser. Thus, HttpSession.invalidate() does not get a chance to be called and the session remains active until the timeout occurs (usually 20 minutes later).

The person I was talking with, though that it is not necessary to care about that. In his view, the garbage collector will take care of this and that it can be forced. We discuss the matter a bit deeper and here are some myths that I think must be rebutted.

First assumption: I can force the garbage collection

This is not true, actually according to the Java documentation:

1
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

System.gc() suggests the garbage collection, it does not enforce it. This signals that you would like the garbage collector to do its job, but there is no guarantee whatsoever. It is only possible to enforce garbage collection by writing your own garbage collector, but you cannot expect all garbage collectors of all the possible VM to act similarly. Therefore, relying on this assumption is not portable.

Second assumption: If I close the browser the session and its objects are collected

Even If it would be possible to enforce the garbage collection, it is of no use as long as there remains a single reference to the objects to collect. Again, this is absolutely not the case. Remember that closing the browser does not mean anything to the server. It would, in theory possible to imagine something with an ajax call that traps the close event of the browser and does a HttpSession.invalidate() . This is quite complex to do in a cross-browser manner and gives no guarantee. Therefore, the data attached to the session will be kept in memory until the session timeout. This is precisely the beauty of conversation scopes, the developer just tells when the conversation starts and when it ends. Usually, user do not stop in the middle of a conversation, they tend to finish it. At least, more often that they click on logout.

Third assumption: Anyway this does not represent a huge amount of memory.

Let us take a simple example: a standard business application that, at some point in the business process, requires a tree for shop selection. This kind of interactions requires several client-server communications and therefore several requests. A temptation would be to put the tree in the session scope. Let us say that 10,000 (logical) users log into the application, for instance from 09:00 am to 09:30 am. If each session requires 100 KB (trees are huge even with lazy loading), we end up with 1G memory(only for the tree). As most of the users do not click on logout, you rely on the timeout to free these objects.

Conclusion

Using request scope of conversation scope over session scope is a good practice as it frees you from managing the garbage collection. The code is therefore cleaner and more efficient. This can be done with JSF’s @ConversationScoped or with Spring Webflow’s Conversation.

Object-XML Mapping With JAXB & MOXy

| Comments

Object-Relational mapping is around for a while and its last incarnation, JPA 2.0, is easy to use yet powerful and adapted to most of the real-life situations. A problem that is similar to Object-Relational mapping (ORM) is Object-XML mapping (OXM). More precisely, it aims at mapping XML schemas to JAVA classes. JAXB (JSR 222) specifies how to maps classes to xml schemas. In this post, I demonstrate the ease of use of this approach using MOXy. MOXy is the Eclipse implementation of JAXB and I found it really easy to use.

As always let us first look at the Maven dependencies:

Maven dependencies for using MOXy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<repositories>
        <repository>
            <id>EclipseLink Repo</id>
            <name>EclipseLink Repository</name>
            <url>http://download.eclipse.org/rt/eclipselink/maven.repo</url>
        </repository>
</repositories>

<dependencies>

    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.3.2</version>
        <scope>compile</scope>
    </dependency>
    ...

</dependencies>

Eclipse-link provides an implementation for JAXB. The rest is in the JEE 6 SDK.

In this post I only consider the case in which we have control over the schema. In this case, it is sufficient to annotate the fields and the classes you want to marshall to XML. Let us use the JEE-6-Demo project that can be found on Google Code. The following snippet shows a simple model that represents a student.

As you can see there are few annotations. The first one @XmlRootElement simply declares what the root element is. The second annotation specifies the mapping policy. We will come back on that later. The fields are either not annotated or annotated with @Transient. In the first case, they are marshaled if not null and in the second they are simply ignored. The only tricky part is that transient fields (in the Java sense) are ignored. For instance, this is the case of the gender property.

A simple mapping from object to XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Student implements Serializable {

    private Long id;

    private String lastName;

    private String firstName;

    private Date birthDate;

    @XmlTransient
    private PhoneNumber phoneNumber;

    private transient Gender gender;

    @XmlTransient
    private Address address;

    @XmlTransient
    private List<Grade> grades;

    ...

    @XmlTransient
    private Badge badge;
    ...
}

Let us now test the mapping. The code below, creates a new Student and fills the associated fields. The second part of the snippet marshals the object into XML and streams it to System.out.

Creation of student and its marshaling to XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Student student = new Student("Lion Hearth", "Richard", new Date());
Address address = new Address();
address.setCity("Carouge");
address.setNumber("7");
address.setPostalCode("1227");
address.setStreet("Drize");
student.setAddress(address);
Badge b = new Badge();
b.setSecurityLevel(30L);
b.setStudent(student);
student.setBadge(b);
student.setPhoneNumber(new PhoneNumber(0, 0, 0));
for (Discipline d : Discipline.values()) {
    Grade g = new Grade(d, 10);
    student.getGrades().add(g);
}

JAXBContext jaxbContext = JAXBContext.newInstance(Student.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(student, System.out);

Finally, the result looks like the XML below. As you can see, it is pretty easy and straight-forward to produce XML from a Class description. Most of the fields that have been populated are not marshaled to XML. This is due to the @XMLTransient annotation that tells JAXB not to consider them for output.

Marshaled version of the previous Student object.
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    <lastName>Lion Hearth</lastName>
    <firstName>Richard</firstName>
    <birthDate>2012-06-04T11:12:34.751+02:00</birthDate>
</student>

Mapping Overview

The previous example was as simple as possible. Obviously, sometimes it is important to be able to tweak the mapping. Let us look at some simple mapping options.

Element naming

The default mapping rule is to use the field name as XML element name. This policy can be overridden by the @XmlElement(name = ...) annotation. Applying the annotation @XmlElement(name="last_name") on the lastName field of the previous example would result in:

Example of named element
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    <last_name>Lion Hearth</last_name>
    <firstName>Richard</firstName>
    <birthDate>2012-06-04T11:12:34.751+02:00</birthDate>
</student>

Attributes vs elements

By default fields are marshaled as XML elements. It is possible to ask JAXB to transform them to XML attributes by using @XmlAttribute annotation. Putting @XmlAttribute on the lastName field of the previous example would produce the following XML:

Example of using an attribute instead of an element
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student lastName="Lion Hearth">
    <firstName>Richard</firstName>
    <birthDate>2012-06-04T11:12:34.751+02:00</birthDate>
</student>

Please note that as for an element, the attribute name can be customized.

Mapping strategy

As mentioned before, the default mapping strategy is declared by using the @XmlAccessorType(XmlAccessType.*) annotation.

There exists four mapping policies. For more details, look at the Javadoc for XmlAccessorType. Here is an excerpt from the Java doc.

  1. FIELD: Every non static, non transient field in a JAXB-bound class will be automatically bound to XML, unless annotated by XmlTransient.
  2. NONE: None of the fields or properties is bound to XML unless they are specifically annotated with some of the JAXB annotations.
  3. PROPERTY: Every getter/setter pair in a JAXB-bound class will be automatically bound to XML, unless annotated by XmlTransient.
  4. PUBLIC_MEMBER: Every public getter/setter pair and every public field will be automatically bound to XML, unless annotated by XmlTransient.

Name spaces

An important aspect of XML is its modularity. In particular, namespaces bring a nice way to organize the XML and the schemas. Namespaces can be specified at different levels. For more details look at the MOXy documentation. For now, it is sufficient to known that the @XmlType, @XmlElement, and @XmlAttribute annotations support a namespace attribute.

One to one mapping

Now that we have mapped simple field, let us look at more complex mappings. First, a 1-1 mapping. The following example maps an address.

Add a one to one mapping
1
2
3
4
5
6
7
8
9
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Student implements Serializable {

    ...

    private Address address;

}

To that end, it is sufficient to add the following annotations to the Address type.

Add a one to one mapping
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@XmlRootElement(name = "address")
@XmlAccessorType(XmlAccessType.FIELD)
public class Address implements Serializable {
    ...
    /** house number. */
    private String number;

    /** the name of the street. */
    private String street;

    /** the city name. */
    private String city;

    /** the postal code. */
    private String postalCode;
    ...
}

And the rest is handled by JAXB to produce the following result.

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    ...
    <address>
        <number>7</number>
        <street>Drize</street>
        <city>Carouge</city>
        <postalCode>1227</postalCode>
    </address>
</student>

Bi-directional one to one

The next example is more tricky. The problem with bi-directional mapping is that they produce graphs. Of course, since XML are trees, we must avoid cycles. The solution is to annotate the reverse mapping (Student student in this case) with @XMLTransient causing the property to be ignored by JAXB.

Add a one to one bidirectional mapping
1
2
3
4
5
6
7
8
9
@XmlRootElement(name = "student")
@XmlAccessorType(XmlAccessType.FIELD)
public class Student implements Serializable {

    ...

    private Badge badge;

}

The following type describes the Badge that has a reverse mapping to Student.

Mapping of the type “Badge“
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@XmlRootElement(name = "badge")
@XmlAccessorType(XmlAccessType.FIELD)
public class Badge implements Serializable {

    /** The unique id. */
    private Long id;

    /** The student's security level. */
    @XmlAttribute
    private Long securityLevel;

    /** The student that owns this badge. */
    @XmlTransient
    private Student student;

And finally, here is the result.

Result of the bi-directional mapping
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    ...
    <badge securityLevel="30"/>
</student>

One to many mapping

One to many mappings are handled automatically. There is nothing special to do. In our example, removing the @XmlTransient annotation on the grades property will generate the following output:

One to many example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    <last_name>Lion Hearth</last_name>
    <firstName>Richard</firstName>
    <birthDate>2012-06-05T10:57:36.699+02:00</birthDate>
    <phoneNumber>+00-0000-0000</phoneNumber>
    <address>
        <number>7<number>
        <street>Drize</street>
        <city>Carouge</city>
        <postalCode>1227</postalCode>
    </address>
    <grades>
        <discipline>MATHEMATICS</discipline>
        <grade>10</grade>
    </grades>
    <grades>
        <discipline>BIOLOGY</discipline>
        <grade>10</grade>
    </grades>
 ...
    <badge securityLevel="30"/>
</student>

Custom mapping

Sometimes, it is difficult to map a given type to a given XML structure. This is the case of the PhoneNumber type in our example. To that end, it is possible to define a XMLJavaTypeAdatper that will convert XML to object and objects to XML manually. The adapter is not very difficult to implement. It is composed of two methods that respectively unmarshal from XML and marshal to XML.

1
2
3
4
5
6
7
8
9
10
11
12
public class PhoneNumberAdapter extends XmlAdapter<String, PhoneNumber> {

    @Override
    public PhoneNumber unmarshal(final String value) throws Exception {
        return PhoneNumber.getAsObject((String) value);
    }

    @Override
    public String marshal(final PhoneNumber value) throws Exception {
        return PhoneNumber.getAsString((PhoneNumber) value);
    }
}

Then, it is required to annotated the property with this adapter:

Using a custom XML-Object Adapter
1
2
3
4
...
@XmlJavaTypeAdapter(PhoneNumberAdapter.class)
private PhoneNumber mPhoneNumber;
...

This will produce the following result:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    <last_name>Lion Hearth</last_name>
    <firstName>Richard</firstName>
    <birthDate>2012-06-05T10:57:36.699+02:00</birthDate>
    <phoneNumber>+00-0000-0000</phoneNumber>
    ...
</student>

What about XML schemas

As mentioned previously, we assumed that you have total control over the schema. Nevertheless, it can be useful to be able to produce this schema. This is done by the following snippet.

Output the underlying schema
1
2
3
4
5
6
7
8
9
10
SchemaOutputResolver sor = new SchemaOutputResolver() {
    @Override
    public Result createOutput(final String namespaceUri,
            final String suggestedFileName) throws IOException {
        Result result = new StreamResult(System.out);
        result.setSystemId("System.out");
        return result;
    }
};
jaxbContext.generateSchema(sor);

Write XML

Writing XML is fairly easy, just populate the objects that you want to marshal and then use the following code:

How to marshal a given object
1
2
3
4
JAXBContext jaxbContext = JAXBContext.newInstance(Student.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(student, System.out);

Read XML

The reverse operation is as easy and straightforward (provided that use the same schema):

How to unmarshal a given XML file to objects
1
2
3
4
InputStream stream = StudentOXTest.class.getResourceAsStream("/student.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Student.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Student student = (Student) unmarshaller.unmarshal(stream);

Conclusion

We have seen how to use MOXy to map objects to XML. Using JAXB annotations, it is very easy to read and write XML. The examples used in this blog are to be found in the JEE-6-Demo project on Google code hosting.

Verification & Validation

| Comments

I’ve read many articles (tutorials, books, courses, forums…) about Verification & Validation. One think that really strikes me is the lack of consistency and the fuzziness among the definitions or more precisely among the interpretations. As I do think that something cannot be understood completely if it is not be expressed clearly, I propose a mini-serie of blog posts to clarify Verification & Validation and the associated activities. I will try to give simple and consistent (at least in my point of view) definitions. Sure, this is a rehash of well-known stuff but putting everything at the same place seems worth to me. I do not pretend to know best and thus feel free to comment on this post to correct me or to suggest other explanations and definitions. My only purpose is to help to better understand these words and the underlying concepts.

Verification & Validation

Most of the literature on the subject distinguish between Verification and Validation. The usual way (taken from Barry Boehm) to sum up the difference between the two is to say that:

Verification consist in checking that we are building the product right, and validation consists in checking building the right product.

I am not very satisfied with this definition. Although it sounds good, it raises the question of what it does mean to built a product right and what the right product is. Let’s go back to the roots by looking at the definitions of these words in the Merriam-Webster dictionary.

Verification: the act or process of “establishing the truth, accuracy, or reality of a claim”.
Validation: the act or process of “making legally valid”.

To summarize, my understanding is that the general sense of verification is to prove a claim whereas validation aims at declaring something legal or official (i.e. something that comply to a set of rules or regulations). Of course this raises the question of what, in the context of software systems, is a claim and what is legal/official. This leads us to the next section that defines terms such as requirements, and specification.

Requirements & Specification

Again, let’s lookup the meaning of these words in the Merriam-Webster dictionary:

Requirement: the need for a particular purpose; depend on for success or survival.
Specification: the act of describing or identifying something precisely or of stating a precise requirement.

A requirement expresses a need upon which the success of the project depends. Whereas, a specification is a precise description of a requirement. Now let us look at the standard definitions in Software Engineering.

Software Requirements & Specification

As a software systems is usually developed in response to someone needs (or supposed needs), it must satisfy that person, that group of person, or that organization needs. Furthermore, it must often comply to a set of regulations or other expectations. This leads us to the following concept:

Requirements represent what the stakeholders expect from the system. It is important to note that the stakeholders can be end-users, power-users or even internal or external regulatory entities such as government agencies that enforce laws and regulations. Stakeholder requirements do not take the feasibility into account nor do they take technical details into account. They only state their problem or expectations.

As it is not possible to have access to all stakeholders at any time during the development process (for instance, to ask questions), it is necessary to capture their requirements in a persistent form. In the following, I call the role that capture the stakeholder requirements: the business analyst.

Specifications capture in a written form what a business analyst understood from the requirements. This written form is usually expressed in natural language or is a mixed of natural language and semi-formal, or formal description. The specifications describe implementable requirements and how to meet them. Therefore, they propose a solution to the problem.

Interestingly enough, there is the same kind of semantical difference between requirements and specifications as between verification and validation. This is the basis that helps to understand the subtle yet important difference between the two terms, in particular in the context of the development of software systems.

It is important to understand is that the specifications are derived from the interpreted requirements and therefore specifications cannot be sound and complete. In other words, there may be things that are over-specified (not sound) and things that are under-specified (not complete).

Let’s imagine for a second that a perfect business analyst did capture exactly what the stakeholders had in mind. This perfect specification must still be implemented and therefore we must ensure that implementation does satisfy the specification (and by transitivity the stakeholders needs).

A software system does reflect the stakeholder requirements if the following hypotheses hold:

  1. All stakeholders expresses their needs in a sound and complete set of requirements;
  2. a business analyst captures these requirements in a sound and complete specification (with respect to the requirements);
  3. the development team understands and implements this specification in a sound and complete way;

Of course non of these hypotheses hold in a real industrial setting but we have to admit them to be able to realize a system. In order to minimize the risk of diverging from the stakeholders requirements to much we need a process to ensure that the final system agrees to a certain degree to the stakeholders requirements. This a the role of verification and validation.

Software Verification & Validation

The figure below illustrates the difference between verification and validation and where they take place in the development process. Building a software system consists in capturing the stakeholders’ requirements into a persistent description, called informal specifications (e.g., Use Cases, storyboards, …). This specifies what problems the system addresses. At this stage a number of interpretation mistakes may have occurred leading to incorrect specifications. To limit these problems, the informal specifications must be explained to the user and validated. Developers require non-ambiguous specification to work on. Thus, a design (e.g., UML diagrams) are derived from the informal specifications . Similarly, the quality assurance team derives a formal specification (e.g, Petri nets, test cases, metrics, …). The design and later the implementation are then verified with respect to this formal specification. To a certain extend, the formal specification must itself be validated by the stakeholders.

Verification and ValidationVerification and Validation

Verification stands for the process of evaluating whether a software system satisfies the specified requirements. On the design level, it can be achieved by simulation or model checking. On the implementation level, it can be achieved by different kind of testing, code review, static analysis, and metrics. In other words: “Did we build the system right (with respect to specified requirements)?”.

Validation stands for the process of evaluating whether a software system satisfies the stakeholder requirements and intended uses . This is, for instance, achieved by User Acceptance Tests and by submitting the final system to certification authorities. In other words: “Did we build the right (with respect to stakeholder requirements) system?”.

Conclusion

Stakeholders cannot be available at any time of the development. Therefore, it is necessary to build a persistent view (i.e., specification) of their needs (i.e., requirements). The activity of checking whether the design and the implementation fulfill the specification is called Verification Some details may be lost in the translation from the requirements to the specification. Therefore, at each phase of the development of a software systems, we must check that what has been specified and later implemented during that phase reflect the stakeholders’ expectations. This activity is called validation . Integrating these two concepts as first class citizen, is one of the major benefits of agile methods. Because the interpretation of the stakeholder requirements and later the translation from the informal specifications to the formal specifications may be incomplete or incorrect, it is necessary to often go back to the customer or the stakeholders to confirm that the product is on the good track. This is one of the major benefits of iterative and incremental development.

A JEE6 Security Interceptor for Tomcat 7

| Comments

Security in Java EE is a well-known subject and JAAS, the framework that manages security, is stable and reliable. Nevertheless, its API is quite low level and not always very convenient. For that reason, there exist a number of frameworks that have been built on top of JAAS that provide nice abstractions and convenient tools. This is especially true for the JEE application servers such as Glassfish, JBoss and the like.

In servlet containers such as Tomcat or Jetty however, only the web components are secured and it is not trivial to secure services and the data access layer. This can be solved by integrating framework such as Spring Security, Apache Shiro.

As always it is not always possible to put a new framework or library in place. I will not discuss whether it is a good or a bad idea to develop a new security mechanism. Nevertheless, a good rule of thumb is to reuse existing components and not reinvent the wheel … when possible. If for let’s say licensing reasons, it is not possible: here is a way to provide a simple declarative authorisation procedure based on JAAS and the JEE6 interceptors. The objective is to propagate the authorisation to non-web layers such as services or data access layer through a thread-local variable.

The goal is to be able to write something similar to the following snippet. The idea is to annotate a method (or a class) with a list of roles that are authorised. If the method executes in a context in which a user has not enough rights, it raises an exception.

Example of a service layer protected by JEE6 interceptor
1
2
3
4
5
6
7
8
9
@Secure(roles = { "user" })
public List<Student> getAll() {
    ...
}

@Secure(roles = { "admin" })
public void add(final Student student) {
    ...
}

Java Authentication and Authorisation System

Java Authentication and Authorisation System (JAAS) provides a security infrastructure for JAVA. Both authentication (are you who you pretend to be?) and authorisation (are you allowed to do something you would like to do?) are covered. JAAS relies on the concept of principal. A principal is a particular identity of a user (e.g. social security id, driver licence id, …). By default, in JAVA SE, there is no easy way to have the list of roles granted to a given user. To solve that problem, we need a bean that knows to which role a given Principal is authorised. This is the role of MyPrincipal.

A custom principal that contains the roles
1
2
3
4
5
6
7
8
9
10
11
public class MyPrincipal implements Principal, Serializable {

    public MyPrincipal(final Principal pPrincipal, final List<String> pRoles) {
        this.principal = pPrincipal;
        this.roles = pRoles;
    }
    ...
    public boolean isUserInRole(final String pRole) {
        return roles.contains(pRole);
    }
}

JEE6 Interceptors

Since JEE6, a feature called interceptors enables simple Aspect Oriented Programming without using any specific framework. It works, of course, only on managed classes. Namely, classes that are instantiated by CDI through dependency injection.

Just to fix the vocabulary, here some definition about Aspect Oriented Programming:

  • Advice: code at it executed at a certain point in the code. This point is called a join point;
  • Join point: place in the code at which a given advice is executed.;
  • Pointcut: set of join point, usually described by a meta data that can be internal or external to the program (xml, annotations);
  • Aspect: advice + its pointcut;

In Java EE6, an interceptor is made of an annotation that characterizes an aspect and an implementation for that annotation. The annotation is placed at a join point, that is a place in the code where a specific advice must be executed. Usually around a method call. However, JEE6 interceptors are not as powerful as advanced AOP frameworks such as AspectJ, it provides enough facility to decouple non-functional behaviors from the business code. That is exactly what we want to achieve here. Let us now illustrate JEE6 interceptors through the implementation of a declarative security annotation that protects calls to the service layer.

A meta data that asks for security

The first thing is to declare an annotation that is parametrized by an array of String that represents roles. This is presented in the following snippet. The annotation InterceptorBinding is required to mark the annotation as a pointcut. The @Retention(RetentionPolicy.RUNTIME) declares that Then @Target({ ElementType.METHOD, ElementType.TYPE }) tells that the annotation can be applied at both method level and type level. Finally, the member String[] roles(); declares that the annotation has a parameter called roles.

Secure.java
1
2
3
4
5
6
7
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface Secure {
    @Nonbinding
    String[] roles();
}

The interceptor (advice) that check the authorisation

The next step is to program an advice. To that end, a simple class must be annotated by the annotation @Interceptor and by the annotation that it implements @Secure(roles = { }) (i.e. the pointcut). The method that is annotated by @AroundInvoke is executed by the container when it encounters a method annotated by @Secure (i.e. join point). The name of the method (e.g. invoke ) does not matter as long as it returns an Object and it accepts an InvocationContext as a parameter. This context contains information about the intercepted method.

About the method itself, getRoles is a private method (given hereafter) that extract the list of roles that are authorised to this method. The SecurityContext is described below and is container for the ThreadLocal variable that contains the principal of the current user. The method principal.isUserInRoles(roles) returns true if one the roles matches the expected authorisation. If it is not the case an exception is raised and the interceptor stops there without having executed the intercepted method. Otherwise, the interceptor goes on and executes the intercepted method and finally returns its return value by executing return context.proceed() .

SecurityInterceptor.java CDI Interceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Secure(roles = { })
@Interceptor
public class SecurityInterceptor implements Serializable {

    @AroundInvoke
    public Object invoke(final InvocationContext context) throws Exception {
        String[] roles = getRoles(context.getMethod());
        MyPrincipal principal = SecurityContext.getPrincipal();

        if (!principal.isUserInRoles(roles)) {
            throw new IllegalAccessException("Current user not autorised!");
        }

        return context.proceed();
    }

    private String[] getRoles(final Method method) {
        ...
    }
}

The private method getRoles scans the class of the method that has been intercepted in order to discover the list of roles. First it scans at method level (method.isAnnotationPresent ) to find the annotation Secure.class that has been described above. If it does not find the proper annotation then it scans at class level (method.getDeclaringClass().isAnnotationPresent ). Remember that we allow to put the annotation at the method level AND at the class level.

Method that scans the caller for annotation parameters
1
2
3
4
5
6
7
8
9
10
11
private String[] getRoles(final Method method) {
    if (method.isAnnotationPresent(Secure.class)) {
        return method.getAnnotation(Secure.class).roles();
    }

    if (method.getDeclaringClass().isAnnotationPresent(Secure.class)) {
        return method.getDeclaringClass().getAnnotation(Secure.class).roles();
    }

    return null;
}

The last step to activate the interceptor is to declare it in the beans.xml file. Remember that it works thanks to CDI and only for the beans managed by CDI. By default, interceptors are disabled.

beans.xml CDI descriptor
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<beans 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://jboss.org/schema/cdi/beans_1_0.xsd">
    <interceptors>
        <class>ch.demo.business.interceptors.SecurityInterceptor</class>
    </interceptors>
</beans>

How to populate the ThreadLocal variable with principal information

So far, we did intercept the method call and check whether the current principal associated with the thread is authorised to access to a the intercepted method. The problem is that in servlet containers the security is at web level and we would to propagate this information. To that end, we will use the concept of thread local variables.

The following class contains a thread-local variable principalHolder that holds the current (thread-local) principal. This assumes that a thread is processed by one and only one thread from A to Z. This is the case for servlet engines but not always for application servers. In the latter case, the vendor-specific security mechanism is much better as it takes things such as clustering into account. The method setPrincipal is invoked at the beginning of a new request when it is authenticated and authorised at the web level. removePrincipal cleans up the Thread-Local value at the end of the request processing.

SecurityContext.java Thread-local container for the principal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public final class SecurityContext implements Serializable {

    private static InheritableThreadLocal<MyPrincipal> principalHolder =
                new InheritableThreadLocal<MyPrincipal>();

    private SecurityContext() { }

    public static MyPrincipal getPrincipal() {
        if (principalHolder.get() == null) {
            principalHolder.set(new MyPrincipal(null, null));
        }
        return (MyPrincipal) principalHolder.get();
    }

    public static void setPrincipal(final MyPrincipal principal) {
        principalHolder.set(principal);
    }

    public static void removePrincipal() {
        principalHolder.remove();
    }
}

The last step is to populate the principal and its associated roles to the thread-local container when the request is initialized. For that purpose, we use a request listener that is invoked when a new request has been submit and just before its destruction. On initialization, the method getMyPrincipal extracts the principal from the request request.getUserPrincipal(). The resulting principal is put in the thread-local by SecurityContext.setPrincipal.

getMyPrincipal also goes through the list of roles and adds the authorised roles using request.isUserInRole from HttpServletRequest.

SecurityListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class SecurityListener implements ServletRequestListener {

    private static List<String> roles = null;

    @Override
    public void requestInitialized(final ServletRequestEvent sre) {
        SecurityContext.setPrincipal(getMyPrincipal((HttpServletRequest) sre.getServletRequest()));
    }

    @Override
    public void requestDestroyed(final ServletRequestEvent sre) {
        SecurityContext.removePrincipal();
    }

    public static MyPrincipal getMyPrincipal(final HttpServletRequest request) {
        if (roles == null) {
            roles = getSecurityRoles(request.getServletContext());
        }

        Principal principal = (Principal) request.getUserPrincipal();
        List<String> currentRoles = new ArrayList<String>();
        for (String role : roles) {
            if (request.isUserInRole(role)) {
                currentRoles.add(role);
            }
        }
        return new MyPrincipal(principal, currentRoles);
    }

    public static synchronized List<String> getSecurityRoles(final ServletContext ctx) {
        ...
    }
}

The next method is not very elegant but this is the only way that have found to extract the role list that is required by the current web application. It parses the web.xml, looking for role-name elements that describe a role.

Extract the role list from web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static synchronized List<String> getSecurityRoles(final ServletContext ctx) {
    List<String> r = new ArrayList<String>();
    InputStream is = ctx.getResourceAsStream("/WEB-INF/web.xml");

    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware(true);
    try {
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(is);
        doc.getDocumentElement().normalize();

        NodeList elements = doc.getElementsByTagName("role-name");
        for (int i = 0; i < elements.getLength(); i++) {
            r.add(elements.item(i).getTextContent().trim());
        }
    } catch (Exception e) {
        new IllegalAccessException(e.getMessage());
    }
    return r;
}

Finally, the listener is enabled by putting the following lines in web.xml.

web.xml
1
2
3
<listener>
    <listener-class>ch.demo.web.SecurityListener</listener-class>
</listener>

Whenever there is not redirect (that triggers a new request) after login or there is a manual call to JAAS, the principal must be manually set into thread-local right after the login. This is because if the security is checked right after authentication and the listener has already been called (at the beginning of the request) it has been set to an invalid principal.

1
2
request.login(user, password);
SecurityContext.setPrincipal(SecurityListener.getMyPrincipal(request));

Conclusion

In this post, we have seen how to write a JEE6 interceptor to authorise access to service level methods in servlet containers. The examples used in this blog are to be found in the JEE-6-Demo project on Google code hosting.

Using Selenium for Web Integration Testing

| Comments

Following up on my previous posts (here and here about integration testing of JEE web applications, I will present how to write smoke tests using Selenium. The idea is to detect whether important regressions have been introduced. This is especially useful to detect configuration and navigation problems. I’ve split the test in three parts:

  1. starting and stopping the container. Embedded Tomcat 7 in our case. This is described here;
  2. building the WAR file to test. To that end, you can look at this post that describes how to build such a test archive using Shrinkwrap;
  3. finally, we must build the test case. This is the goal of this post.

Testing a use case requires to be able to:

  1. get a page at a given URL;
  2. input test data into the web elements;
  3. assert whether the server answers as expected.

Selenium provides an easy API to fetch URLs As these are smoke tests, using the HtmlUnitDriver instead of a specific browser is sufficient. We do not want to detect minor display problems but rather important functional problems.

Selenium has many different drivers for many different browser. The problem is that it opens the browser in a new window. I prefer to have the continuous integration running headless.

The following dependencies are required to run the tests.

Maven dependencies
1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>2.20.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>net.sourceforge.htmlunit</groupId>
    <artifactId>htmlunit</artifactId>
    <version>2.9</version>
    <scope>test</scope>
</dependency>

First, let’s build a new headless driver. This object simulates the browser. It manages the HTTP part as well as parsing the HTML and the javascript code that is returned.

1
WebDriver driver = new HtmlUnitDriver();

The next step is to ask the driver to load the home page that we want to test. For convenience, in my previous posts I defined a method that returns the current Tomcat port and the application context.

1
driver.get("http://localhost:" + getTomcatPort() + "/" + getApplicationId());

Let’s assume that the home page redirects to a login page that has two text boxes (respectively called username and password). The following snippet uses XPATH expressions to locate web elements. First, it locates a HTML element of type input that has an attribute id set to username. If this web element is not present, the driver will raise an exception. This allows to easily detect whether a widget has been accidentally removed.

1
WebElement username = driver.findElement(By.xpath("//input[contains(@id,'username')]"));

Now we can interact with the previous element. For instance, to simulate a user that types in its username (admin).

1
username.sendKeys("admin");

After that, Let’s do the same for the web element called password.

1
2
WebElement password = driver.findElement(By.xpath("//input[contains(@id,'password')]"));
password.sendKeys("admin");

Finally, we locate a button called loginand we simulate a click on it.

1
2
WebElement login = driver.findElement(By.xpath("//button[contains(@id,'login')]"));
login.click();

On successful login, our example redirects to a page that contains a list of students. The following assertion checks that the string Student list exists somewhere is the returned HTML source code.

1
Assert.assertTrue(driver.getPageSource().contains("Student list"));

With this approach, it is also very easy to do trivial security testing. For instance, let’s check that the application redirects (or forwards) the user to the login page upon unsuccessful login.

1
2
3
4
5
6
7
8
9
WebElement username = driver.findElement(By.xpath("//input[contains(@id,'username')]"));
username.sendKeys("foo");
WebElement password = driver.findElement(By.xpath("//input[contains(@id,'password')]"));
password.sendKeys("foo");
WebElement login = driver.findElement(By.xpath("//button[contains(@id,'login')]"));
login.click();
Assert.assertTrue(driver.getPageSource().contains("username"));
Assert.assertTrue(driver.getPageSource().contains("password"));
Assert.assertTrue(driver.getPageSource().contains("login"));

Conclusion

In this post, we have seen how to write smoke integration tests with Selenium. This is especially useful to detect whether an important functionality has been hindered. For instance, a change in the navigation or a unexpected change of the status (availability, visibility) of one the buttons or web elements. I recommend implementing the three or four major scenarios with this technique. This is usually enough to detect major problems. The examples used in this blog are to be found in the JEE-6-Demo project on Google code hosting.

Embedded Web Application Integration Testing Using Tomcat 7 and JUnit

| Comments

To follow up on my previous post about how to programmatically build a web archive, I propose to look at how to deploy this archive in a Tomcat instance that is embedded into a JUnit test.

As usual, the presented snippets are available in the JEE-6-Demo application. I will first look at the dependencies, then I will show how to configure Tomcat and finally how to start and stop the embedded instance.

The first dependency is the embedded Tomcat core component. JULI which stands for Java Utility Logging Implementation that is the container extension of common logging. The ECJ compiler and JASPER are required to handle JSPs. Of course all these dependencies are scoped to test only.

The dependencies

Maven dependencies necessary to start an embedded Tomcat instance into JUnit tests.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-core</artifactId>
  <version>7.0.26</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-logging-juli</artifactId>
  <version>7.0.26</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.eclipse.jdt.core.compiler</groupId>
  <artifactId>ecj</artifactId>
  <version>3.7.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <version>7.0.26</version>
  <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
</dependency>

Configuring Tomcat

The following snippet prepares the embedded instance. The static member mTomcat references a new instance of Tomcat. As Tomcat still requires a file system to work, a temporary directory is used to put all the temporary files. To that end, we use the java.io.tmpdir java property. These variables are shared among the test cases.

Shared static variables
1
2
3
4
/** The tomcat instance. */
private Tomcat mTomcat;
/** The temporary directory in which Tomcat and the app are deployed. */
private String mWorkingDir = System.getProperty("java.io.tmpdir");

As we want to use the same Tomcat configuration among all test cases, the initialization is put in a method annotated with @Before. First, the method sets the port to 0. This tells the engine to choose the port to run on by itself. This is especially useful to avoid starting the embedded Tomcat on a already used port as 8080 for instance. Then the base directory is set mTomcat.setBaseDir() to the temporary directory. Without doing that, Tomcat would start in the current directory. The rest of the method configures the way WAR are managed by the engine.

Configuration of the embedded Tomcat instance
1
2
3
4
5
6
7
8
9
10
@Before
public void setup() throws Throwable {
  mTomcat = new Tomcat();
  mTomcat.setPort(0);
  mTomcat.setBaseDir(mWorkingDir);
  mTomcat.getHost().setAppBase(mWorkingDir);
  mTomcat.getHost().setAutoDeploy(true);
  mTomcat.getHost().setDeployOnStartup(true);
  ...
}

The rest of the method builds a reference to a directory (based into the temporary directory) that contains the web application. This directory is deleted if it exists to ensure redeployment of the WAR. Finally, the WAR built as explained there is exported into the temporary directory.

Finally, the web application is added to the Tomcat instance. More specifically, a path exploded version webApp.getAbsolutePath() of the WAR is linked to a context contextPath.

Cleaning and preparing the web application deployment.
1
2
3
4
5
6
7
8
9
10
11
@Before
public void setup() throws Throwable {
  ...
  String contextPath = "/" + getApplicationId();
  File webApp = new File(mWorkingDir, getApplicationId());
  File oldWebApp = new File(webApp.getAbsolutePath());
  FileUtils.deleteDirectory(oldWebApp);
  new ZipExporterImpl(createWebArchive()).exportTo(new File(mWorkingDir + "/" + getApplicationId() + ".war"),
          true);
  mTomcat.addWebapp(mTomcat.getHost(), contextPath, webApp.getAbsolutePath());   
}

Starting Tomcat

Now that Tomcat has been configured, the next step is to start it. We want a fresh Tomcat for each and every test case. This way, a failed test does not have repercussions on the subsequent tests (e.g. session information, memory leaks);

Start the embedded Tomcat instance and add a web application
1
2
3
4
5
@Before
public void setup() throws Throwable {
    ...
  mTomcat.start();
}

If necessary, the actual port on which Tomcat has been started can be retrieved using the following snippet.

1
2
3
protected int getTomcatPort() {
  return mTomcat.getConnector().getLocalPort();
}

Finally, after the test, the Tomcat instance is stopped and destroyed clearing the way for the next test.

Stopping Tomcat

1
2
3
4
5
6
7
8
9
10
@After
public final void teardown() throws Throwable {
  if (mTomcat.getServer() != null
            && mTomcat.getServer().getState() != LifecycleState.DESTROYED) {
        if (mTomcat.getServer().getState() != LifecycleState.STOPPED) {
              mTomcat.stop();
        }
        mTomcat.destroy();
    }
}

Conclusion

In this post, we have seen how to start an embedded version of Tomcat into a JUnit fixture. The examples used in this blog are to be found in the JEE-6-Demo project on Google code hosting.