Using OpenEJB for EJB3 testing with Maven2

Like I promised here I will show my project setup in which I test my EJB3 beans with OpenEJB. Although there are a lot of examples provided with OpenEJB I ran into some minor issues that I will explain here. I assume the Maven2 basics are known so I won’t go into much detail about that.

This is my stack:

  • JDK1.5
  • Maven2
  • EJB3 project
  • Glassfish EJB Container


I have the following project structure:

  • my-project (parent pom)
  • my-core (jar)
  • my-entities (jar)
  • my-services (ejb)
  • my-business-services (ejb)
  • my-business-services-ear (ear)

The used Maven2 ‘settings.xml’ can be viewed here (use view source if your browser messes up the xml content). The use of the ‘develop’ and ‘test’ profile will be clarified later. The ‘repos’ profile makes all necessary repositories available for downloading.

Next I will go through each module and explain the important parts of it in relation with the unit testing of the code. Please notice that the Java examples are just examples, they are not written with the idea to be used in a real application.

  • The parent project
  • Contains nothing but the parent pom. The parent pom looks like this.

  • The ‘my-core’ module
  • This is just a simple jar-module that will contain all constants and utility classes that are used throughout the application. The pom looks like
    this.
    There is no special configuration here.

  • The ‘my-model’ module
  • This one contains the model of the application which are in this case the EJB Entity objects reflecting the underlying database model. The content of the project:

    $ find . -type f
    ./pom.xml
    ./src/main/java/net/pascalalma/model/Customer.java
    ./src/main/resources/META-INF/ejb-jar.xml
    ./src/main/resources/META-INF/MANIFEST.MF
    ./src/main/resources/META-INF/persistence.xml

    The Customer.java is just a simple Entity bean.
    The pom of the project looks like this (complete file is here).

    ...
        <dependencies>
            <!-- Libraries necessary for compiling -->
            <dependency>
                <groupId>glassfish</groupId>
                <artifactId>appserv-rt.jar</artifactId>
                <version>LATEST</version>
                <scope>system</scope>
                <systemPath>${glassfish.home}/lib/appserv-rt.jar</systemPath>
            </dependency>
            <dependency>
                <groupId>glassfish</groupId>
                <artifactId>javaee.jar</artifactId>
                <version>LATEST</version>
                <scope>system</scope>
                <systemPath>${glassfish.home}/lib/javaee.jar</systemPath>
            </dependency>
        </dependencies>
        <build>
            <resources>
                <resource>
                    <!-- Use filtering so the property values are written to persistnece.xml
                         based on the selected profile (develop or test) -->
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    ...
    

    As you can see I refer to the Glassfish jars to compile my bean. You can pick your own JEE implementation here. Another thing I do is filtering the persistence.xml. This file looks like:

    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
      <persistence-unit name="MyPersistenceUnit" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/MyDS</jta-data-source>
        <properties>
          <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
          <property name="hibernate.transaction.manager_lookup_class" value="org.apache.openejb.hibernate.TransactionManagerLookup"/>
          <property name="hibernate.show_sql" value="${hibernate.show_sql}"/>
          <property name="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}"/>
        </properties>
      </persistence-unit>
    </persistence>
    

    Some Hibernate values are depending on the profile I chose when building the project (see the settings.xml I showed at the beginning of this post). I have two profiles: ‘develop’ and ‘test’. In ‘develop’ mode Hibernate will drop and recreate all tables in my entity objects. And that is good because this is necessary for my unit tests to succeed. But when I am deploying this ear on my test server and the datasource is referring to my test database I don’t want this ‘dropping and recreating’ to happen. That’s why I created this ‘switch’. When creating an ear to be deployed on our test server I have to choose the ‘test’ profile so no dropping of the scheme occurs and this will also result in skipping the tests when building the ear file, since these would fail anyway. Although this is not fail safe at all, it’s something I can live with at the moment.
    Finally there is the ‘ejb-jar.xml’ file in the project. This one is empty and only there because OpenEJB needs it to recognize the EJBs.

  • The ‘my-services’ module
  • Now the real work begins. This module contains the fine grained services that are based at one entity.
    The module contains:

    $ find . -type f
    ./pom.xml
    ./src/main/java/net/pascalalma/myservices/CustomerServiceBean.java
    ./src/main/java/net/pascalalma/myservices/CustomerServiceLocal.java
    ./src/main/resources/META-INF/ejb-jar.xml
    ./src/main/resources/META-INF/MANIFEST.MF
    ./src/test/java/net/pascalalma/myservices/EJBTestBase.java
    ./src/test/java/net/pascalalma/myservices/TestCustomerService.java
    ./src/test/resources/import.sql
    ./src/test/resources/log4j.properties
    ./src/test/resources/META-INF/ejb-jar.xml

    First let’s look at the pom (complete version here):

    ...
        <dependencies>
            ...
            <!-- libraries necessary for testing -->
            <dependency>
                <groupId>org.apache.openejb</groupId>
                <artifactId>openejb-core</artifactId>
                <version>3.1</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>3.4.0.GA</version>
                <scope>test</scope>
            </dependency>
            <dependency>
        ...
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-ejb-plugin</artifactId>
                    <configuration>
                        <generateClient>false</generateClient>
                        <ejbVersion>3.0</ejbVersion>
                    </configuration>
                </plugin>
            </plugins>
            <finalName>my-services</finalName>
        </build>
    ...
    

    I have added some new depencies for testing the module: the OpenEJB dependency and some hibernate libraries. And I have configured the ejb-plugin to create an EJB3 jar of the module, notice that the packaging of the project is set to ‘ejb’.
    The bean files themselves contain nothing special.
    The interface here and the implementation here.

    Then the test files. The first I want to mention is the ‘import.sql’import. This is used by a feature of Hibernate. It executes the ‘import.sql’ file as it is found on the classpath after creating the database. For now this is sufficient but I am not sure about the future.
    Then there is the ‘EJBTestBase.java’. Actually this code is based on the examples that are provided with OpenEJB. There is one ‘hack’ to make it possible to test your methods inside an existing transaction but this is also described in the examples. This ‘hack’ is also the reason for the ejb-jar.xml in the test resources. A new ‘TransactionBean’ is instantiated in this context so an ejb-jar.xml is necessary.
    And finally there is the ‘TestCustomerService.java’ where the testing of the session bean is done. In this file the JNDI lookup is essential:

    csb = (CustomerServiceLocal)context.lookup("CustomerServiceBeanLocal");
    

    The JNDI name is configurable in OpenEJB and by default differs from the used syntax in Glassfish. But since this test class won’t be used in Glassfish that’s no problem here, but something to keep in mind if you need JNDI look ups in your production code.

  • the module ‘my-business-services’
  • This module contains the following files:

    $ find . -type f./pom.xml
    ./src/main/java/net/pascalalma/mybusinessservices/CustomerBusinessServiceBean.java
    ./src/main/java/net/pascalalma/mybusinessservices/CustomerBusinessServiceRemote.java
    ./src/main/resources/log4j.properties
    ./src/main/resources/META-INF/ejb-jar.xml
    ./src/test/java/net/pascalalma/mybusinessservices/TestCustomerbusinessService.java
    ./src/test/resources/import.sql

    The pom of this project contains nothing new. We have seen all used dependencies and plugins in other modules already.
    The EJB is made up of a remote interface ‘CustomerBusinessServiceRemote’ and its implementation ‘CustomerBusinessServiceBean’. The most important thing here is the injection of a session bean into this bean:

     ...
     @EJB
     private CustomerServiceLocal cs;
     ...
    

    The bean in this module is tested with the class ‘TestCustomerbusinessService’.
    This test class looks similar to the one in the ‘my-service’ module. We also use a JNDI lookup in the local EJb container to get a pointer to the ‘business service’ bean and then call the methods on it.

      ...
      ots = (CustomerBusinessServiceRemote) context.lookup("CustomerBusinessServiceRemote");
      assert ots != null;
      ots.validateCustomer("1");
      ..
    
  • The ‘my-business-services-ear’ module
  • This project only contains a ‘pom.xml’ that contains the necessary configuration to create an ear file for the whole project and a plugin to deploy it to GlassFish.

