WYTIWYR : What You Test Is What You Run

I’m fed up with unit testing !

It’s 2012 and my first resolution of the year is to finally tell the truth about testing : unit testing is pretty much useless when your code runs inside a container. How do you unit test an EJB which relies on the container services (i.e transaction, injection, security…) ? Well, you mock the database access, you mock your security layer, you mock your dependencies, you mock your validation layer… to test what ? A bit of business logic. Yes. Unit test is interesting when you have complex business logic to test so you can have quick feedback. Otherwise, it’s a waste of time which doesn’t test your container services. So I’m not saying unit testing is completely useless, I’m saying that integration testing is also to be considered when you run your code inside a Java EE container.

In this post I’ll show you how to unit test an EJB with Mockito and how to do integration test with and without Arquillian.

Use case

So let’s take a simple use case (but of course, in real life it’s more complex) : I have a Book entity with a complex named query (well, sort of) and an EJB that queries the entity (CRUD operations + calling the named query). Because my JPQL query is complex and I have a bug in production, I want to reproduce the bug and correct the JPQL query. Because I like Java EE 6 and CDI I use extensively some artifacts that need to be injected (such as a Logger, DataSourceDefinition and so on).

As you can see in the class diagram, I have the following classes :

  • ItemEJB : a stateless EJB with a @Path annotation to add REST services. It manipulates the Book entity.
  • Book : entity with JPA annotation for persistence and query as well as JAXB annotations for XML marshaling.
  • IsbnGenerator : CDI bean that generates an ISBN number for the book.
  • DatabasePopulator : startup singleton that persists a few books into the database.
  • ApplicationConfig : helper class annotated with @ApplicationPath to declare all REST services under the /rs URL.
  • DatabaseResource : produces an injectable EntityManager.
  • LogResource : produces an injectable logger.

The Book entity

The Book entity is pretty simple but some things have to be highlighted :

@Entity
@NamedQueries({
@NamedQuery(name = Book.FIND_ALL_SCIFI, query = "SELECT b FROM Book b WHERE 'scifi' member of b.tags ORDER BY b.id DESC")
})
public class Book {

  public static final String FIND_ALL_SCIFI = "Book.findAllScifiBooks";

  @Id @GeneratedValue
  private Long id;
  @NotNull
  private String title;
  private Float price;
  private String description;
  private String isbn;
  @ElementCollection
  private List tags = new ArrayList();
  ..

This entity has a named query which retreives all the scifi books from the database and I need to test it (this query is pretty simple but imagine an harder one). The JPA provider will generate an id automatically thanks to @GeneratedValue. The integration between JPA with Bean Validation will make sure I cannot insert a Book with a null title (thanks to @NotNull). These services have to be mocked in unit testing (not in integration test as you will see).

The ItemEJB

The ItemEJB is a Stateless EJB with REST capabilites doing CRUD operations and invoking the entity named query :

@Stateless
public class ItemEJB {

  @Inject
  private EntityManager em;

  @Inject
  private IsbnGenerator numberGenerator;

  @Inject
  private Logger logger;

  public Book createBook(Book book) {
    book.setIsbn(numberGenerator.generateNumber());
    em.persist(book);
    return book;
  }

  public void removeBook(Book book) {
    em.remove(em.merge(book));
  }

  public List findAllScifiBooks() {
    logger.info("###### findAllScifiBooks ");
    return em.createNamedQuery(Book.FIND_ALL_SCIFI, Book.class).getResultList();
  }
  ...
}

This POJO uses several services from the container. First of all, every method is transactional (without any extra boiler plate code, just because it’s annotated with @Stateless). Then, this EJB gets injected an EntityManager that has been produced (see below), a helper class (the IsbnGenerator POJO) and a logger (I’ll use the good old java.util.logging so my code doesn’t have external dependencies). Again, these services will have to be mocked in unit testing.

DataSource

I need a datasource to access a database. Because I want to do some testing, Derby in-memory database will do. And because I’m pretty lazy and don’t want to create a datasource inside my container using the admin console, I use the @DataSourceDefinition annotation to make my life easier :

@DataSourceDefinition(name = "java:app/jdbc/sampleArquilianWytiwyrDS",
className = "org.apache.derby.jdbc.EmbeddedDriver",
url = "jdbc:derby:memory:sampleArquilianWytiwyrDB;create=true;user=app;password=app"
)
public class DatabaseResource {

  @Produces
  @PersistenceContext(unitName = "sampleArquilianWytiwyrPU")
  private EntityManager em;
}

As you can see I produce my EntityManager so it can be injected with @Inject. In unit testing this class is pretty much useless as no datasource can be used and injection as to be mocked.

Testing scenario

As I said, I want to test a complex scenario with all the container services available (so this is not unit testing per se). Here is the scenario :

  • I get all the scifi books from the database (using the named query that looks for the scifi tag)
  • I persist three books : one that fills the query, another one that doesn’t and a third one that has a null title which will not get persisted (due to Bean Validation ConstraintViolationException)
  • I get all the scifi books from the database again and make sure there is an extra one
  • I remove all the entities from the database
  • I get all the scifi books from the database again and make sure we have the initial number of books

Implementing the scenario with unit testing

I’m going to say this again to make sure I don’t receive thousands of emails from unit testing fanatics : the scenario described above is not a unit test, but I want to show how you can unit test your EJB with Mockito (and how painful and useless it is). So let’s go, I’ll start with the code and explain it later :
@RunWith(MockitoJUnitRunner.class)
public class ItemEJBTest {

  @Mock
  private EntityManager mockedEntityManager;
  @Mock
  private TypedQuery mockedQuery;
  private ItemEJB itemEJB;

  @Before
  public void initDependencies() throws Exception {
    itemEJB = new ItemEJB();
    itemEJB.setEntityManager(mockedEntityManager);
    itemEJB.setNumberGenerator(new IsbnGenerator());
    itemEJB.setLogger(Logger.getLogger(ItemEJB.class.getName()));
  }

  @Test
  public void shouldFindAllScifiBooks() throws Exception {

    List books = new ArrayList();

    // Finds all the scifi books
    when(mockedEntityManager.createNamedQuery(Book.FIND_ALL_SCIFI, Book.class)).thenReturn(mockedQuery);
    when(mockedQuery.getResultList()).thenReturn(books);
    int initialNumberOfScifiBooks = itemEJB.findAllScifiBooks().size();

    // Creates the books
    Book scifiBook = new Book("Scifi book", 12.5f, "Should fill the query", 345, false, "English", "scifi");
    Book itBook = new Book("Non scifi book", 42.5f, "Should not fill the query", 457, false, "English", "it");
    Book nullBook = new Book(null, 12.5f, "Null title should fail", 457, true, "English", "scifi");

    // Persists the books
    itemEJB.createBook(scifiBook);
    itemEJB.createBook(itBook);
    verify(mockedEntityManager, times(2)).persist(any());

    try {
      doThrow(ConstraintViolationException.class).when(mockedEntityManager).persist(nullBook);
      itemEJB.createBook(nullBook);
      fail("should not persist a book with a null title");
    } catch (ConstraintViolationException e) {
    }

    // Finds all the scifi books again and make sure there is an extra one
    books.add(scifiBook);
    when(mockedQuery.getResultList()).thenReturn(books);
    assertEquals("Should have one extra scifi book", initialNumberOfScifiBooks + 1, itemEJB.findAllScifiBoks().size());

    // Deletes the books
    itemEJB.removeBook(scifiBook);
    itemEJB.removeBook(itBook);
    verify(mockedEntityManager, times(2)).remove(any());

    // Finds all the scifi books again and make sure we have the same initial numbers
    books = new ArrayList();
    when(mockedQuery.getResultList()).thenReturn(books);
    assertEquals("Should have initial number of scifi books", initialNumberOfScifiBooks, itemEJB.findAllScifiBooks().size());
  }
}

Some explanation :

  • line number 4 and 6 : thanks to @RunWith(MockitoJUnitRunner.class), I’m mocking the database access by mocking my EntityManager and TypedQuery with the @Mock annotation
  •  line number 12 :  in the initDependencies method that’s where we lose all the container services : we do a new of the ItemEJB (itemEJB = new ItemEJB()) instead of injecting or lookingup the EJB. Instanciating ItemEJB is not seen by the container, so it’s just a POJO without any container services. And because we run in isolation, we have to manually mock or instanciate the dependencies using setters (setEntityManagersetNumberGenerator and setLogger).
  • line number 19 : shouldFindAllScifiBooks implements our testing scenario. As you can see, I use an ArrayList to add my books and Mockito returns this list (instead of the query result). I then persist my books (verify(mockedEntityManager, times(2)).persist(any())) and I want to make sure I get a ConstraintViolationException when persisting a book with a null title (that why I have doThrow(ConstraintViolationException.class).when(mockedEntityManager).persist(nullBook)). To test that my query returns an extra book I just add the object to the list (books.add(scifiBook)) and remove it afterwards (books.remove(scifiBook)).

As you can see, I haven’t tested my JPQL query, the code is not that nice, and I have to do many Mockito tricks to simulate what I want. Isn’t that a test smell ? A Mockery ? We shouldn’t mock third-party libraries. So let’s do integration tests.

Implementing the scenario with integration testing

I can hear you saying “Integration test in Java EE is difficult, don’t do that“. This was true in the past but not anymore. Integration testing use to be nearly impossible, that’s why we had no choice but unit test and mock all the services. But today, thanks to Java EE 6, we can easily do integration testing. How ? By using standard (and some time non standard) APIs or testing frameworks such as Arquillian :

