Building an EJB 3.0 application using GlassFish v2, Apache Maven 2 and
NetBeans IDE 6.0
Contributed by Jacek Laskowski
While I was putting together the
environment for reconstructing a potential error in the operation of Apache
OpenEJB, where the remove() method could be incorrectly thought to be
disallowed (GERONIMO-3452
Stateless Session EJBs cannot contain a remove() method), I decided to use
the tools available to try and minimize the time needed for its creation. I
decided to tackle the issue by first running it on the Java EE 5-certified
application server - GlassFish v2, which is the reference implementation of
Java EE 5, and then to act according to whether it ran there properly or not.
Contents
Required Software
In order to create the environment needed to build the EJB 3.0 application
you need to have the following installed:
- "Web & Java EE" or "All" download of NetBeans IDE 6.0 (download).
- Java Standard Development Kit (JDK) version 5.0 or version 6.0 (download)
- GlassFish V2 Application Server (bundled with full IDE download) or
Sun Java System Application Server, Platform Edition 9 (download)
- Apache Maven 2.0.7 (download)
- Maven plugin (available from the Update Center via the Plugins manager) (Maven2 project, NetBeans support for Maven)
Let us assume that the above software is installed and operating correctly.
Software installation boils down to selecting and unzipping a folder in the
selected directory.
In order to install the NetBeans Maven2 project support plugin we need to
startup NetBeans IDE 6.0. Next, select the Tools > Plugins menu and
from the dialogue box which appears choose the Available Plugins tab and
select the plugin.
The complete project is available as ejb3-remove-stateless.zip.
Creating the project structure
2.1 Creating the parent project - ejb3-remove-stateless
We will start by creating the
parent project (main project) from the point of view of organizing the project
run by Apache Maven 2 (hereafter called m2). This will be a pom-type
project which will include two sub-projects - the EJB bean module and the
remote client module.
We can either create the project
by hand - with the help of the mvn command, or using the NetBeans
Maven2 project support plugin. Using the plugin made the process of
creating the environment and working with m2 much easier. Thanks to the plugin
we are able to perform most management functions from the IDE level. Until
now these functions were performed from the command line level.
Assuming that the NetBeans Maven2 project support plugin has been installed
correctly, select the File > New Project menu, and then the Maven
category and the Maven Project.

(click to enlarge screenshot)
Click Next >

(click to enlarge screenshot)
Click Next > again, staying within the selection of the Maven
Quickstart Project archetype.
On the next screen select the following project settings:
- Project Name: ejb3-remove-stateless
- Project Location: C:\
- Group Id: pl.jaceklaskowski.javaee
- Version: 1.0
- Package: pl.jaceklaskowski.javaee

(click to enlarge screenshot)
These settings may differ from those given but the rest of this article
assumes that they are the same as those listed above.
Click Finish to complete the creation of the project.
Finally a jar-type project is
created. We will change the configuration of this project in order for
it to fulfill the role of parent project. Select the new ejb3-remove-stateless
project, right click the mouse and choose the Properties option from the
drop-down menu. Change the Packaging field from jar to pom.

(click to enlarge screenshot)
We will also modify the property of the project since we are using the Java
version.

(click to enlarge screenshot)
Agree to the changes by clicking OK.
We will finish preparing the
project by deleting the src directory which is created by default when
the project is created, but which we will not need. To remove the directory go
to the Files tab, select the src directory and choose Delete
from the drop-down menu.

Remove the test library junit-3.8.1 from the project (we will later
change this to version 4.2)

Creating the sub-project - ejb3-remove-stateless-ejb3
To create the ejb3-remove-stateless-ejb3 sub-project we will again
use NetBeans IDE 6.0. We will follow similar steps to those we took when we
created the ejb3-remove-stateless parent project, just changing the location of
the target sub-project so that it appears in the directory containing the
parent project (this is similar to performing the command mvn create:archetype
in the parent catalogue).
Select the following project settings:
- Project Name:
ejb3-remove-stateless-ejb3
- Project Location:
C:\ejb3-remove-stateless
- Group Id:
pl.jaceklaskowski.javaee
- Version: 1.0
- Package: pl.jaceklaskowski.javaee

(click to enlarge screenshot)
Click Finish to complete the creation of the project.
Successful creation of the project will cause the pom.xml file of the parent
project to be modified due to the registration of module
ejb3-remove-stateless-ejb3.
<modules>
<module>ejb3-remove-stateless-ejb3</module>
</modules>
Just as we did with the parent
project, we will remove the junit-3.8.1 test library. We will
also remove the Test Packages directory for individual tests (select the
Files tab, expand the ejb3-remove-stateless-ejb3 (jar) > src folder
and remove the test directory marked with a red exclamation
mark).

We will configure the project by changing Packaging to ejb.
Right-click the mouse, select the Properties menu and in the dialogue
box change the Packaging field from jar to ejb.