To test the final deployment in Glassfish I turned my remote interface into a webservice by adding this to the interface:

@WebService
@SOAPBinding(style = javax.jws.soap.SOAPBinding.Style.DOCUMENT
            ,use = javax.jws.soap.SOAPBinding.Use.LITERAL
            ,parameterStyle = javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED)

and this to the class:

@WebService( endpointInterface = "net.pascalalma.mybusinessservices.CustomerBusinessServiceRemote"
           , serviceName = "CustomerBusinessService")

If I try to build this, however, the remote interface dissapears in the JNDI tree of OpenEJB?!?! So the unit test for this EJB will fail. I worked around this to just build the ear by skipping the tests and deploy it (see this post for more info about deploying to Glassfish with Maven).
A nicer solution would be to add a local interface for the EJB and use that one in the test class. This way the implementation stays the same and that is what is supposed to be tested.

Advertisement

About Pascal Alma

Pascal is a senior IT consultant and has been working in IT since 1997. He is monitoring the latest development in new technologies (Mobile, Cloud, Big Data) closely and particularly interested in Java open source tool stacks, cloud related technologies like AWS and mobile development like building iOS apps with Swift. Specialties: Java/JEE/Spring Amazon AWS API/REST Big Data Continuous Delivery Swift/iOS
This entry was posted in EJB3 and tagged , , . Bookmark the permalink.

