7. Version 3: Porting the PAM application to a GlassFish application server
We propose to place the EJBs from the [business] and [DAO] layers of the OpenEJB/EclipseLink architecture into the container of a GlassFish application server.
The current implementation with OpenEJB / EclipseLink
![]() |
Above, the [ui] layer uses the remote interface of the [business] layer.
We tested two execution contexts: local and remote. In the latter mode, the [ui] layer acted as a client of the [business] layer, which is implemented by EJBs. To operate in client/server mode, where the client and server run in two separate JVMs, we will deploy the [business, DAO, JPA] layers on the GlassFish Java EE server. This server is included with NetBeans.
The implementation to be built with the Glassfish server
![]() |
- the [ui] layer will run in a Java SE (Standard Edition) environment
- The [business logic, DAO, JPA] layers will run in a Java EE (Enterprise Edition) environment on a GlassFish v3 server
- The client will communicate with the server via a TCP/IP network. Network communication is transparent to the developer, though they must still be aware that the client and server exchange serialized objects to communicate, not object references. The network protocol used for this communication is called RMI (Remote Method Invocation), a protocol usable only between two Java applications.
- The JPA implementation used on the GlassFish server will be EclipseLink.
7.1. The server- e part of the PAM client/server application
7.1.1. The application architecture
Here we are examining the server-side component that will be hosted by the Glassfish server’s EJB3 container:
![]() |
The goal is to port to the Glassfish server what has already been developed and tested with the OpenEJB container. This is the advantage of OpenEJB and, more generally, of embedded EJB containers: they allow us to test the application in a simplified runtime environment. Once the application has been tested, all that remains is to port it to a target server, in this case the GlassFish server.
7.1.1.1. The NetBeans Project
Let’s start by creating a new NetBeans project:
![]() |
- in [1], new project
- in [2], select the Maven category, and in [3], select the EJB Module type. The goal is to build a project that will be hosted and run by an EJB container, specifically the GlassFish server.
![]() |
- Using the [4a] button, select the parent folder for the project folder or type its name directly in [4b].
- In [5], give the project a name
- In [6], select the application server on which it will run. The one selected here is one of those visible in the [Runtime / Servers] tab, in this case GlassFish v3.
- In [7], select the Java EE version.
![]() |
- In [1], the new project. It differs from a standard Java project in a few ways:
- an [Other Sources] branch [2] is automatically created. It will contain, in particular, the [persistence.xml] file that configures the JPA layer,
- If you build the project (Build), a [javaee-api-6.0] dependency appears [3]. It is of the "provided" type because it is supplied at runtime by the Glassfish EJB container.
7.1.1.2. Configuring the persistence layer
By "persistence layer configuration," we mean writing the [persistence.xml] file, which defines:
- the JPA implementation to use
- the definition of the data source used by the JPA layer. This will be a JDBC source managed by the GlassFish server.
![]() |
We can proceed as follows. First, in the [Runtime / Databases] tab, we will create [1] a connection to the MySQL5 / dbpam_eclipselink database:
![]() |
Once this is done, we can move on to creating the JDBC resource used by the EJB module:
![]() |
- In [1], create a new file—make sure the EJB project is selected before performing this operation
- In [2], select the EJB project
- In [3], select the [Glassfish] category
- in [4], select "Create a JDBC resource"
![]() |
- in [5], specify that the JDBC resource will use a new connection pool. Note that a connection pool is a pool of open connections used to speed up the application’s interactions with the database.
- in [6], give a JNDI name to the created JDBC resource. This name can be anything, but it often takes the form jdbc/name. This JNDI name will be used in the [persistence.xml] file to designate the data source that the JPA implementation must use.
- In [7], give any name to the connection pool that will be created
- In the drop-down list [8], select the JDBC connection previously created for the MySQL database / dbpam_eclipselink.
- In [9], a summary of the connection pool properties—leave everything as is
![]() |
- In [10], you can specify several properties of the connection pool—leave the default values
- In [11], after completing the wizard for creating a JDBC resource for the EJB module, a [glassfish-resources.xml] file was created in the [Other Sources] branch. The contents of this file are as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-resource enabled="true" jndi-name="jdbc/dbpam_eclipselink" object-type="user" pool-name="dbpamEclipselinkConnectionPool">
<description/>
</jdbc-resource>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="dbpamEclipselinkConnectionPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="URL" value="jdbc:mysql://localhost:3306/dbpam_eclipselink"/>
<property name="User" value="root"/>
<property name="Password" value=""/>
</jdbc-connection-pool>
</resources>
The [glassfish-resources.xml] file is an XML file that contains all the data collected by the wizard. It will be used by NetBeans to request the creation of the JDBC resource required by this module when deploying the EJB module to the GlassFish server.
You can now create the [persistence.xml] file, which will configure the JPA layer of the EJB module:
![]() |
- In [1], create a new file—make sure the EJB project is selected before performing this operation
- in [2], select the EJB project
- in [3], select the [Persistence] category
- in [4], create a persistence unit
![]() |
- in [5], give the persistence unit a name
- In [6], several JPA implementations are offered. Here, select [EclipseLink]. Other implementations can be used provided you include the libraries that implement them along with those of the GlassFish server.
- In the drop-down list [7], select the JDBC data source [jdbc/dbpam_eclipselink] that was just created.
- In [8], specify that transactions are managed by the EJB container
- In [9], specify that no operations should be performed on the data source when deploying the EJB module to the server. This is because the EJB module will use a [dbpam_eclipselink] database that has already been created.
- At the end of the wizard, a [persistence.xml] file has been created [10]. Its content is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="mv-pam-ejb-metier-dao-eclipselinkPU" transaction-type="JTA">
<jta-data-source>jdbc/dbpam_eclipselink</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
- line 3: the name of the persistence unit [mv-pam-ejb-metier-dao-eclipselinkPU] and the transaction type (JTA for an EJB container)
- line 5: the JNDI name of the data source used by the persistence layer: jdbc/dbpam_eclipselink
- line 6: JPA entities are not specified. They will be searched for in the EJB module’s classpath.
- The name of the JPA implementation (Hibernate, EclipseLink, etc.) used is not specified. In this case, GlassFish v3 uses EclipseLink by default.
7.1.1.3. Inserting the [JPA, DAO, Business] layers
Now that the [persistence.xml] file has been defined, we can proceed to insert the [business, DAO, JPA] layers of the [pam] enterprise application into the project:
![]() |
These three layers are identical to what they were with OpenEJB. We can simply copy and paste between the two projects. That is what we are doing now:
![]() |
- in [1], the result of copying the [jpa, dao, business, exception] packages from the [mv-pam-openejb-eclipselink] project into the EJB module [mv-pam-ejb-business-dao-jpa-eclipselink]
7.1.1.4. Configuring the GlassFish server
We still need to configure the GlassFish server in two areas:
- The JPA layer is implemented by EclipseLink. We need to ensure that the Glassfish server has the libraries for this JPA implementation.
- The data source is a MySQL database. We need to ensure that the GlassFish server has the JDBC driver for this database management system.
You may discover that these libraries are missing when deploying the EJB module. Here is one of several ways to add missing libraries to the GlassFish server:
![]() |
- In [1], view the GlassFish server properties
- In [2], note the server’s domains folder. We’ll refer to it as <domains>
- In the <domains>\domain1\lib folder, place the missing libraries. In the example, the Hibernate libraries (lib/hibernate-tools) and the MySQL JDBC driver (lib/misc) were added. By default, the GlassFish server includes the EclipseLink libraries. We will therefore only add the MySQL JDBC driver.
![]() |
- In [1], on the [Services] tab, we start the GlassFish v3 server
- In [2], it is active
7.1.1.5. Deploying the EJB module
We will now deploy the EJB module on the GlassFish server:
![]() |
- In [1], the EJB module is deployed
- In [2], the GlassFish server tree is refreshed
- in [3], after deployment, the EJB module appears in the [Applications] branch of the GlassFish server
- in [4], the JDBC resource [jdbc / dbpam_eclipselink] has been created on the GlassFish server. Recall that we defined it in Section 7.1.1.2.
During deployment, the GlassFish server logs the following information to the console:
Note that lines
- 3, 6, 8, and 11: the portable JNDI names of the deployed EJBs. Java EE 6 introduced the concept of portable JNDI names. This denotes a JNDI name recognized by all Java EE 6 servers. With Java EE 5, JNDI names are specific to the server being used.
- 4, 7, 9, 12: the JNDI names of the deployed EJBs in a format specific to GlassFish v3.
These names will be useful for the console application we are going to write to use the deployed EJB module.
7.2. Console Client - Version 1
Now that we have deployed the server side of our client/server application, we will examine the client side [1]:
![]() |
7.2.1. The client project
We create a new Maven project of type [Java Application] named [mv-pam-client-ejb-metier-dao-eclipselink]:
![]() |
- in [1], the client project
In the [pom.xml] file, we add the following dependencies:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st</groupId>
<artifactId>mv-pam-client-ejb-metier-dao-eclipselink</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-pam-client-ejb-business-dao-eclipselink</name>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
<id>eclipselink</id>
<layout>default</layout>
<name>Repository for library Library[eclipselink]</name>
</repository>
<repository>
<url>http://repo1.maven.org/maven2/</url>
<id>swing-layout</id>
<layout>default</layout>
<name>Repository for library Library[swing-layout]</name>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.appclient</groupId>
<artifactId>gf-client</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mv-pam-ejb-metier-dao-eclipselink</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swing-layout</artifactId>
<version>1.0.3</version>
</dependency>
</dependencies>
</project>
- lines 31–35: the dependency on the [gf-client] library, which allows a Classfish client to communicate with a remote server,
- lines 36–41: the dependency on the EJB module’s Maven project. Here, we want to retrieve the definitions of the JPA entities and the various interfaces, as well as that of the exception class [PamException],
From the [mv-pam-openejb-eclipselink] project, we copy the [MainRemote] class:
![]() |
The [MainRemote] class must obtain a reference to the EJB in the [business] layer. The code for the [MainRemote] class changes as follows:
// OK—we can now retrieve the pay stub
PayStub payStub = null;
IMetierRemote business = null;
try {
// GlassFish server JNDI context
InitialContext initialContext = new InitialContext();
// Instantiate the business layer
business = (IMetierRemote) initialContext.lookup("java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!business.IMetierRemote");
// calculate the pay stub
payroll = business.calculatePayroll(args[0], hoursWorked, daysWorked);
} catch (PamException ex) {
System.err.println("The following error occurred: "
+ ex.getMessage());
return;
} catch (Exception ex) {
System.err.println("The following error occurred: "
+ ex.toString());
return;
}
- Line 6: Initialization of the GlassFish server's JNDI context.
- line 8: this JNDI context is queried for a reference to the remote interface of the [business] layer. According to the GlassFish logs, we know that the remote interface of the [business] layer has two possible names:
Line 1: the JNDI name that can be used with any Java EE 6 application server. Line 2: the GlassFish-specific JNDI name. In the code, on line 9, we use the portable JNDI name.
- The rest of the code remains unchanged
![]() |
In [1], we configure the project to run the [MainRemote] class with arguments. If all goes well, running the project yields the following result:
If an incorrect social security number is entered in the properties, the following result is obtained:
7.3. Client console - version 2
In previous versions, the Glassfish server's JNDI environment was configured using a [jndi.properties] file located somewhere in the project archives. Its default content is as follows:
# JNDI access to Sun Application Server
java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.factory.url.pkgs=com.sun.enterprise.naming
# Required to add a javax.naming.spi.StateFactory for CosNaming that
# supports dynamic RMI-IIOP.
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
org.omg.CORBA.ORBInitialHost=localhost
org.omg.CORBA.ORBInitialPort=3700
Lines 7 and 8 specify the JNDI service machine and its listening port. This file does not allow you to query a JNDI server other than localhost or one running on a port other than port 3700. If you want to change these two settings, you can create your own [jndi.properties] file or use a Spring configuration. We will demonstrate the latter technique.
We start by creating a new project based on the initial [pam-client-metier-dao-jpa-eclipselink] project.
![]() |
- In [1], the new project
- in [2], the Spring configuration file [spring-config-client.xml]. Its contents are as follows:
The Spring configuration file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<!-- business -->
<jee:jndi-lookup id="metier" jndi-name="java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote">
<jee:environment>
java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.factory.url.pkgs=com.sun.enterprise.naming
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
org.omg.CORBA.ORBInitialHost=localhost
org.omg.CORBA.ORBInitialPort=3700
</jee:environment>
</jee:jndi-lookup>
</beans>
Here we are using a <jee> tag (line 14) introduced in Spring 2.0. Using this tag requires defining the schema to which it belongs, lines 4, 10, and 11.
- Line 14: The <jee:jndi-lookup> tag is used to obtain an object reference from a JNDI service. Here, we associate the bean named "metier" with the JNDI resource associated with the [Metier] EJB. The JNDI name used here is the portable name (Java EE 6) of the EJB.
- The contents of the [jndi.properties] file become the contents of the <jee:environment> tag (line 15), which is used to define the connection parameters for the JNDI service.
The main class [MainRemote] changes as follows:
Lines 7–8: Spring is asked for the [IMetierRemote] type reference in the [business] layer. This solution brings flexibility to our architecture. In fact, if the EJB in the [business] layer became local—i.e., executed in the same JVM as our [MainRemote] client—the client’s code would remain unchanged. Only the contents of the [spring-config-client.xml] file would change. We would then have a configuration similar to the Spring/JPA architecture discussed in Section 5.11.
Readers are invited to test this new version.
7.4. The Swing Client
We will now build the Swing client for our EJB client/server application.
![]() |
The [pom.xml] file must include the necessary dependency for Swing applications:
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swing-layout</artifactId>
<version>1.0.3</version>
</dependency>
Above, the [PamJFrame] class was originally written to run in a Spring/JPA environment:
![]() |
Now this class must become the remote client of an EJB deployed on the Glassfish server.
![]() |
Practical exercise: Following the example of the [ui.console.MainRemote] console client in the project, modify the way the [doMyInit] method (see Section 5.12.4) in the [PamJFrame] class is used to acquire a reference to the [business] layer, which is now remote.

























