Building Enterprise Applications for GlassFish using Netbeans 6.0 (Beta 2) and Maven2

A few weeks ago an article appeared in the Netbeans Knowledge Base about how to get started with GlassFish V2, Maven2 and Netbeans 6.0. It is a great article doing exactly what the title says: getting you started with Maven2 in Netbeans 6.0 and deploying the project thus created to GlassFish V2. Despite the fact that I couldn’t get a few steps to work correctly, I was able to connect to the Remote Session Bean from my client app and see the log message appear in the GlassFish log.

After having completed the instructions in the article I felt I wanted to do a bit more. Over the past year or so I have been developing a few small Enterprise Applications. These are applications containing an EJB jar file and a war file packed in and deployed through an ear file. The EJB jar contains Entities and Session Beans and the classes in the war file make use of the (Local) Session Beans to allow users of the web application to manage data. This article describes the steps you need to take to create such an application with Netbeans 6.0 (Beta 2) and Maven2.

Installing the software

To follow the steps in this article you’ll need Netbeans 6.0 and a database. Netbeans 6.0 Beta 2 can be downloaded from this link. The “Web & Java EE” download is sufficient for the purposes of this article since it contains the GlassFish V2 application server. If you choose to download another variant, please make sure to install GlassFish V2 and register your GlassFish installation with Netbeans. GlassFish can be downloaded here.
Besides that, you’ll need a database with a JDBC 3 compliant driver. I used Oracle XE but any other database should do. Make sure to create a JDBC Connection Pool and a JDBC Resource to your database so you can use it in the Enterprise Application. For instructions on how to create a Connection Pool and a JDBC Resource for an Oracle database, please refer to this article of mine. The instructions in that article are for GlassFish V1 but the steps in V2 are similar.
After having installed Netbeans, make sure the MevenIDE plugin is downloaded and installed into Netbeans. To do so, start Netbeans and go to Tools -> Plugins. The second tab of the frame that pops up should list Maven under the Java Category. Select it and click the Install button to the lower left. That’s it, you’re all set up now.

Defining the project layout

Our application needs to contain three projects. One project will hold the EJB content, one project the war content and one project will create the ear file. Since these three projects will share some configuration settings for Maven it makes sence to put all of them in a parent pom project. this means that our application will contain this structure

Parent Pom Project 
|
|--- EJB Project
|
|--- WAR Project
\
  --- EAR Project

Let’s have a look at how to create all of these projects.

The Parent POM project

To create the parent pom project, select File -. New Project and select Maven in the list to the left of the frame that pops up. Select Maven Project to the right and click the Next button.

 

Building Enterprise Applications for GlassFish using Netbeans 6.0 (Beta 2) and Maven2 gf mvn nb6 creating a maven project

In the next frame, select the “Maven Quickstart Archetype” archetype and click the Next button.

Building Enterprise Applications for GlassFish using Netbeans 6.0 (Beta 2) and Maven2 gf mvn nb6 selecting a maven archetype

In the third frame specify the Project Name, Project Location, Group Id, Version and Package. For now, the version and package don’t matter much. But it’s nice to have some meaningful name like “MavenEnterpriseApplication” and a meaningful Group Id like “nl.amis.maven.enterprise”.

Building Enterprise Applications for GlassFish using Netbeans 6.0 (Beta 2) and Maven2 gf mvn nb6 specifying the maven properties

Now we’ll have to edit the pom.xml file by hand to make it suit our needs. Some of the properties can be edited by right clicking the project name and selecting properties. These properties can also directly be edited by opening the pom.xml file and modifying the XML. Using the built in editor saves us a lot of typing, so right click the MavenEnterpriseApplication project name and select Properties. Since this is our parent project that we’ll only use for general Maven configuration purposes, we need to change the packaging from jar to pom.

Building Enterprise Applications for GlassFish using Netbeans 6.0 (Beta 2) and Maven2 gf mvn nb6 using the maven properties editor

Next, select the Source category and set the Source/Binary format to 1.5. Click OK to exit the editor and save the changes you made. Most of the other changes we need can be made without actually editing the pom.xml file. First of all, by default Maven creates one source class and one test class in every project that is created. We won’t need those in this project. Go to the Files window right of the Projects window (if it’s not visible select the Windows menu item and then Files) and expand the project. Select the src directory and hit the Delete button. Next return to the Projects window.
By default Maven also generates a JUnit dependency and we won’t need that either. so expand the Test Libraries node, right click the junit-3.8.1.jar library and select Remove Dependency. That’s it for now.