6 Responses to Using OpenEJB for EJB3 testing with Maven2

  1. Konstantin says:

    Hi. I’m converting my project from ant to maven2 and this is the most useful post about maven + ejb over the internet, really. Thanks a lot.

  2. Craig says:

    Thank you for a detailed explanation of how to use Maven, because they could not understand how to use the program, but thanks to your explanation, all became clear!

  3. David Blevins says:

    Great blog post. Going to forward this to the OpenEJB list. I see what you mean about the interface. We can definitely fix that. A great deal of the feature set is driven by feedback like this, so if you have any more, we’re all ears.

  4. David Blevins says:

    Just a followup. We’ve added the @Remote + @WebService feature (along with any combination of @Remote, @Local, @WebService). It will be available in the 3.1.1 release. As well we’ve pushed to get this clarified in the coming EJB 3.1 spec.

  5. jptech says:

    Hi Pascal,

    You pointed me here from a post on the Glassfish forum.

    This is a nice blog entry. I really wish I’d have seen it about a month ago since I ended up struggling through the same thing on my own. I have a couple of questions if you don’t mind.

    I use a very similar project structure, except I don’t have an equivalent to your ‘my-services’ module. Would you mind explaining the concept behind that module? I assume it’s so you can add more ‘business-services’ type modules later without having to reproduce the basic functionality of ‘my-services’ or (maybe worse) mix EJBs from different ‘business-services’.

    Also, I tend to split my remote interfaces into separate modules. Using your structure as an example, I’d have:

    ‘my-entities’
    ‘my-business-services-api’
    ‘my-business-services-impl’

    Do you have any thoughts on whether or not such a design adds any benefit? It’s not necessary to distribute the ‘my-business-services-impl’ module with application clients, but I’m starting to wonder if it’s worth the hassle of having an extra module for it.

    As for the question I was asking on the GF forums, I was asking about combining all of the annotations because I’d like to have the ability to build two UI clients for my app. I’d like to (be able to) build one in Adobe Flex using webservices and one in Java using remote EJBs.

    I’d only develop one UI for my app at the moment and have a partially developed Java Swing UI, but I’ve decided to take a week and assess the viability of moving to Flex as a front end technology. I was hoping to mix annotations temporarily so I could re-implement a portion of my UI in Flex and compare the two techs.

    After reading your blog post I’m thinking the best strategy for me will be to add an EJB module similar to your ‘my-services’ module and keep adding ‘my-business-services’ style modules for each UI type since it’s very unlikely I’d actually end up writing two UIs using different tech but the same requirements. For example:

    ‘my-web-services’ (Flex UI)
    ‘my-remote-ejb-services’ (Java UI)

    I apologize if my comment seems a bit long winded. I’d appreciate any feedback you can give me, even if it’s harshly worded criticism.

  6. Pascal Alma says:

    Hi JPTech,

    Thx for your comment. I’ll try to find some time coming days to give you an answer/feedback.

Comments are closed.