  • EJBContainer.createEJBContainer() : creates an in-memory EJB container where you can deploy and use your EJB
  • Persistence.createEntityManagerFactory() : creates a JPA provider so you can manipulate entities
  • Validation.buildDefaultValidatorFactory() : gets a validator to validate your beans
  • ActiveMQConnectionFactory : creates an in-memory JMS broker (non-standard)
  • ServletTester : Jetty helper class to test your servlets and web services in-memory (non-standard, I whish we had a standard WebContainer API like in EJBs)

Without Arquillian (i.e EJBContainer)

Let’s start with the simplest standard integration test for an EJB : using the javax.ejb.embeddable.EJBContainer API. This API was created in EJB 3.1 and is used to execute an EJB application in an embeddable container (in a standard way). Here is the code of our scenarion with the EJBContainer (BTW I’m using GlassFish 3.1 as the implementation) :

public class ItemEJBWithoutArquillianIT {

    private static EJBContainer ec;
    private static Context ctx;

    @BeforeClass
    public static void initContainer() throws Exception {
        Map properties = new HashMap();
        properties.put(EJBContainer.MODULES, new File[]{new File("target/classes"), new File("target/test-classes")});
        ec = EJBContainer.createEJBContainer(properties);
        ctx = ec.getContext();
    }

    @AfterClass
    public static void closeContainer() throws Exception {
        if (ec != null) {
            ec.close();
        }
    }

    @Test
    public void shouldFindAllScifiBooks() throws Exception {

        // Check JNDI dependencies
        assertNotNull(ctx.lookup("java:global/classes/ItemEJB"));
        assertNotNull(ctx.lookup("java:global/jdbc/sampleArquilianWytiwyrDS"));

        // Looks up for the EJB
        ItemEJB itemEJB = (ItemEJB) ctx.lookup("java:global/classes/ItemEJB");

        // Finds all the scifi books
        int initialNumberOfScifiBooks = itemEJB.findAllScifiBooks().size();

        // Creates the books
        Book scifiBook = new Book("Scifi book", 12.5f, "Should fill the query", 345, false, "English", "scifi");
        Book itBook = new Book("Non scifi book", 42.5f, "Should not fill the query", 457, false, "English", "it");
        Book nullBook = new Book(null, 12.5f, "Null title should fail", 457, true, "English", "scifi");

        // Persists the books
        itemEJB.createBook(scifiBook);
        itemEJB.createBook(itBook);
        try {
            itemEJB.createBook(nullBook);
            fail("should not persist a book with a null title");
        } catch (Exception e) {
            assertTrue(e.getCause() instanceof ConstraintViolationException);
        }

        // Finds all the scifi books again and make sure there is an extra one
        assertEquals("Should have one extra scifi book", initialNumberOfScifiBooks + 1, itemEJB.findAllScifiBooks().size());

        // Deletes the books
        itemEJB.removeBook(scifiBook);
        itemEJB.removeBook(itBook);

        // Finds all the scifi books again and make sure we have the same initial numbers
        assertEquals("Should have initial number of scifi books", initialNumberOfScifiBooks, itemEJB.findAllScifiBooks().size());
    }
}

Some explanation :

