JavaGen.com

EJB JAMing - Building & Testing EJBs using JAM

This page discuses the packaging, deployment, and testing of a simple EJB example. The focus is on using JAM (JavaGen Ant Modules) and understanding the supporting build files. Also discussed is re-generating the code using the included UML file and JavaGen. If you're only interested in using JAM, just skip the JavaGen code generation step. This example uses the JBoss J2EE application server and Cactus for integration testing. By the end of this tutorial you will have a reusable, database-independent primary key generator in your local repository.

AutoPK EJB Example

Most databases have a mechanism for creating primary keys automatically when new data is inserted. Unfortunately, achieving this varies from vender to vender and often requires specialized handling when installing J2EE applications. A more generic solution is to handle the generation of primary keys with pure Java. The AutoPK module used in this tutorial is an EJB-based automatic primary key generator used extensively by JavaGen for solving this problem. The following UML diagram shows the design of the code we will be working with:

AutoPK UML Class Diagram
DIAGRAM 1 - AutoPK UML Class Diagram

Step-by-Step instructions:

  1. The prerequisites for this example are working installations of Java, Ant, Maven, JAM and JBoss. If your missing any of these tools, complete the setup instructions before preceding.
  2. Download and extract the AutoPK source code located on the download page.
  3. Examining the contents, you should see the following files and directory layout:
    	+ autopk               - module folder
    	  | - build.xml        - Ant build file
    	  | - project.xml      - Maven POM file
    	  | - classpath.xml    - Ant classpath and deployment properties
    	  | - props-module.xml - Module-specific property settings.
    	  + src                - source code folder
    	    + java             - Java source folder
    	    + META-INF         - deployment descriptor folder
    	    + test             - unit tests source folder
    	    + test-cactus      - integration tests source folder
    	    + uml              - UML model (input for JavaGen)
    	  + src-gen            - generated source code folder
    	    + java             - generated Java source folder
    	    + META-INF         - generated deployment descriptor folder
    	    + test             - generated unit tests source folder
    	    + test-cactus      - generated integration tests source folder
    	
    Poking around in the code, you will notice there are actually only two source files located under the src-gen/java directory and a few unit test files located under src-gen/test-cactus. As you'll see later, these files were all generated using JavaGen. Teaser question #1: A good question to ask yourself as you work through this exercise is: Where's the beef? Hint: it's in two files.
  4. The build.xml file is pretty much an exact copy of the standard JAM EJB template. The most important detail is specifying the name attribute, in this case 'javagen-autopk-ejb', which is used for naming deployment files. To test this build file type ant setup and make sure the displayed settings make sense. To see a listing of the commands we will be working with type ant -p. In this tutorial we are more interested in using JAM, rather than how it works, but if you want more details see the JAM User's Guide. Here are contents of build.xml:
    <?xml version="1.0"?>
    <project name="javagen-autopk-ejb" default="default" basedir=".">
      <description>
      + ==\_/============J=A=V=A=G=E=N===A=N=T===M=O=D=U=L=E=S================= +
      +  \(_)/                                                                  +
      +  -(_)-                 AutoPK EJB Build Targets                         +
      +  /(_)\                                                                  +
      + ======================================================================= +
      + =  Copyright (c) 2002-2004 Outsource Cafe, Inc.  All rights reserved. = +
      + ======================================================================= +
      + 
      + AutoPk EJB generates unique primary keys.  It is used as the default key
      + provider for CMP EJBs that have the cmp-autopk stereotype.
      +
      + =J=A=M===========================================J=A=V=A=G=E=N=.=C=O=M= +
      </description>
      <property environment="env"/>
      <property name="jam.home" location="${env.JAM_HOME}"/>
      <property name="project.home" location="."/>
      <import file="${basedir}/props-module.xml" optional="true"/>
      <import file="${project.home}/props-project.xml" optional="true"/>
      <import file="${user.home}/.ant/props-user.xml" optional="true"/>
      <import file="${jam.home}/props-global.xml"/>
      <import file="${basedir}/classpath.xml"/>
      <import file="${jam.home}/appserver-jboss3.xml"/>
      <import file="${jam.home}/ejb.xml"/>
      <import file="${jam.home}/ejbtest-cactus.xml"/>
      <!-- =================================================================== -->
      <!-- Override standard targets: -->
      <!-- =================================================================== -->
      <!-- override dist to wrap EJBs in Cactus distribution file:  -->
      <target name="dist" depends="ejb.dist,testdist" description="generate target and test distribution files"/>
      <!-- override to deploy Cactus distribution instead of EJB jar file:  -->
      <target name="deploy" depends="dist" description="deploys ejb and test archives to server">
        <antcall target="appserver.deploy">
          <param name="dist.name" value="${test.dist.name}"/>
        </antcall>
      </target>
      <!-- override to undeploy Cactus distribution instead of EJB jar file:  -->
      <target name="undeploy" description="removes archive from server deploy folder">
        <antcall target="appserver.undeploy">
          <param name="dist.name" value="${test.dist.name}"/>
        </antcall>
      </target>
    </project>
    	
  5. The POM (project.xml) file lists the dependencies that are required to build and deploy this EJB. Besides being a great source of documentation, it is used to generate the classpath.xml file and application.xml deployment descriptor. Looking at the dependencies listed in the POM, you can see that the j2ee, xdoclet-ejb-module, and junit libraries are required for the build process and that the log4j library is required for both the build and deployment. You should be able to use the provided classpath.xml file as-is, but if you would like to regenerate it, type:
    maven javagen:classpath
    Likewise, the application.xml file used for deploying the Cactus test code, was generated using the command:
    maven javagen:appxml-cactus
    Note: The new Cactus application.xml file will end up in the src-gen/META-INF directory, move it to the src/META-INF to prevent it from being overwritten. Here is a partial listing of the POM contents:
    <?xml version="1.0"?>
    <project>
      ...snip...
      <dependencies>
        <dependency>
          <id>j2ee</id>
          <version>1.3.1</version>
        </dependency>
        <dependency>
          <id>xdoclet+ejb-module</id>
          <version>1.2</version>
        </dependency>
        <dependency>
          <id>junit</id>
          <version>3.8.1</version>
        </dependency>
        <dependency>
          <id>log4j</id>
          <version>1.2.8</version>
          <properties>
            <ear.bundle>true</ear.bundle>
          </properties>	  
        </dependency>
      </dependencies>
      <build>
      </build>
    </project>	
  6. The props-module.xml property file is trivial, as it just sets the version number and folder name under which this distribution will be stored in the local repository. To see these settings type ant setup. Here is the contents of props-module.xml:
    <?xml version="1.0"?>
    <project name="props-module">
      <description>
      + ==\_/============J=A=V=A=G=E=N===A=N=T===M=O=D=U=L=E=S================= +
      +  \(_)/                                                                  +
      +  -(_)-            Module Properties for JavaGen AutoPK                  +
      +  /(_)\                                                                  +
      + ======================================================================= +
      +    Copyright (c) 2002-2004 Outsource Cafe, Inc.  All rights reserved.   +
      + ======================================================================= +
      </description>
      <!-- ===================================================================== -->
      <!-- current version: -->
      <!-- ===================================================================== -->
      <property name="module.version" value="1.0"/>
      <!-- ===================================================================== -->
      <!-- repository folder name: -->
      <!-- ===================================================================== -->
      <property name="maven.groupId" value="javagen"/>
    </project>
    	
  7. Now let's do something useful. Issue the command ant gen. This command calls XDoclet which generates EJB support code and deployment descriptors using information located in the EJB source code. JAM uses XDoclet extensively to avoid a lot of repetitive work. To see the generated files look in the target/xdoclet directory.
  8. Next issue the command ant compile which compiles everything found in the src/java, src-gen/java and target/xdoclet/java directories. If you received an error make sure your setup is correct and check your classpath by issuing the ant cp command.
  9. To package your EJB into a jar file, type ant ejb.dist. This should result in the creation of the javagen-autopk-ejb-1.0.jar in the dist directory. You now have a ready-to-use EJB distribution. Teaser question #2: Why did you have to type ant ejb.dist instead of ant dist? Hint: this is an Ant 1.6 feature and is core to understanding and using JAM.
  10. Now lets prepare this code for testing using Apache Cactus. Type ant dist. This command compiles integration test source code found in the src/test-cactus and src-gen/test-cactus directories and packages them into a cactus.war file which along with the EJB jar is packaged into an ear file. You can see all these files under the dist directory. If you want to see whats in a jar, war or ear file, they can all be viewed using a zip utility like WinZip.
  11. In preparation for testing start JBoss in a separate console. Type run from the JBoss bin directory and wait for it to startup. Keep this console visible so you can watch the deployment progress.
  12. Now you are ready to deploy. Type ant deploy from the AutoPK console. The server console will indicate its progress as it verifies the deployment descriptors, installs the EJBs, and creates the database tables. All the deploy command does is copy the distribution file to the deploy directory of the server. If you have problems, copy it manually. One Cavet when using Cactus is that if you have other test deployments on the server using the cactus web context, you'll get deployment errors. Remembering to remove Cactus deployments when your done, will avoid this problem.
  13. To verify your code is working, run the integration tests by typing ant itest. If everything is setup correctly, there should be no errors or failures. The test results are summarized into a nicely formatted HTML page located in the target/reports directory.
  14. Type ant undeploy to remove the test deployment from JBoss. Again, all the undeploy command does is delete the distribution file from the deploy directory of the server. If you have problems, delete it manually.
  15. If everything is working at this point, congratulations! Clean up everything you've done by typing ant clean. Now lets try something really bold, type ant testcycle. This target automates everything we have done so far in this tutorial. It can be used as the basis for implementing a continuous integration process and should work weather the server is started or not. If it doesn't work, you may have to adjust the delay properties (appserver.start.delay, appserver.deploy.delay and appserver.post.stop.delay) found in appserver-jboss3.xml. The main point is you can't deploy until the server has started, nor can you run the test until the deployment is complete. Watch the console sequence to see if these times are appropriate for your machine's speed and deployment size.
  16. Now that we know this code is working, we can make it available to other applications by placing it in the local repository by typing: ant repo. This places the EJB jar javagen-autopk-ejb-1.0.jar in the javagen/jars sub-directory of the repository. Now you can include this in other projects by declaring the following dependency in your POM files:
        <dependency>
          <id>javagen+autopk-ejb</id>
          <version>1.0</version>
          <type>ejb</type>
          <properties>
            <ear.bundle>true</ear.bundle>
          </properties>	  
        </dependency>
    	
  17. To round this tutorial off, try re-generating the EJBs from the UML using the on-line JavaGen code generator. Rename or delete the src-gen folder and point your browser at the UML Upload page. Upload the AutoPK UML file by selecting javagen-autopk-ejb.zargo from the src/uml directory and pressing Upload. Soon you should be looking at the JavaGen Code Generator page. Check JBoss for the application server and select the database you're using (JBoss ships with Hypersonic SQL database). Don't select the unit test or build file options. Press Generate Source and Download. You may be presented with the software licence agreement page, press Agree. Unzip the contents so the src-gen directory is in the AutoPK directory, were it was before. Type ant clean compile to verify that everything is working again.

Nice work! You now know how to develop and test your own EJBs using JAM. See the tutorials page for other examples.

Answer to teaser question #1: Where's the beef? The only two files in this project that are not trivial or generated from something else are the POM and UML files. Given a POM, JAM can do much of the build work and given a UML model, JavaGen can do much of the development work.

Answer to teaser question #2: Why did you have to type ant ejb.dist instead of ant dist? This is the new Ant 1.6 target override feature that makes it possible for JAM to maintain a standard set of target names (setup, gen, compile, dist, etc.). Have another look at the build.xml file above and notice how the dist target overrides and calls the original dist target defined in the ejb.xml JAM module. When you override a target name, the original target can still be called by prefixing it with the name attribute from the imported Ant file, thus the original dist target becomes ejb.dist above. You can see all the overridden public targets when you type ant -p.