(click to enlarge screenshot)
Agree to the changes by clicking OK.
Remove the pl.jaceklaskowski.javaee.App
category (from the Source Packages section). Finally we will configure
the project to include the EJB 3.0 bean. This change requires the direct
editing of the pom.xml file. We will add the maven-ejb-plugin to
the configuration of this file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>
After modifying the pom.xml file you should see the following:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<artifactId>ejb3-remove-stateless</artifactId>
<groupId>pl.jaceklaskowski.javaee</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>pl.jaceklaskowski.javaee</groupId>
<artifactId>ejb3-remove-stateless-ejb3</artifactId>
<name>ejb3-remove-stateless-ejb3</name>
<packaging>ejb</packaging>
<version>1.0</version>
<url>http://www.JacekLaskowski.pl</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
Creating the sub-project - ejb3-remove-stateless-client
We will create the ejb3-remove-stateless-client project in the same
way as we created the previous sub-project. It is very important that the Project
Location is the ejb3-remove-stateless parent project directory.
Select the following project settings
- Project Name:
ejb3-remove-stateless-client
- Project Location:
C:\ejb3-remove-stateless
- Group Id:
pl.jaceklaskowski.javaee
- Version: 1.0
- Package: pl.jaceklaskowski.javaee

(click to enlarge screenshot)
We will complete the preparation
of the project by removing the junit-3.8.1.jar test library (Test
Libraries), the pl.jaceklaskowski.javee.App category (Source
Packages) as well as pl.jaceklaskowski.javaee.AppTest (Test
Packages).
Complete project structure
The project structure is presented as follows:

Creating the EJB bean - Removable
Declaration of dependence of the EJB 3.0 library
We will begin creating the EJB
bean by defining the project dependency.

We will add the EJB 3.0 library
supplied as org.apache.geronimo.specs:geronimo-ejb_3.0_spec:1.0.

Remote business interface - RemovableRemote
We will create the remote business interface RemovableRemote (category
pl.jaceklaskowski.javaee.RemovableRemote) in the ejb3-remove-stateless-ejb3
project.
package pl.jaceklaskowski.javaee;
import javax.ejb.Remote;
@Remote
public interface RemovableRemote {
public void remove(String message);
}
Bean type - RemovableBean
We will create the bean type RemovableBean (category pl.jaceklaskowski.javaee.RemovableBean)
by realizing the RemovableRemote business interface.
package pl.jaceklaskowski.javaee;
import javax.ejb.Stateless;
@Stateless(mappedName="Removable")
public class RemovableBean implements RemovableRemote {
public void remove(String msg) {
System.out.println(msg);
}
}
Using the @Stateless annotation mappedName attribute allows
you to assign names which you can use to search the EJB bean through the remote
client (more information can be found in How
are Global JNDI names assigned to Session / Entity beans?).
Creating the remote client - RemovableClient
We will create the RemovableClient according to the remote access
guidelines for beans operating within GlassFish - How
do I access a Remote EJB from a stand-alone java client?.
We will begin from the defined dependence on the sub-project - ejb3-remove-stateless-ejb3
(the client uses the sub-project category) through Libraries > Add
Library...

After adding the dependency you may see an error message about the
unavailability of dependencies in the local repository.

(click to enlarge screenshot)
To solve this problem we need to build the EJB bean - Removable, i.e. build
the ejb3-remove-stateless-ejb3 project, and in turn place the library in
the m2 local repository. We will build the project by selecting the ejb3-remove-stateless-ejb3
project, right-clicking the mouse and selecting the Build option
from the drop-down menu.