  • line number 7 : here I create my embedded EJB container and get the JNDI context. As you can see, I don’t have to mock anything (EntityManager, injection and so on) because from now on my code will be running in an embedded container (which is the same container that you will be running in production, but in runtime mode instead of in-memory)
  • line number 15 : closes the EJB container once the test is passed
  • line number 22 : in this method I implement our testing scenario, with no mocks. I lookup my EJB using JNDI and invoke the needed methods (findAllScifiBooks, createBook and removeBook) which will be intercepted by the container that will give me all the services (transactions, injection, lifecycle…)
  • line number 26 : because I’m running inside a container, I can even lookup my datasource (because it has been deployed thanks to @DataSourceDefinition
  • line number 43 : if I persist a book with a null title, Bean Validation will throw a constraint violation (a real one, I don’t have to mock it)

With Arquillian

Arquillian is a JBoss project that can execute test cases inside a container (embedded, local or remote). And when I say a container, it can run the same test in several ones (GlassFish, JBoss…). In my case I’m using GlassFish, so as you can see, Arquillian is not stuck to JBoss. I will write about multiple server deployment later, but for now, let’s see how an integration test with Arquillian differs from one with the EJBContainer API :

@RunWith(Arquillian.class)
public class ItemEJBWithArquillianIT {

    @Inject
    private ItemEJB itemEJB;

    @Deployment
    public static JavaArchive createTestArchive() {
        JavaArchive archive = ShrinkWrap.create(JavaArchive.class)
                .addPackage(Book.class.getPackage())
                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
                .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml");
        return archive;
    }

    @Test
    public void shouldFindAllScifiBooks() throws Exception {

        // Check JNDI dependencies
        Context ctx = new InitialContext();
        assertNotNull(ctx.lookup("java:global/jdbc/sampleArquilianWytiwyrDS"));

        // Finds all the scifi books
        int initialNumberOfScifiBooks = itemEJB.findAllScifiBooks().size();

        // Creates the books
        Book scifiBook = new Book("Scifi book", 12.5f, "Should fill the query", 345, false, "English", "scifi");
        Book itBook = new Book("Non scifi book", 42.5f, "Should not fill the query", 457, false, "English", "it");
        Book nullBook = new Book(null, 12.5f, "Null title should fail", 457, true, "English", "scifi");

        // Persists the books
        itemEJB.createBook(scifiBook);
        itemEJB.createBook(itBook);
        try {
            itemEJB.createBook(nullBook);
            fail("should not persist a book with a null title");
        } catch (Exception e) {
            assertTrue(e.getCause() instanceof ConstraintViolationException);
        }

        // Finds all the scifi books again and make sure there is an extra one
        assertEquals("Should have one extra scifi book", initialNumberOfScifiBooks + 1, itemEJB.findAllScifiBooks().size());

        // Deletes the books
        itemEJB.removeBook(scifiBook);
        itemEJB.removeBook(itBook);

        // Finds all the scifi books again and make sure we have the same initial numbers
        assertEquals("Should have initial number of scifi books", initialNumberOfScifiBooks, itemEJB.findAllScifiBooks().size());
    }
}

Some explanation :

  • line number 4 : thanks to Arquillian, I can inject a reference of my EJB instead of looking it up. My test runs inside the container, so I can use the injection service of this container
  • line number 8 : the createTestArchive method uses ShrinkWrap to create an archive which will then be deployed by Arquillian in the container
  • line number 17 : the code of the integration test is nearly the same as the one we say before
In this example it’s difficult to see the benefit of Arquillian as both test classes (with EJBContainer and with Arquillian) are similar. Arquillian is not standard, the EJBContainer API is. But I’ll spend more blogs explaining you the benefit in the long run.

Some metrics

Ok, some metrics now. How much does it cost to run a unit test vs integration tests ? I measured each of these tests (on my fantastic Mac Book Pro – i7 – 8Gb RAM – SSD drive) and here is the execution time :

  • unit testing : 195 milliseconds to run
  • integration test without Arquillian : 5.3 seconds (that’s 27 times slower than unit testing)
  • integration test with Arquillian : 6.1 seconds (that’s 31 times slower than unit testing)
As you can see, unit testing is by far much faster to execute. Unit testing gives you a quick feedback and you can really develop and test continuously. It’s still time consuming to do with integration test.

Conclusion

There is unit testing and integration testing. Historically integration testing was pretty much impossible in Java EE and you had to do many different tricks. That’s why we used extensively unit testing and mocked even objects that we don’t owe (like the EntityManager). But since Java EE 6, thanks to all our container factories (EJBContainerEntityManagerFactoryValidatorFactory…) we can now easily use these container and their services in an embedded mode. Unit testing is good to test business code or code in isolation (mocking external components) but we have to remember that we have easy integration testing now and we should use it to test code interacting with external components or services.

But the world is not perfect… yet. The big advantage of unit testing is the quick feedback because unit tests run faster. But, because you are mocking so many services, you don’t have a clue how your code will behave in production. Integration test uses the container and the container services, so you know that What You Test Is What You Run.

I little bit of hope now. A few month ago I wrote a (long) post about startup time of most of the Java EE 6 application servers. Most of the application servers startup in less than 4 seconds. If you look at the application servers history, that is a huge improvment in the last years. Same thing will happen with embedded containers and integration test framework such as Arquillian : they will get faster and faster, and soon, running your in-memory database and in-memory container will cost you little resources. Having fast integration tests that’s what we want !

Thanks

I would like to thank Brice Duteil, a Mockito committer who gave me some advices on Mockito.

References


O Java EE 6 Application Servers, Where Art Thou?

Nearly two years ago (time flies), when Java EE 6 came out, I wrote a post about application servers where I did some micro benchmarking (basically, startup time). I had plenty of comments and recently I had many people asking for some updates. Witht Java EE 6 booming, with some cloud vendors moving to Java EE 6, it was time to update this microbenchmark and focus on Java EE 6 application servers. BTW, if you want to know what Java EE 6 is, you can check the slides of a presentationI gave a few times.

The benchmark

Same disclaimer as last time : This is not a real benchmark ! so I’ll copy paste the paragraph I wrote last time :

In this test I’m just concerned about the usability of an application server for a developer. The idea is to download it, install it, start it and take some measurements : size of download, ease of installation, size of disk, startup time, size of RAM... That’s all. No deployment of an application, no fancy twists to gain performance… Because some of these application servers are resource consuming, I’m doing all my tests on a Windows XP SP3 virtual machine (running on Virtual Box 4.1). It is a fresh install of Windows XP sp3 with 1Gb of RAM and not too many software installed. So when I boot there are 27 processes running and using 230 Mb of RAM (leaving 770 Mb free). Virtualizing can be slower, so keep in mind that startup time can be a bit faster that what I’m giving you here. I use JDK 1.6.0_27 (when it’s not bundled with the server). No optimization at all is made (I haven’t twisted the JVM, or antyhing application server parameter, everything comes out of the box).

To calculate the startup time, I don’t do any fancy rocket science either. I just start the server a few times, check how long it takes and use the best startup time. Also remember that some servers do not load any container at startup, making them very fast to start. That’s why I first trigger the web admin console (when there’s one) so I’m sure at least one web application is deployed (I did a print screen of the admin console when there’s one). Then I just stop and start the server a few times and get the best startup time (by reading the logs). To calculate the memory footprint, I just use the Windows task manager and check the size of the java.exe process.

Which application servers ?

If you look at the Java EE Compatibility page at Oracle, you’ll see that there are a bunch of application servers that actually have passed the Java E E6 TCK (Oracle GlassFish Server 3.1.1Caucho Resin 4.0.17JBoss Application Server 7Apache TomEE 1.0.0-beta-1,  TMAX JEUS 7, IBM WebSphere Application Server 8.0Fujitsu Interstage Application Server) and some still haven’t (Geronimo 3, JOnAS 5.3, Siwpas). On this list some application servers implement the full Java EE 6 and others just implement the Web Profile 1.0.

GlassFish 3.1.1

GlassFish 3 is the open source reference implementation for Java EE 6. The 3.1 release has added clustering capabilities. Being the reference implementation, GlassFish 3.x implements both Java EE 6 and the Web Profile 1.0, that’s why you have two different bundles you can download (one of 80.6 Mb and the other 45.8 Mb).

Version 3.1.1
What do you get ? Java EE 6 & Web Profile 1.0
Who is behind? Oracle
Open source? Dual license CDDL and GPL
Documentation Documentation
Download Zipfile, executables
Size of the downloaded file 80.6 Mb (Java EE 6) 45.8 Mb (Web Profile)
Installation mode Unzip or exe
Size once installed on drive 96.1 Mb (Java EE 6) 57.8 Mb (Web Profile)
How to start it Execute %GLASSFISH_HOME%\bin\asadmin start-domain
Location of log files %GLASSFISH_HOME%\domains\domain1\logs
Best startup time 2 953ms (Java EE 6) 1 914ms (Web Profile)
Size of the process in RAM at startup 83 MB (Java EE 6) 69 MB (Web Profile)
Welcome page http://localhost:8080/
Admin console http://localhost:4848

Resin 4.0.23

Resin 4 was one of the first web server (such as Jetty or Tomcat) to move to the Web Profile 1.0. For me it’s the success story that confirmed that profiles in Java EE were needed. It’s really difficult to go from a Web Server to a full Java EE 6 application server (remember that there’s still Entity CMPs in EE 6) but much easier to implement the Web Profile. Resin is very CDI centric and based on the Caucho implementation called CanDI.

Version 4.0.23
What do you get ? Web Profile 1.0
Who is behind? Caucho
Open source? GPL License
Documentation Documentation
Download Zip, tgz, deb
Size of the downloaded file 24.2 Mb
Installation mode Unzip the file
Size once installed on drive 32 Mb
How to start it Execute %RESIN_HOME%\java -jar lib/resin.jar start
Location of log files %RESIN_HOME%\log
Best startup time 1 845ms
Size of the process in RAM at startup 2 processes : 68.5 MB + 39 MB
Welcome page http://localhost:8080/
Admin console http://localhost:8080/resin-admin/

JBoss 7.0.2-Final

It looks like JBoss 7 is, finally, a nice millésime. For those of you who waited so long for JBoss 5 to get certified and then didn’t see any JBoss 6, JBoss 7 is what you need with a fantastic startup time compared to the older versions (in my previous benchmardJBoss 5 was the slowest app servers, slower than WebSphere 7). Another novelty is an admin console (sexier than the good old JMX Console).

Version 7.0.2-Final
What do you get ? Web Profile 1.0
Who is behind? JBoss/RedHat
Open source? LGPL
Documentation Documentation
Download Zipfile
Size of the downloaded file 70.7 Mb
Installation mode Unzip
Size once installed on drive 77.9 Mb
How to start it Execute %JBOSS_HOME%\bin\standalone
Location of log files %JBOSS_HOME%\standalone\log
Best startup time 2 782ms
Size of the process in RAM at startup 70.7 MB
Welcome page http://localhost:8080/
JMX console http://localhost:9990/console

TomEE 1.0.0-beta-1

Like Resin, Apache TomEEis the perfect success story for the Web Profile. TomEE is no more than Tomcat + OpenWebBeans + OpenEJB + OpenJPA + MyFaces + other bits. It really shows that Java EE is a jigsaw puzzle where you can take open standards, bundle them together and become a certified Web Profile application server.

Version 1.0.0-beta-1
What do you get ? Web Profile 1.0
Who is behind? Apache
Open source? Apache Software License
Documentation Documentation
Download Zip, tar.gz
Size of the downloaded file 24.2 Mb
Installation mode Unzip the file
Size once installed on drive 29.2 Mb
How to start it Execute %TOMEE_HOME%\bin\startup.bat
Location of log files %TOMEE_HOME%\logs
Best startup time 3 288ms
Size of the process in RAM at startup 65 MB
Welcome page http://localhost:8080/
Admin console (*) http://localhost:8080/manager/html

(*) Looks like to be able to log on to the admin console, you need to change the %TOMCAT_HOME%\conf\tomcat-users.xml configuration files and add a manager-script role to a user. But I couldn’t make it work.

Geronimo v3.0-M1

Geronimo is not already Java EE 6 ceritified (still in Miletone 1). Geronimo comes in 2 flavours, one with Jetty the other one with Tomcat. And like TomEE, Geronimo bundles several open source implementationsof Java EE.

Version 3.0-M1
What do you get ? Not yet certified
Who is behind? Apache
Open source? Apache Software License
Documentation Documentation
Download Zip, tar
Size of the downloaded file 66.9 Mb (Geronimo + Tomcat)
Installation mode Unzip the file
Size once installed on drive 76.4 Mb
How to start it %GERONIMO_HOME%\bin\geronimo start
Location of log files %GERONIMO_HOME%\var\log
Best startup time 12 467ms
Size of the process in RAM at startup 159 Mb
Welcome page http://localhost:8080/
Admin console (*) http://localhost:8080/console-base

(*) user/pwd : system/manager

JOnAS 5.3.0-M4

JOnASis till not Java EE 6 certified. It provides a full Java EE 5 execution stack plus some Java EE 6 previews (JPA 2.0, CDI, …), supporting EJB3 (and not EJB 3.1 yet).

Version 5.3.0-M4
What do you get ? Not yet certified
Who is behind? OW2
Open source? LGPL
Documentation Documentation
Download Zip, tar.gz
Size of the downloaded file 211 Mb
Installation mode Unzip the file
Size once installed on drive 231 Mb
How to start it %JONAS_HOME%\bin\jonas start
Location of log files %JONAS_HOME%\logs
Best startup time 11 036ms
Size of the process in RAM at startup 107 Mb
Welcome page http://localhost:9000/
Admin console (*) http://localhost:9000/jonasAdmin

(*) user/pwd : jonas/jonas

Siwpas Enterprise 2.0.0-GA

Siwpas (Simple Web Profile Application Server) is quite new compared to the good old application servers. But like most of them, it embeds well known open source stacks, most from Apache  (Tomcat, OpenEJB, OpenWebBeans, MyFaces, OpenJPA, Apache BeanValidation). It’s open source but you’ll still need a 30 days trial license to startup the enterprise version of the server.

Version 2.0.0-GA
What do you get ? Web Profile 1.0 (Not yet certified)
Who is behind? Mechsoft
Open source?
Documentation Documentation
Download Zip, exe, tar.gz
Size of the downloaded file 34.2 Mb
Installation mode Unzip the file
Size once installed on drive 38.2 Mb
How to start it %SIWPAS_HOME%\bin\startup
Location of log files %SIWPAS_HOME%\logs
Best startup time 8 598ms
Size of the process in RAM at startup 72.8 Mb
Welcome page http://localhost:8080/
Admin console (*) http://localhost:8080/console

(*) user/pwd : admin/admin

Websphere 8.0.0.1

Websphere 8 is the Java EE 6 application server of IBM. Like the previous versions, you need a big bandwith to download one gigabyte of modules that get installed in nearly 2 hours. I noticed that there is a developer edition but once installed it looks like the 2.2 Gb of the full server (I might got lost in the maze of the IBM website). There is also a Community Edition and it looks like it’s based on Geronimo (and the executable to install it is also 116 Mb). IBM, please, make it simple.

Thanks to @sebsto I found a gem : it looks like IBM is working on a version WAS 8.5 Alpha that would look like the other app servers (light and easy to install). I’ll stay tuned on this one.

Version 8
What do you get ? Java EE 6
Who is behind? IBM
Open source? Commercial product
Documentation Documentation
Download Exe file for WAS & WAS for developers
Size of the downloaded file 116 Mb
Installation mode Execute + Wizard install (with all the defaults) which downloads more stuff (took nearly 1:40 hour)
Size once installed on drive 2.2 Gb
How to start it Execute %WEBSPHERE_HOME%\AppServer\profiles\AppSrv01\bin\startServer.bat server1 -profileName AppSrv01
Location of log files %WEBSPHERE_HOME%\AppServer\profiles\AppSrv01\logs\server1
Best startup time 42 s
Size of the process in RAM at startup 155 Mb
Admin console https://localhost:9043/ibm/console

Jeus 7

A bit unknown but in version 7.0 (so it shows this application server has been around for long time), Jeus 7from TMaxSoft was a bit difficult to startup (create an account on the web site, download, install, run a wizard and read the README.txt to make it started). Then I discovered that there is no Jeus 7 for Windows so I downloaded the Linux version and installed it on Ubuntu (so the results of the microbenchmark are not very accurate compare to the other made on Windows).

Version 7
What do you get ? Java EE 6
Who is behind? TmaxSoft
Open source? Commercial
Documentation Documentation
Download bin file (only available on Linux)
Size of the downloaded file 126 Mb
Installation mode Execute the file and answer a wizard
Size once installed on drive 198 Mb
How to start it Execute $JEUS_HOME/bin/jeus -u administrator -p <pwd you declared in the wizard>
Location of log files $JEUS_HOME/domains/jeus-domain1/logs
Best startup time 23 783ms (but again that was on Ubuntu, not in Windows)
Size of the process in RAM at startup 147 Mb
Welcome page http://localhost:8088/ (but looks like there’s no page)
Admin console Not sure there’s a admin console, but jeusadmin tool helps you to manage the server

Interstage

I couldn’t even find where to click and download the server, so if anybody knows, I’ll be ready to give it a try.

Where the hell is Tomcat ?

Tomcat 7 is not a Java EE 6 application server nor does it implement the Web Profile 1.0. It is just a Servlet 3.0 container, so it’s shouldn’t appear in this blog post. But, everybody likes Tomcat, everybody feels Tomcat is way much faster than any server on earth (even faster than Neutrinos or maybe not). So I had to put it in this benchmark just to be a source of comparaison. And, indeed, Tomcat is the fastest application server of the list (3 times faster than GlassFish or 4 times faster than JBoss). But it only does Servlet 3 while the others implement between 12 (Web Profile) or 28 (Java EE 6) specifications.

Version 7.0.22
What do you get ? Servlet 3
Who is behind? Apache
Open source? Apache Software License
Documentation Documentation Index
Download Zip, tar.gz
Size of the downloaded file 7.5 Mb
Installation mode Unzip the file
Size once installed on drive 11.3 Mb
How to start it Execute %TOMCAT_HOME%\bin\startup.bat
Location of log files %TOMCAT_HOME%\logs
Best startup time 694 ms
Size of the process in RAM at startup 34.6 Mb
Welcome page http://localhost:8080/
Admin console http://localhost:8080/manager/html

Summary

As a summary I will show you two graphs with startup time and resource consumption so it’s easier to compare.

Startup time

When you are a developer, startup up time matters (it doesn’t when you are in production). Thanks to tools like JRebel or the hot deployment of our IDEs, we tend to restart our app servers less and less. But, sometimes it happens (PermGens, classpath mess up, memory leaks, refreshing app server cache…). I didn’t put WAS 8 nor Jeus 7 in the graph below because they would just break the scale (42 and 23 seconds). It’s interesting to notice that 4 app servers (Resin, GlassFish, JBoss and TomEE) start in less that 5 seconds (Jonas & Geronimo are still in Milestone). Resin is 3 times slower than Tomcat, but again, it comes with the Web Profile.

Size once installed on the drive & size of process in RAM

The size of the application installed on your disk is not very accurate : some app servers come with documentation, samples… others no. But still, that gives you an overview of how big an app server can be (again, I couldn’t put WAS in this diagram as it will break the scale with its 2.2 Gb). The memory consumption is more interesting. Without any JVM or server twists, when you startup, they nearly all take less that 100Mb of RAM(see how close TomEE, GlassFish, JBoss and Siwpas are).

Conclusion

First of all, as you can see there is no Weblogic. Unfortunatelly Weblogic is the last big player to be certified Java EE 6. I don’t know the roadmap, hopefully I’ll soon be able to update this blog entry with the latest version of Weblogic. Second, this is not a real benchmark : I didn’t deploy any application nor I did some stress tests. One task I would like to do is to deploy a Java EE 6 application on all these servers and see how portable the code is. But that’s for another blog.

What did I want to show in this blog ? Well, that application servers have changed. Except for WAS, Weblogic or Jeus, all the others are fast at startup and take few resources (memory).

And why did I want to show this ? Because I’m fed up to still hear in 2011 : “Tomcat is light, Java EE app servers are not”. As you can see, in terms of startup and memory, the gap between Tomcat and Resin, GlassFish or JBoss is really small.

How is it going to affect your development life ? Do you remember when 7/8 years ago we had to mock our database accesses because we didn’t want to install a fat oracle database on our laptop ? These days are over now because we use in-memory databases such as H2 or Derby. Same thing is happening with application servers : soon app servers will be running in memory and we won’t be mocking anything. We will fire a test case, app servers and databases in memory, and that’s it. And with tools like Arquilian, it looks like this future is already happening.

Long live Java EE 6 and Java EE 6 application servers !


Injection with CDI (Part III)

If you follow this blog you should know that latelly I’ve been writing (and talking) about CDI (Contexts and Dependency Injection). CDI has many aspects to it but until now I’ve focused on how to boostrap CDI in several environments, how to add CDI to an existing Java EE 6 application,  and more recently how to use injection with CDI. Actually this post is the third on CDI Injection : Part I focused on default injection and qualifiers, and Part II on all the possible injection points (field, constructor and setters). In this post I’ll explain producers or “how you can inject anything anywhere in a type safe manner“.

Injecting just beans ?

Until now I’ve shown you how to inject beans with a simple @Inject. If we focus on the book number generator example I’ve been using, we have a Servlet and a RESTService being injected an implementation of the NumberGenerator interface. Thanks to qualifiers, the servlet can specifically ask to get the IsbnGenerator by specifying the @ThirteenDigit qualifier on the injection point and the rest service an IssnGenerator with a @EightDigits (check my first post). The following class diagram shows you some combinations of bean injection :

But as you can see, all this is are beans injecting other beans. Can we just inject beans with CDI ? The answer is no, you can inject anything anywhere.

Producers

Yes, you can inject anything anywhere, the only thing you have to do is produce the thing you want to inject. For that, CDI has producers (a nice implementation of the Factory pattern) A producer exposes any sort of :

  • Class : unrestricted set of bean types, superclass, and all interfaces it implements directly or indirectly
  • Interface : unrestricted set of bean types, interfaces it extends directly or indirectly, and java.lang.Object
  • Primitive and Java array type

So by that you can inject a java.util.Date, java.lang.String or even an int. Let’s start by producing and injecting some data types and primitives.

Producing data types and primitives

One example of injecting anything anywhere is the possibility to inject data types or primitives. So let’s inject a String and an int. For that I need to add extra classes to our model. Until now, the IsbnGenerator would generate a random number like 13-124-454644-4. I can say that this number is made of a String that acts like a prefix (13-124) and an int that acts like a suffix (4). The following class diagram shows the two new classes PrefixGenerator and PostfixGeneratorthat will be used by the number generators :

If we look at the code of the PrefixGenerator for example, you can see that the class itself is not annotated by any qualifier, but the methods are. The method getIsbnPrefix returns a String that is qualified with @ThirteenDigits. This String is produced by CDI (thanks to @Produces), meaning that you can now inject it with @Inject using its qualifier (@ThirteenDigits)

public class PrefixGenerator {

    @Produces @ThirteenDigits
    public String getIsbnPrefix() {
        return "13-84356";
    }

    @Produces @EightDigits
    public String getIssnPrefix() {
        return "8";
    }
}

And now look carefully at the class  PostfixGenerator. The code is exactly the same as previously except in this case we produce an intthat can now be injected.

public class PostfixGenerator {

    @Produces @ThirteenDigits
    public int getIsbnPostfix() {
        return 13;
    }

    @Produces @EightDigits
    public int getIssnPostfix() {
        return 8;
    }
}

So now let’s change the way an ISBN number is generated. The bean IsbnGenerator now injects both a String and an int with @Inject @ThirteenDigits. You understand now what strong typing means with CDI.  Using the same syntax (@Inject @ThirteenDigits), CDI knows that it needs to inject a String, an int or an implementation of a NumberGenerator.

@ThirteenDigits
public class IsbnGenerator implements NumberGenerator {

    @Inject @ThirteenDigits
    private String prefix;

    @Inject @ThirteenDigits
    private int postfix;

	public String generateNumber() {
        return prefix + "-" + Math.abs(new Random().nextInt()) + "-" + postfix;
    }
}

Injecting Java EE resources with producer fields

So if CDI can inject anything anywhere, if CDI can even inject Strings and integers, what about Java EE resources ? That’s another story and producers are here to help. As I’ve said before, CDI is all about type safety : CDI doesn’t like Strings, so there is no way to inject a resource by its JNDI name such as @Inject(name="jms/OrderQueue"). A common example is the entity manager. This is how you must inject it in Java EE 6 if you don’t use CDI :

@Stateless
public class ItemEJB {

    @PersistenceContext(unitName = "cdiPU")
    private EntityManager em;
    ...
}

So why can’t you just @Inject an entity manager? If you remember my first post about ambiguous injection, this is the same problem. You can have several persistence units (named with a string), so if you just use an @Inject, CDI will not know which persistence unit to inject. Instead you must produce the entity manager first, give it a name (if you don’t want the @Default) and then an @Inject as follow :

public class DatabaseProducer {

    @Produces
    @PersistenceContext(unitName = "cdiPU")
    @BookStoreDatabase
    private EntityManager em;
}

The DatabaseProducer class uses the @PersistenceContext to inject the entity manager with the persistence unit cdiPU. It gives it a name using a qualifier (@BookStoreDatabase) and produces it so it can now be injected in an EJB as follow :

@Stateless
public class ItemEJB {

    @Inject
    @BookStoreDatabase
    private EntityManager em;
    ...
}

Another nice use case is to produce JMS factories and destinations. @Resource allows you to get a JNDI reference to a specific JMS factory or destination, the qualifier @Order gives it a name, and the @Produces allows you to inject it :

public class JMSResourceProducer {

    @Produces @Order @Resource(name = "jms/OrderConnectionFactory")
    private QueueConnectionFactory orderConnectionFactory;

    @Produces @Order @Resource(name = "jms/OrderQueue")
    private Queue orderQueue;
}

Now your EJB can use @Inject in a type-safe way :

@Stateless
public class ItemEJB {

    @Inject @Order
    private QueueConnectionFactory orderConnectionFactory;

    @Inject @Order
    private Queue orderQueue;
    ...
}

Producing Java EE resources with producer methods

The examples above are pretty simple : produce a field and you can then inject it. That’s called producer field. But sometimes you need a more complex business logic to produce a bean, that’s what we called producer method. Let’s take another use case. When you need to send a JMS message you always end up injecting a JMS Factory, a destination (queue or topic) creating a connection, then a session and so on until you actually send your message. Because this code is repetitive and error prone, why not externalize all of if into a single class and produce a session so the other components can use when sending a message. This class could look something like that :

public class JMSResourceProducer {

    @Resource(name = "jms/OrderConnectionFactory")
    private QueueConnectionFactory orderConnectionFactory;
    @Produces @Order @Resource(name = "jms/OrderQueue")
    private Queue orderQueue;

    @Produces @Order
    public QueueConnection createOrderConnection() throws JMSException {
        return orderConnectionFactory.createQueueConnection();
    }

    @Produces @Order
    public QueueSession createOrderSession(@Order QueueConnection conn) throws JMSException {
        return conn.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
    }
}

First, the class uses the @Resource to get a reference of the QueueConnectionFactory and Queue. For the same reason I just explain above, you can have several JMS factories and destinations and you must distinguish them by their JNDI name. And because CDI does not allow you to give a string name on an injection point, you must still use @Resource instead of @Inject. The createOrderConnection method take a QueueConnectionFactory creates a QueueConnection and produces it (while giving it the name of @Order). If you look carefully at the method createOrderSession it takes the produced QueueConnection and creates a QueueSession. An external component then just needs to inject the JMS session without going through the process of creating it :

@Stateless
public class ItemEJB {

    @Inject @Order
    private QueueSession session;

    @Inject @Order
    private Queue orderQueue;

    private void sendOrder(Book book) throws Exception {
        QueueSender sender = session.createSender(orderQueue);
        TextMessage message = session.createTextMessage();
        message.setText(marshall(book));
        sender.send(message);
    }
    ...
}

Producing and… disposing

I can hear you saying “ok, that’s nice, I have an external class doing all the plumbing and creating a connection and a session…. but who is going to close it ?“. Indeed, someone needs to free these resources by closing them. And that’s when CDI brings you another nice bit of magic : @Disposes.

public class JMSResourceProducer {

    @Resource(name = "jms/OrderConnectionFactory")
    private QueueConnectionFactory orderConnectionFactory;
    @Produces @Order @Resource(name = "jms/OrderQueue")
    private Queue orderQueue;

    @Produces @Order
    public QueueConnection createOrderConnection() throws JMSException {
        return orderConnectionFactory.createQueueConnection();
    }

    @Produces @Order
    public QueueSession createOrderSession(@Order QueueConnection conn) throws JMSException {
        return conn.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
    }

    public void closeOrderSession(@Disposes @Order QueueConnection conn) throws JMSException {
        conn.close();
    }

    public void closeOrderSession(@Disposes @Order QueueSession session) throws JMSException {
        session.close();
    }
}

To ask CDI to close a resource you just need to create a method which signature is the same as the one that created it (createOrderSession(@Order QueueConnection conn) creates a session and closeOrderSession(@Order QueueConnection conn) closes it) and add a @Disposes. CDI will dispose the resources in the right order (session first, connection second) for you. I haven’t mentioned it yet but CDI will create and dispose resources depending on the scope (resquest, session, application, conversation…). But that’s for another post.

Conclusion

As you’ve seen in my previous posts (Part I, Part II), CDI is about injection (I’ll explain other topics later). So far I’ve been showing you how to inject beans, but you know now that you can inject anything (String, integer, entity manager, JMS factories…) anywhere (in POJOs, Servlets, EJBs…). You just need to produce what you need to inject (either with field producers or method producers).
The next article will cover alternatives, so stay tuned.

Download

Download the code, give it a try, and give me some feedback.

References


Walking through the Java EE 6 implementation maze

I’ve been asked so many times “what are the implementations of such or such specification in Java EE 6 ?” or “what is the reference implementation of such a spec ?“. Because I always forget some (and to be honest, sometimes I don’t even know if a spec has several implementations of not), I’m writing this post to help me (and you) to remember.

So here is a non-exhaustive list of the several Java EE 6 implementations (please leave a comment to add anything to this list) :

Specification Version JSR Prunned Reference implementation Other implementations
Java EE 6.0 316 GlassFish V3 JEUS 7, Websphere 8, Geronimo 3*, Weblogic 12g
Web Profile 1.0 316 GlassFish V3 JBoss 6, JBoss 7*, Resin 4Geronimo 3*, Siwpass 1, Weblogic 12g, TomEE*
Managed Beans 1.0 316
JAX-RPC 1.1 101 Yes
JAX-WS 2.2 224 Metro Axis 2, CXF 2,
JAXB 2.2 2.2 222 Glassfish JAXB 2.2
JAXM 1.0 67 Glassfish SAAJ 1.3
StaX 1.0 173 Sjsxp 1 Woodstox 3Codehaus+
Web Services 1.2 109
Web Services Metadata 1.1 181
JAX-RS 1.1 311 Jersey 1.x Wink*, CXF 2, Resteasy 2, Restlet 2,
JAXR 1.1 93  Yes Scout 1,
JSF 2.0 314 Mojara 2 MyFaces 2,
JSP 2.2 245 GlassFish JSP 2.2 Tomcat 7,
Debugging Support 1.0 45
JSTL 1.2 52 Glassfish JSTL 1.2
Servlet 3.0 315 GlassFish 3 Tomcat 7, Jetty 8,
Expression Language 2.2 245 GlassFish EL 2.2 JUEL 2,
EJB 3.1 318 Entity Beans CMP GlassFish 3 OpenEJB 3.1,
Interceptors 1.1 318
JAF 1.1 925 GlassFish JAF 1
JavaMail 1.4 919 Kenai Project+ GNU Java Mail, Geronimo JavaMail,
JCA 1.6 322
JMS 1.1 914 Open MQ 4 ActiveMQ 5, SonicMQ, HornetQ 2, Websphere MQ, Joram,
JPA 2.0 317 EclipseLink 2 OpenJPA 2, Hibernate 3.5,
JTA 1.1 907 Atomikos, BTM, JBoss Transaction, SimpleJTA, JOTM,
JACC 1.1 115
Bean Validation 1.0 303 Hibernate Validator 4 Apache Bean Validation*
CDI 1.0 299 Weld 1 OpenWebBeans 1, CanDI,
Dependency Injection 1.0 330 Guice 3+ OpenWebBeans 1Weld 1CanDI, Spring 3,
Common Annotations 1.1 250
Application Deployment 1.2 88 Yes
Management 1.1 77
JASPIC 1.0 196

(*) not final yet at the time of writing this article  (+) not sure about that

Yes, it’s a maze and sometimes it’s difficult to walk through it… but hey, that’s also the strengh of being standard, portable and avoiding vendor locking. I will never say that an application is 100% portable through implementations (if you hear someone telling you this, don’t trust him/her), but it can get close to 100% in many cases. That’s also the difference between standard and defacto-standard (check the definition of De Facto).

And because I get lost in this maze, please help me in finding my way out. If I’ve missed something and I’m mistaken, please use the comments to improve this maze and give me your suggestions.


[Debate] – And what about configuration in Java EE 7 ?

How do you configure your enterprise application ? Or to be more precise “what is configuration,  what can you configure in Java EE and how can you configure it ?

What is configuration ?

Sometimes your application needs to change parts of its behavior at deployment time. You then need to provide some external configuration for some components. For example, in your development environment you don’t want to use a datasource and instead hit the database with a user & password, in your test environment you lookup for the datasource and use it. If you deploy your application in Europe you need to use the Euro as the current currency and if you deploy it in the US you need dollars. You’ve deployed your 2.3 version of your application and you want this “2.3” to appear at the bottom of your webpage as well as in your Swing Help->About menu. In a test environment everybody can access all the methods, in production security roles add certain restrictions. And so on and so forth…

In the Java EE specification there are several roles that deal with configuration (chapter 2.11) :

  • Deployer : “During Configuration, external dependencies declared by the Application Component Provider are resolved and application assembly instructions defined by the Application Assembler are followed.”
  • System Administrator : “The System Administrator is responsible for the configuration and administration of the enterprise’s computing and networking infrastructure.”

If you want to read more about configuration of the EE platform I suggest you read chapter 5 of the Java EE 6 spec.

How do we configure today ?

I first need to say that, thanks to Configuration by exception (or Convention over Configuration), you don’t need to add default configuration to your EE 6 application.  Default behavior and default configuration allows most applications to get the behavior they want most of the time, without the use of either annotations or deployment descriptors. But when we need to configure our application, how do we do it today ? The EE platform has some (optional) deployment descriptors you can use such as :

  • web.xml : you can configure parameters in your servlets with <context-param> or filters with  <init-param>
  • ejb-jar.xml : with the <env-entry> you can configure your EJBs
  • application.xml : here you can configure some application specific information such as the context-root of the web application
  • persistence.xml : it’s typically where you will configure the datasource or database access parameters
  • application-client.xml, ra.xml, webservices.xml

Usually these files are located under your WEB-INF or META-INF directory. You can then also use JNDI to access this configuration or create your own environment entries in the JNDI tree. Your methods can then access the environment using the JNDI interfaces and lookup methods on component-specific context objects (or with the @Resource annotation and the new lookup attribute @Resource(lookup="java:app/env/TheOrderQueue")). Since Java EE 6 there are several environment namespaces (java:comp, java:module, java:app, java:global). So the EE prefered approach are environement entries such as this ejb-jar.xml file :

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.2">
    <enterprise-beans>
        <session>
            <ejb-name>MyEJB</ejb-name>
            <ejb-class>org.agoncal.MyEJB</ejb-class>
            <remote>org.agoncal.MyEJBRemote</remote>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
            <resource-ref>
                <res-ref-name>jdbc/employee</res-ref-name>
                <jndi-name>jdbc/__default</jndi-name>
            </resource-ref>
            <env-entry>
                <env-entry-name>aMessage</env-entry-name>
                <env-entry-type>java.lang.String</env-entry-type>
                <env-entry-value>Hello World</env-entry-value>
            </env-entry>
        </session>
    </enterprise-beans>
</ejb-jar>

Environment entries are seen as resources (you can inject them with @Resource) and they can be of any type : String, Object, JMS factories & destinations, datasources… In the code below I inject the datasource called jdbc/employee as well as a String called aMessage :

@Stateless
public class MyEJB {
    @Resource(name="jdbc/employee")
    private DataSource employeeDataSource;

    @Resource(name="aMessage")
    private String welcomeMessage;
    ...
}

With CDI, Qualifiers and Producers you could have the following code which makes use of the CDI typesafety :

@Stateless
public class MyEJB {
    @Inject @EmployeeDS
    private DataSource employeeDataSource;

    @Inject @AHelloWorldMsg
    private String welcomeMessage;
    ...
}

With CDI and Alternatives you can then inject an alternative value for welcomeMessage or a different datasource for the employeeDataSource. Alternatives can then be used to configure your application.

What’s missing ?

JNDI is cool… but can be of a drag when you use servlet containers such as Tomcat or when you do simple batch processing (you don’t want to access a remote JNDI tree) or simple Java class. And EE relies a lot on JNDI. If we look at EJBs, the world is changing : it went from a complex component model to a POJO that can run in an embedded container. So let’s treat it as a POJO.

In the code above, why do I have to treat the welcomeMessage as an environment entry I should lookup ? Why can’t I just treat it as a simple String in a POJO which value changes at deployment time? Datasources, JMS factories… are container resources, but not a welcome message. Going futher, if an EJB is a POJO as well as a Servlet a RESTful Web Service or a Managed Bean, why not just configure these component using the same configuration model ?

CDI brings alternatives and the possibility to inject alternative values. But again, why do I have to use @Produces (to produce a String for the welcome message), @Inject, @Alternative and a seperate class that gives me the value of the alternative welcome message, when I just want to configure externally the value of the String ?

What’s missing in Java EE is a simple way to configure your beans (and by bean I mean EJBs and so on).

What do we do next ?

Java EE 7 has started and we have 18 months to talk about it and make it happen. So why not having a more flexible configuration model in the platform. And because we don’t want to reinvent the wheel, let’s get some inspiration from Spring Config, or even better Seam Config (which makes even XML a bit more type-safe ;o) Taking my previous code example, I would not inject the welcomeMessage but just treat it as a simple String :

@Stateless
public class MyEJB {
    @Inject @EmployeeDS
    private DataSource employeeDataSource;

    private String welcomeMessage;
    ...
}

Then, if I want to configure the welcome message the Seam Config way I’ll have an external XML file (let’s reuse the ejb-jar.xml) and use new namespaces : here the namespace r refers to the package org.agoncal. So r:MyEJB referes to the class org.agoncal.MyEJB. So, as you can see  r:welcomeMessage refers to the property org.agoncal.MyEJB.welcomeMessage in which we set the String Hello World :

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:s="urn:java:ee:ejb"
         xmlns:r="urn:java:org.agoncal" version="3.2">

    <s:enterprise-beans>
        <s:session>
            <r:MyEJB>
                <s:ejb-name>MyEJB</s:ejb-name>
                <s:ejb-class>
                    <r:MyEJB/>
                </s:ejb-class>
                <s:remote>
                    <r:MyEJBRemote/>
                </s:remote>
                <s:session-type-stateless/>
                <s:transaction-type-container/>
                <r:employeeDataSource>
                    <r:ADifferentEmployeeDSQualifier/>
                </r:employeeDataSource>
                <r:welcomeMessage>Hello World</r:welcomeMessage>
            </r:MyEJB>
        </s:session>
    </s:enterprise-beans>
</ejb-jar>

The namespace urn:java:ee:ejb is EJB Config’s root namespace (inspired from Seam Config). This is where the built-in elements live. Here I just give a simple (mayby non accurate) example of what configuration could look like, but if you look at Seam Config, you can configure nearly everything (lists, maps, references…).

And going further ?

Well, if an EJB is a POJO with specific services (transactional, thread safe, secure…) let’s consider it like a bean : a Managed Bean with sepecific services. So let’s declare it in the beans.xml (CDI file). Same for all the managed beans. At the moment there are several deployment descriptors. What about having the possibility to have a single one (as well as multiple like today) to configure the entire plaform ? Something like application.xml could be extended, or beans.xml.

Java EE 7 is going cloud, so why not use the same way to configure your nodes, instances, platform… ?

Let’s continue this debate

I’ve written this blog because I started a thread on the Java EE 7 mailing list on configuration. I’m not an expert on configuration but I can see the benefit of having something similar to Seam Config in the EE platform. Changing (or upgrading) the way we’ve been doing configuration throught environment entries is a huge work (look at all the deployment descriptors that we should have to extend). Is it worth it ? Do you care ?

Use this blog to post your comments or the Java EE 7 mailing list.

References


To inject or not to inject: CDI is the question

Two weeks ago I did a little tour around several JUGs and conferences to talk about dependency injections with CDI. The final goal of this road movie was to end up at GeeCon in Krakow. It was my second time at GeeCon and I have to say that this conference is like good wine : getting better with age. This community based conference is on its third edition and attracts people through out central and eastern Europe. Plenty of good speakers, nice location, skilled attendees… and a lot of fun (GeeCon organizers are party addicts). So make sure you mark this conference into your agenda for next year.

In the meantime, I have made my slides available. Enjoy and do not hesitate to send me some feedback.


Injection with CDI (Part II)

This is the second post based on pure CDI Injection (see Part I) after having talked about how to bootstrap CDI in several environments and how to add CDI to an existing Java EE 6 application. In this post I quickly want to show the different injection points in CDI : field, constructor and setter. To illustrate these different injection points I’ll use a subset of the previous example : a servlet injecting an ISBN generator POJO :

Field injection

Until now, in all the previous posts, you’ve seen the @Inject annotation put on fields (attributes).

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    @Inject
    @ThirteenDigits
    private NumberGenerator numberGenerator;

    @Inject
    private ItemEJB itemEJB;
    ...
}

As you can see in the code above, the @Inject and the qualifiers (here @ThirteenDigits) annotate an attribute. But like many other injection frameworks, in CDI you can also have constructor and setter injection.

Constructor injection

Instead of annotating the attributes, you can add the @Inject annotation on a constructor. If you then need to use qualifiers, you can add them to the attributes of the constructor as follow :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    private NumberGenerator numberGenerator;
    private ItemEJB itemEJB;