The EJB Project

Next we’ll create the EJB Project. To do so, follow the same three steps as when creating the new Parent POM Project. This time make sure the Project Location is the root directory of the Parent POM Project. This will make Maven recognise it as a sub-module managing the necessary changes to the pom.xml files of both the parent and the sub-module. I chose these settings for the EJB module:

Project Name: MavenEnterpriseApplication-ejb
Project Location: /home/wouter/NetBeansProjects/MavenEnterpriseApplication
Group Id: nl.amis.maven.enterprise
Package: nl.amis.maven.enterprise

The package I specified is the same as the package I specified for the Parent POM Project. Note that the Parent POM Project pom.xml file was modified to now include a reference to the EJB module:

  <modules>
    <module>MavenEnterpriseApplication-ejb</module>
  </modules>

The EJB module pom.xml file was created with a reference to the Parent POM Project:

  <parent>
    <artifactId>MavenEnterpriseApplication</artifactId>
    <groupId>nl.amis.maven.enterprise</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>

Right click the MavenEnterpriseApplication-ejb project and select Properties. This time change the packaging to “ejb”. After clicking OK to save the changes and reopening the Properties editor it is also possible to open the Run Category and select the GlassFish V2 application server. Please do NOT do this! It will generate errors in the Netbeans project. If you do so and encounter problems, please remove the profile.xml file from the MavenEnterpriseApplication-ejb project. Next, remove these lines from the pom.xml file:

  <properties>
        <netbeans.hint.deploy.server>J2EE</netbeans.hint.deploy.server>
  </properties>

Finally, you need to tell Maven to make
use of the version 3.0 EJB Maven plugin. This can be done by adding these lines to the pom.xml file by hand

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ejb-plugin</artifactId>
                <configuration>
                    <ejbVersion>3.0</ejbVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>

Let’s create our Entities and Session Beans now. Since we didn’t connect our EJB project to the GlassFish application server, and doing so causes errors, we will need to use a Netbeans local database connection to generate the beans. Later on, before deploying our project, we will need to make adjustments to the Persistence Unit persistence.xml file so our deployed application makes use of the datasource we defined in Glassfish. But first things first.

Creating the beans

If you haven’t created a database connection in Netbeans yet, this would be a good time to do it. If you don’t Netbeans will prompt you for it later. However, for most databases you need to register your JDBC driver first and you won’t be able to do it when Netbeans prompts you for a database connection. After having created the database connection, right click the MavenEnterpriseApplication-ejb project and select New -> Entity Classes From Database. In the wizard that pops up, select your database connection and then select the tables you want to create Entities for. Since I am using Oracle XE I have created a database connection to the HR schema. Therefore I selected all tables in the HR schema.

Building Enterprise Applications for GlassFish using Netbeans 6.0 (Beta 2) and Maven2 gf mvn nb6 selecting all tables in the hr schema

After clicking next you get the chance to rename the Entity classes to your liking and specify the package in which they will be created. More importantly, here is where you can create a Persistence Unit. Click the “Create Persistence Unit” button and give the Unit a more sensible name, e.g. “MavenEnterpriseApplication-ejbPU”. Finish creating the Persistence Unit and Entities.
Besides the new Entity classes and Persistence Unit, some changes have been made to the pom.xml file as well. Since the Entity classes make use of the Toplink Essentials classes, the dependencies on the toplink jars have been resolved for us. This has been done in two ways. First of all, a reference to the java.net Maven Repository has been added. Second, the depenency entries for toplink-essentials and toplink-essentials-agent have been added to the pom.xml file. Since our web project will need access to the java.net repository as well, it is wise to move the repository reference from the EJB pom.xml to the Parent POM pom.xml file. Besides that, we need to tell Maven not to include the jar files for Toplink Essentials in the EJB jar file. You need to do this by adding this line to each dependency in the pom.xml file

            <scope>provided</scope>

Since the app I am creating for this article only is a simple one, I am only going to modify one Entity class to contain an additional NamedQuery. In the Employees Entity I am adding this NamedQuery which returns a list of all available Employees

@NamedQuery(name = "Employees.getAll", query = "SELECT e FROM Employees e")