Correctly performing this command as well as reloading the ejb3-remove-stateless-client
client project (menu Reload Project) will solve the problem.
The next step is to create the client class - pl.jaceklaskowski.javaee.RemovableClient.
This step is so wonderfully simple, it�s trivial. The simplicity of the client
is down to the GlassFish library - appserv-rt.jar, which includes the
JNDI configuration. We should also pay attention to the use of the EJB bean�s
name - Removable - which was defined in the bean category through the
@Stateless annotation mappedName attribute.
package pl.jaceklaskowski.javaee;
import javax.naming.Context;
import javax.naming.InitialContext;
public class RemovableClient {
public static void main(String[] args) throws Exception {
Context ctx = new InitialContext();
RemovableRemote removable = (RemovableRemote) ctx.lookup("Removable");
removable.remove("Look at the server's log");
}
}
We now need to add the project dependencies which are libraries belonging to
the GlassFish server - appserv-rt.jar as well as javaee.jar
within the system (according to System
Dependencies). Look out for dependency on the file system where GlassFish
is installed through the variable glassfish.home (by default: c:/apps/glassfish).
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<artifactId>ejb3-remove-stateless</artifactId>
<groupId>pl.jaceklaskowski.javaee</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>pl.jaceklaskowski.javaee</groupId>
<artifactId>ejb3-remove-stateless-client</artifactId>
<name>ejb3-remove-stateless-client</name>
<version>1.0</version>
<properties>
<glassfish.home>c:/apps/glassfish</glassfish.home>
</properties>
<dependencies>
<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>
<dependency>
<groupId>pl.jaceklaskowski.javaee</groupId>
<artifactId>ejb3-remove-stateless-ejb3</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>none</include>
</includes>
</configuration>
<executions>
<execution>
<id>run RemovableClientTest</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/RemovableClientTest.java</include>
</includes>
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
The interesting fact about the module configuration is the configuration of
the maven-surefire-plugin, which is configured in such a way that by
default it exclusively performs the tests meeting the none pattern
(which in our case means that none of the tests will be performed because the
pattern is not met by any of the tests, but more accurately through our single RemovableClientTest),
and it is only performed during the completion of the integration-test
phase.
Despite the accessibility of the client class we will perform the automatic
startup from level m2 with the help of the single test - RemovableClientTest
(pl.jaceklaskowski.javaee.RemovableClientTest category) which we will
build from the Test Packages folder.
package pl.jaceklaskowski.javaee;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.junit.Test;
public class RemovableClientTest {
@Test
public void runRemoteClient() throws Exception {
Context ctx = new InitialContext();
RemovableRemote removable = (RemovableRemote) ctx.lookup("Removable");
removable.remove("Look at the server's log");
}
}
This type of test will not be started up by default (see: the configuration
of the maven-surefire-plugin in pom.xml) because of the need to start up the
bean on the GlassFish application server before the test can be started (if the
way the tests are carried out is changed then the project cannot be created and
it would not be possible to install the bean on the server).
Startup
The project startup depends on the installation of the Removable bean
on the GlassFish server, and then the startup of the single RemovableClientTest.
GlassFish server startup
Before we move on to the installation of the bean, we will startup GlassFish
with the command asadmin start-domain (I earlier defined the variable
PATH to include the GlassFish bin directory).
$ asadmin.bat start-domain domain1
Starting Domain domain1, please wait.
Log redirected to c:\apps\glassfish\domains\domain1\logs\server.log.
Redirecting output to C:/apps/glassfish/domains/domain1/logs/server.log
Domain domain1 is ready to receive client requests. Additional services are being started in background.
Domain [domain1] is running [Sun Java System Application Server 9.1 (build b58d-fcs)]
with its configuration and logs at: [c:\apps\glassfish\domains].
Admin Console is available at [http://localhost:4848].
Use the same port [4848] for "asadmin" commands.
User web applications are available at these URLs:
[http://localhost:8080 https://localhost:8181 ].
Following web-contexts are available:
[/web1 /__wstx-services ].
Standard JMX Clients (like JConsole) can connect to JMXServiceURL:
[service:jmx:rmi:///jndi/rmi://dev:8686/jmxrmi] for domain management purposes.
Domain listens on at least following ports for connections:
[8080 8181 4848 3700 3820 3920 8686 ].
Domain does not support application server clusters and other standalone instances.
Installing the EJB bean - Removable
The installation of the bean
should come before its creation. However, this step was effectively
completed during the definition of the client dependency (ejb3-remove-stateless-client
project). In the ejb3-remove-stateless-ejb3 project target
directory there is a file called ejb3-remove-stateless-ejb3-1.0.jar.
This is the bean distribution file. This will be installed with the help of the
asadmin deploy command.
$ asadmin.bat deploy --user admin ejb3-remove-stateless-ejb3/target/ejb3-remove-stateless-ejb3-1.0.jar
Command deploy executed successfully.
In the administration console of the server (accessible by default through
the address http://localhost:4848)
we will check that the EJB Removable bean has been installed correctly.

(click to enlarge screenshot)
Remote client startup - RemovableClient
We will begin by building the entire ejb3-remove-stateless project by
selecting the Build option from the menu.

Once the command has been started successfully you will see the following
notification:
...
------------------------------------------------------------------------
Reactor Summary:
------------------------------------------------------------------------
ejb3-remove-stateless ................................. SUCCESS [1.500s]
ejb3-remove-stateless-ejb3 ............................ SUCCESS [0.610s]
ejb3-remove-stateless-client .......................... SUCCESS [0.921s]
------------------------------------------------------------------------
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
...
Of course by choosing the Build option we start the install
step in the m2 nomenclature, which at the same time signifies the completion of
the integration-test stage as well as the completion of our test.
The immediate startup of the client is effectively the performance of the mvn
integration-test command, which in our case uses NetBeans IDE 6.0 as the
graphic tool for starting the m2 command -
this boils down to selecting the ejb3-remove-stateless-client project,
right-clicking the mouse and selecting the Custom > Goals... option
from the menu .
A list of m2 stages can be found on the Build
Lifecycle Phases page.

Next we will perform the integration-test stage.

Once the test has been started successfully you will see the following
notification in the NetBeans IDE:
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running pl.jaceklaskowski.javaee.RemovableClientTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.203 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
...
as well as in the GlassFish diary of events (domains/domain1/logs/server.log
file in the GlassFisha home directory)
[#|2007-09-03T22:41:59.750+0200|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=16;_ThreadName=p:
thread-pool-1; w: 8;|
Look at the server's log|#]
Despite the successful startup of the remote client this is not the final
step of the solution. This requires the startup of a test to install the bean.
If we try to perform the Build option before its installation we will
receive an error message. Suggestions for improvements are welcomed. The next
part of the article accompanies the Apache OpenEJB 3.0-SNAPSHOT server.
Related Links