    @Inject
    public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator, ItemEJB itemEJB) {
        this.numberGenerator = numberGenerator;
        this.itemEJB = itemEJB;
    }
    ...
}

As you can see, the @Inject is not on the field but on the constructor. On the other hand, @ThirteenDigits doesn’t qualify the constructor but the numberGenerator parameter itself (which is logical). You can also mix field and constructor injection if you want (below I use constructor injection and attribute injection on the EJB) :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    private NumberGenerator numberGenerator;

    @Inject
    private ItemEJB itemEJB;

    @Inject
    public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator) {
        this.numberGenerator = numberGenerator;
    }
    ...
}

But the rule is : you can only have one constructor injection point. The container is the one doing injection, not you (you can’t invoke a constructor in a managed environment, well, you can, but it will not work as you expect). There is only one bean constructor allowed so the container can do its job of injecting the right references. The following is invalid :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    private NumberGenerator numberGenerator;
    private ItemEJB itemEJB;

    @Inject
    public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator, ItemEJB itemEJB) {
        this.numberGenerator = numberGenerator;
        this.itemEJB = itemEJB;
    }

    @Inject
    public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator) {
        this.numberGenerator = numberGenerator;
    }
	...
}

If you have more than one bean constuctor, this is what you get (the error code and message is Weld specific of course) :