Next create a Local Session Bean by right clicking the MavenEnterpriseApplication-ejb project and selecting New -> Session Bean. Provide a name for your session bean, e.g. Data, and a package, e.g. nl.amis.maven.enterprise.ejb.session. Leave the defaults (Stateless and Local) be. Clicking the Finish button will generate an error in Netbeans. The new session bean will have the @Local and @Stateless annotations and Maven is unable to resolve them. In my case the session bean wizard even doesn’t close so I closed it by clicking the Cancel button. Fortunately this doesn’t remove the session bean!
The problem is that the two annotations are provided by the ejb-api.jar file which Maven doesn’t know of. So we need to add a dependency to that jar file by adding these lines to the EJB pom.xml file

        <dependency>
            <groupId>javax.ejb</groupId>
            <artifactId>ejb-api</artifactId>
            <version>3.0</version>
            <scope>provided</scope>
        </dependency>

Next add this mehtod definition to the DataLocal interface:

    public int countEmployees();

and this EntityManager injection and method implementation to the DataBean class

    @PersistenceContext EntityManager em;
    
    public int countEmployees() {
        return em.createNamedQuery("Employees.getAll").getResultList().size();
    }

That completes the EJB project!

The WAR Project

For this article, we will a simple Servlet which uses the DataLocal bean that displays the number of Employees in your browser. First, create a new Project. This time, don’t create a Maven Quickstart Archetype project, but a Maven Webapp Archetype. I used these settings for it

Project Name: MavenEnterpriseApplication-war
Project Location: /home/wouter/NetBeansProjects/MavenEnterpriseApplication
Group Id: nl.amis.maven.enterprise
Package: nl.amis.maven.enterprise

Inspect the project properties and make sure this time the packaging is set to war. In order to get a proper WAR file a few modifications need to be made to the pom.xml file. First of all, these lines need to be added inside the <build> tag

        <plugins>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
              &nbsp
;&n
bsp;    </archive>
                </configuration>
            </plugin>
        </plugins>

 

This will make sure a Class-Path line will be added to the MANIFEST.MF file. Next we need to add dependencies for our EJB project, the ejb-api.jar and the servlet-api.jar by adding these lines to the pom.xml file in the same section as the junit dependency

        <dependency>
            <groupId>nl.amis.maven.enterprise</groupId>
            <artifactId>MavenEnterpriseApplication-ejb</artifactId>
            <version>1.0-SNAPSHOT</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.ejb</groupId>
            <artifactId>ejb-api</artifactId>
            <version>3.0</version>
            <scope>provided</scope>
        </dependency>

The <optional> tag in the MavenEnterpriseApplication-ejb dependency will make sure that the Class-Path line in the MANIFEST.MF file will contain the MavenEnterpriseApplication-ejb.jar file which is needed for the Enterprise Containier of GlassFish to inject the DataLocal instance in the servlet that we are about to create. Before we can do that, however, we first need to resolve some conflicts that we have introduced. Maven is not able to resolve the MavenEnterpriseApplication-ejb dependency since we haven’t built any code yet. Everything will work fine once we build the Parent POM Project, but for now Netbeans cannot resolve the classes in the MavenEnterpriseApplication-ejb project when we use them in the WAR Project. So, right click the MavenEnterpriseApplication project and select build. This may take a while since Maven will probably need to download quite a buch of jar files.

Besides modifying the pom.xml file, the web.xml file that was created also needs to be modified. Maven creates a web.xml file that GlassFish won’t like. The first three lines of the web.xml file (that are the lines up to and including the line with the <web-app> tag) need to be replaced by these lines

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