WELD-000812 Cannot determine constructor to use for public@WebServlet class ItemServlet. Possible constructors [[constructor] @Inject public ItemServlet(NumberGenerator, ItemEJB), [constructor] @Inject public ItemServlet(NumberGenerator)]

On the other hand, it is syntactically legal to have field and constructor injection at the same time (but useless) :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    @Inject @ThirteenDigits
    private NumberGenerator numberGenerator;
    @Inject
    private ItemEJB itemEJB;

    @Inject
    public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator, ItemEJB itemEJB) {
        this.numberGenerator = numberGenerator;
        this.itemEJB = itemEJB;
    }
    ...
}

Setter injection

The other choice is to use setter injection which looks like constructor injection. You annotate the setter with @Inject and you qualify the parameters :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    private NumberGenerator numberGenerator;
    private ItemEJB itemEJB;

    @Inject
    public void setNumberGenerator(@ThirteenDigits NumberGenerator numberGenerator) {
        this.numberGenerator = numberGenerator;
    }

    @Inject
    public void setItemEJB(ItemEJB itemEJB) {
        this.itemEJB = itemEJB;
    }
    ...
}

When you use constructor or setter injection you need to apply your qualifiers to a parameter. So make sure you have the right @Targets (java.lang.annotation.ElementType.PARAMETER) definition :

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD, PARAMETER})
public @interface ThirteenDigits {
}

Conclusion

One question you could ask (and that’s the one I asked to Pete Muir) is : “when do you use field over constructor or setter injection ?”. There is no real technical answer except that it’s your personal taste. In a managed environment, the container is the one doing all the injection work, it just needs the right injection points. However, with constructor or setter injection you can add some logic if needed (not with field injection). But it looks like setter injection was added for backward compatibility with existing Java Beans.

The next article will cover producers, so stay tuned.

Download

Download the code, give it a try, and give me some feedback.

References


A week in central Europe… with CDI

I haven’t talked much lately at conferences or JUGs. The last one was Devoxx in November 2010 and I have been quite ever since (working on some other plans ;o) But it’s time to do a bit of touring again. This time it will be Central Europe and the topic with injection in CDI. The presentation of the talk is To inject or not to inject: CDI is the question and the description roughly is :

After a quick introduction of CDI (Contexts and Dependency Injection) I will concentrate on dependency injection and the type-safe approach on injection in CDI. If you are fed up of using String based configuration, come to this talk and have a type-safe journey on CDI.

How come I am touring again ? Everything started with an invitation from my friends at GeeCon. I discovered GeeCon in 2009. It was the first edition of this conference in Cracow (Poland) created by the local user group. As I mentioned in my post, I really liked the conference as it felt very professional with good speakers and nice atmosphere. So this year I’ve accepted the invitation and I’m going back to the 2011 edition to talk about injection in CDI…. and on my way, I’ve decided to have some stop-overs :

  • Monday 9th of May – come on listen to my talk at the JUG Cologne in Germany (Map)
  • Tuesday 10th of May – CZJUG (Prague – Czech Republic) : it’s going to be a busy day. I’ll spend the day at the EMEA Oracle User Group (Map) and then go to the JUG to do my talk at 7pm (Map).
  • Wednesday 11th of May – GeeCon (Cracow – Poland) : I’ll be doing a Java EE 6 university talk with my friend Alexis Moussine-Pouchkine. It will be the same talk we did at Devoxx last year, but updated of course
  • Thursday 12th of May - GeeCon (Map) I’ll do my CDI talk
  • On Friday I will have fun and a relaxing time in Cracow (it is such a nice city)
  • Then I’ll visit some friends in Venice (Italy) and stay during the week-end (not talking about Java at all, drinking wine and eating pasta)
  • … and then back home