Once the build process has finished create a new servlet by right clikcing the MavenEnterpriseApplication-war project and selecting New -> Servlet. Give it a name, e.g. DataServlet, and specify a package, e.g. nl.amis.maven.enterprise.web.servlets. Keep all the other default. Now, inject your DataLocal bean and call the countEmployees method like this

    @EJB DataLocal dataLocal;
    
    /** 
    * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("Number of Employees in table is " + dataLocal.countEmployees());
        } finally { 
            out.close();
        }
    }

The EAR Project

the final project we need is the one that will create the ear file using the MavenEnterpriseApplication-ejb and MavenEnterpriseApplication-war projects. First create a new Maven Quickstart Archetype project. I used these settings:

 

Project Name: MavenEnterpriseApplication-ear
Project Location: /home/wouter/NetBeansProjects/MavenEnterpriseApplication
Group Id: nl.amis.maven.enterprise
Package: nl.amis.maven.enterprise

Modify the project properties and set the Packaging to ear. Remove src directory by going to the Files window and deleting the src directory (duh). Remove the junit Test Library from the Projects window. Finally, add the dependencies on the MavenEnterpriseApplication-ejb and MavenEnterpriseApplication-war projects like this

        <dependency>
            <groupId>nl.amis.maven.enterprise</groupId>
            <artifactId>MavenEnterpriseApplication-ejb</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>ejb</type>
        </dependency>
        <dependency>
            <groupId>nl.amis.maven.enterprise</groupId>
            <artifactId>MavenEnterpriseApplication-war</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>war</type>
        </dependency>

Building the Parent POM Project should now be succesfull:

------------------------------------------------------------------------
Reactor Summary:
------------------------------------------------------------------------
MavenEnterpriseApplication ............................ SUCCESS [2.374s]
MavenEnterpriseApplication-ejb ........................ SUCCESS [1.263s]
MavenEnterpriseApplication-war Maven Webapp ........... SUCCESS [1.155s]
MavenEnterpriseApplication-ear ........................ SUCCESS [1.664s]
-----

-------------------------------------------------------------------
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------

Solving deployment issues

Now that the project can succesfully be built, it is time to deploy the ear file to GlassFish V2. For now use the asadmin utility that is shipped with Glassfish V2. I am sure there is a way to deploy to GlassFish via Maven but I haven’t found out how to do this yet. The asadmin utility can be found in the bin directory under the directory in which GlassFish was installed by you. On my Linux system that is glassfish-v2-b58g/bin but you may need to look in C:\glassfish-v2-b58g or perhaps C:\Program Files\glassfish-v2-b58g if you are on Windows. By the way, on Windows the asadmin utility is called asadmin.bat.

To deploy the ear file, open a console and CD to the bin directory holding the asadmin utility. then issue this command

./asadmin deploy --user=admin <path to ear file>

or if you’re on Windows

asadmin.bat deploy --user=admin <path to ear file>

where the “.bat” part in the command is optinal. Here <path to ear file> is the path to the ear file which can be found in the target directory of your ear project. In my case I issued this command

./asadmin deploy --user=admin ./MavenEnterpriseApplication-ear/target/MavenEnterpriseApplication-ear-1.0-SNAPSHOT.ear

the server responds with this error

CLI171 Command deploy failed : Deploying application in domain failed; The persistence-context-
ref-name [nl.amis.maven.enterprise.ejb.session.DataBean/em] in module [] resolves to a 
persistence unit called [MavenEnterpriseApplication-ejbPU] which is of type RESOURCE_LOCAL. 
Only persistence units with transaction type JTA can be used as a container managed entity manager. 
Please verify your application.

Remember what I said about the Persistence Unit and that creating it will make it use a Netbeans local database connection? Well, GlassFish doesn’t buy that. You need to use a JDBC datasource. So it’s time to modify the Persistence Unit persistence.xml file, rebuild our project and try and deploy it again.

All the way at the beginning of this article I asked you to create a JDBC datasource in Glassfish. The one I created is called jdbc/hr and I will mdoify my persistence.xml file to use that. The file can be found in the EJB project under Other Sources -> resources -> META-INF and mine now looks like this

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="MavenEnterpriseApplication-ejbPU" transaction-type="JTA">
    <jta-data-source>jdbc/hr</jta-data-source>
    <properties/>
  </persistence-unit>
</persistence>

Next rebuild the Parent POM Project and issue the asadmin command again. This time GlassFish should answer with

Command deploy executed successfully.

Browsing to the correct URL, in my case http://localhost:8280/MavenEnterpriseApplication-war/DataServlet

should reveal how many Employees are present in our EMPLOYEES table:

Number of Employees in table is 107

Please note that using the Entity wizard again will modify the persisntence.xml file so you need to change this file again afterwards.

Conclusion

The Maven support in Netbeans definately has made a great leap forward with the Netbeans 6.0 version. Despite that, there still are some issues that need to be addressed. Having the possibility to connect a Maven enabled project to the GlassFish application server, or simply being able to use JEE 5 instead of J2EE 1.4, would be great. The discussions at the MevenIDE user mailinglist at codehaus.org show that Milos Kleint and his contributors are working on this. Besides that, full integration of Maven into Netbeans and having the possibility to have any kind of Netbeans project be Maven enabled would be very neat. MevenIDE isn’t there yet, but the future looks promising. I hope this article is “inviting and inciting you to rise” the Maven ladder.

7 Comments

  1. PRADEEP KUMAR REDDY March 1, 2010
  2. Paul Brickell January 19, 2008
  3. Wouter van Reeven November 26, 2007
  4. Ruslan Shavaliev November 26, 2007
  5. Ruslan Shavaliev November 26, 2007
  6. Ruslan Shavaliev November 26, 2007
  7. Ed Burns November 1, 2007