View Larger Map

I’ll be doing all these trips using my favorite transport : night trains. So if you are anywhere near and want to attend one of my talks… of just have a beer, fill free to come.

See you


Formation Java EE 6 en juin à Paris

XebiaVos avez un nouveau projet dans les tuyaux ? Vous vous questionnez sur les frameworks à choisir ? Vous hésitez à utiliser votre framework printanier à base d’XML et de complexité ? Vous voulez migrer votre application vers un standard ? Vous détestez les EJBs ? J’ai ce qu’il vous faut : une formation de 3 jours autour de Java EE 6 intitulée Architectures d’aujourd’hui avec Java EE 6.

Cette formation a été créé par mes soins, s’inspire de mon livre et a pour objectif de démystifier la nouvelle plate-forme Java EE. Elle allie présentations et séances de développement (MavenGlassFishIntellij IdeaJRebel) en mettant l’accent sur les bonnes pratiques d’architectures. Patterns d’hier devenus anti-patterns aujourd’hui, course au découplage, sur-découpage en couches… vous apprendrez à utiliser les briques techniques de Java EE 6 (JPA 2.0, EJB 3.1, JSF 2.0, Bean Validation 1.0, CDI 1.0 et JAX-RS 1.0) pour répondre au mieux aux besoins de vos utilisateurs.


Et comme goodies vous aurez un exemplaire de mon livre, une licence d’Intellij Idea ainsi qu’une licence JRebel de 6 semaines, c’est pas beau ça ?!?!

La prochaine formation aura lieu chez Xebia du 6 au 8 juin, alors n’hésitez pas à vous inscrire.


Injection with CDI (Part I)

After writing a post about how to bootstrap CDI in your environment and giving you some tips about how to incorporate CDI in an existing Java EE 6 application, I want to talk about injection. Yes, pure injection or how to inject a bean into another one. As you’ll see in this series of three articles (Part II), many different cases can happen. Let’s start with a simple one : a straight forward injection.

Default injection

The simplest possible injection case is… simple. You have something, and you inject something into it. Why am I using the word something ? Because until Java EE 5 we could only inject resources (EntityManager, Datasource, JMS destinations and factories…) into certain components (EJBs and Servlets). With CDI, you can inject nearly anything into anything else.

Versions of software used for this arcticle
Java SE 1.6.0_23
GlassFish 3.1
Maven 3.0.2

To illustrate injection I’ll be using the same use case I’ve used in previous articles or in my Java EE 6 book : a CD-Book store.

The class diagram above shows the following components :

  • Book is just an Entity with some attributes and named queries
  • ItemEJB is a stateless EJB (with no interface) doing CRUD operations on the Book thanks to the EntityManager
  • IsbnGenerator is just a POJO that generates a random ISBN number (used for the Book)
  • ItemRestService is annotated with @Path (which designates a REST web service in JAX-RS) and delegates the CRUD operation to the ItemEJB
  • ItemServlet is a Servlet that uses the ItemEJB to display all the books from the database

As you can see, except for the EntityManager that is injected with @PersistenceContext, all the other components use @Inject. Here is a few lines of code of the ItemEJB getting a reference of the EntityManager :

@Stateless
public class ItemEJB {

    @PersistenceContext(unitName = "cdiPU")
    private EntityManager em;
    ...
}

The ItemServlet and the ItemRestService are very similar as they both inject a reference of the ItemEJB and the IsbnGenerator :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    @Inject
    private IsbnGenerator numberGenerator;

    @Inject
    private ItemEJB itemEJB;
    ...
}

And the IsbnGenertor has absolutely nothing special to it as it doesn’t extends from anything nor it is annotated, it’s just a POJO :

public class IsbnGenerator {

    public String generateNumber () {
        return "13-84356-" + Math.abs(new Random().nextInt());
    }
}

In all these cases there is only one implementation to choose from (there is only ItemEJB, only one IsbnGenerator). If you only have one implementation, CDI will be able to inject it. We then talk about default injection. In fact, the code :

@Inject IsbnGenerator numberGenerator

could have been written

@Inject @Default IsbnGenerator numberGenerator

@Default is a built in qualifier that informs CDI to inject the default bean implementation. If you define a bean with no qualifier, the bean automatically has the qualifier @Default. The following code is identical to the previous one.

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    @Inject @Default
    private IsbnGenerator numberGenerator;
    ...
}

@Default
public class IsbnGenerator {

    public String generateNumber () {
        return "13-84356-" + Math.abs(new Random().nextInt());
    }
}

If you only have one implementation of the IsbnGenerator to inject, the default behaviour applies and a straight forward @Inject does the job. But sometimes you have to choose between several implementations, that’s where qualifiers come into play.

In this article I use the term bean, but to be more precise I should say managed bean (ie beans that are managed by CDI). ManagedBeans have been introduced in Java EE 6.

Ambiguous injection & Qualifiers

For a given bean type, there may be multiple beans which implement the type. For example, our application can have two implementations of the NumberGenerator interface : IsbnGenerator generates a 13 digits number and IssnGenerator a 8 digits number. A component that needs to generate a 13 digits number needs some way to distinguish between the two implementations. One approach would be to explicitly specify the class (IsbnGenerator) but that creates a hard dependence between the component and the implementation. Another approach would be to rely on external XML configuration to declare and inject the appropriate bean. CDI uses qualifiers, which are annotations, to get strong typing and loose coupling.

In this article I’m using injection on the attribute, meaning that the @Inject annotation is on the attribute. But with CDI you can also use setter injection or constructor injection.

Let’s say, for some reason, that the ItemServlet creates books with a 13 digits ISBN number, and the ItemRestService creates books with a 8 digits ISSN number. Both (the ItemServlet and the ItemRestService) inject a reference of the same NumberGenerator interface, which implementation will there use ? You don’t know ? CDI doesn’t know either, and this is the kind of error message you will get :

Ambiguous dependencies for type [NumberGenerator] with qualifiers [@Default] at injection point [[field] @Inject private ItemRestService.numberGenerator]. Possible dependencies [[Managed Bean [class IsbnGenerator] with qualifiers [@Any @Default], Managed Bean [class IssnGenerator] with qualifiers [@Any @Default]]].

That means we need to be less ambiguous and tell CDI which bean to inject where. If you come from Spring the first thing that comes to your mind is “let’s use the beans.xml file“. But as this post says, “beans.xml is not there to define beans in XML“. With CDI you use qualifiers (annotations).

There are three built-in qualifiers in CDI :

  • @Default : If a bean does not explicitly declare a qualifier, the bean has a @Default qualifier
  • @Any : allows the application to specify qualifiers dynamically
  • @New : allows the application to obtain a new qualified bean

A qualifier represents some semantic associated with a type that is satisfied by some implementations of the type. For example, you could introduce qualifiers to represent thirteen digits number generator or eight digits number generator. In Java qualifiers are represented by annotations defined as @Target({FIELD, TYPE, METHOD}) and @Retention(RUNTIME). It is declared by specifying the @javax.inject.Qualifier meta-annotation as follow :

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface EightDigits {
}

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface ThirteenDigits {
}

As you can see, I’ve just defined two qualifiers, very easily. Right, so how do I use them now ? Better than words, a class diagram will make it clear.

First of all, the qualifiers need to be applied on the appropriate implementation. As you can see, @ThirteenDigits is applied to IsbnGenerator and @EightDigits to @IssnGenerator :

@EightDigits
public class IssnGenerator implements NumberGenerator {

    public String generateNumber() {
        return "8-" + Math.abs(new Random().nextInt());
    }
}

@ThirteenDigits
public class IsbnGenerator implements NumberGenerator {

    public String generateNumber() {
        return "13-84356-" + Math.abs(new Random().nextInt());
    }
}

Then, the components that inject a reference to the NumberGenerator interface also need to use it as follow :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    @Inject @ThirteenDigits
    private NumberGenerator numberGenerator;
    ...
}

@Path("/items")
@ManagedBean
public class ItemRestService {

    @Inject @EightDigits
    private NumberGenerator numberGenerator;
    ...
}

You don’t need external configuration, that’s why CDI is said to use strong typing. You can rename your implementations to whatever you want, the injection point will not change (that’s loose coupling). Note that a bean may declare multiple qualifiers. As you can see, CDI is an elegant way to have typesafe injection. But if you start creating annotations each time you need to inject something, your application will end up being very verbose. That’s when enumerations can help you.

Qualifiers with enumerations

Each time you need to choose between implementation you create an annotation. So if you need an extra two digits number generator or a ten digits number generator you create more and more annotations. Looks like we are moving from XML Hell to Annotation Hell ! One way to avoid the multiplication of annotations is to use enumeration as follow :

@WebServlet(urlPatterns = "/itemServlet")
public class ItemServlet extends HttpServlet {

    @Inject @NumberOfDigits(Digits.THIRTEEN)
    private NumberGenerator numberGenerator;
    ...
}

@Path("/items")
@ManagedBean
public class ItemRestService {

    @Inject @NumberOfDigits(Digits.EIGHT)
    private NumberGenerator numberGenerator;
    ...
}

@NumberOfDigits(Digits.THIRTEEN)
public class IsbnGenerator implements NumberGenerator {

    public String generateNumber() {
        return "13-84356-" + Math.abs(new Random().nextInt());
    }
}

@NumberOfDigits(Digits.EIGHT)
public class IssnGenerator implements NumberGenerator {

    public String generateNumber() {
        return "8-" + Math.abs(new Random().nextInt());
    }
}

As you can see I got rid of the @ThirteenDigits and @EightDigits qualifiers and I’m using the single qualifier @NumberOfDigits which as an enumerations as a value (in my example @EightDigits). This is the code you need to write :

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface NumberOfDigits {
    Digits value();
}

public enum Digits {
    TWO,
    EIGHT,
    TEN,
    THIRTEEN
}

Conclusion

I don’t know about you, but I love it. I really like the way CDI wires beans together without XML, just with pure Java in a type-safe way. Ok, ok, I admit, not everything is beautiful. The first thing I see is the multiplication of annotations in your code. Thanks to enumerations, this can be limited. The other point I can see is the IDE support. Your IDE needs to be cleaver to know that :

@Inject @NumberOfDigits(Digits.EIGHT) NumberGenerator numberGenerator

refers to IssnGenerator. But here I’m talking without really knowing much about the topic. I use Intellij IDEA and the CDI support is just amazing. I can navigate from bean to bean without worrying about knowing the implementation. I suppose NetBeans might have some kind of support… but I wonder if Eclipse does ;o)

The next article will cover the different available injection points, so stay tuned.

Download

Download the code, give it a try, and give me some feedback.

References