Update 2009/07/15: address the Glassfish v3 Preview instead of the older Prelude release.
EJB 3.1 brings the deployment of EJBs as part of a WAR, ultimately removing any entry barriers to using EJBs with a container that supports EJB 3.1. This article will show how to deploy [fleXive] as part of a WAR application, using [fleXive]’s WAR archetype for Maven and Glassfish v3 Preview.
Create the WAR project
To get started, create a new Maven project using our WAR archetype:
mvn archetype:generate -DarchetypeGroupId=com.flexive -DarchetypeArtifactId=flexive-archetype-war -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://repo.flexive.org/maven2/ -DgroupId=my.group.test -DartifactId=webapp-test -Dversion=1.0-SNAPSHOT
This creates a basic WAR application with the following directory structure:
webapp-test
|-- pom.xml
`-- src
`-- main
|-- java
| `-- my
| `-- group
| `-- test
| |-- EJBExampleBean.java
| `-- ExampleBean.java
`-- webapp
|-- WEB-INF
| |-- faces-config.xml
| `-- web.xml
`-- index.xhtml
EJBExampleBean shows a prime feature of EJB 3.1: instead of having to declare an EJB interface and packaging the EJB class in a separate EJB JAR file, we just add our EJB to the web application and annotate it with @javax.ejb.Stateless
(of course, you can still use explicit local and remote interfaces). This turns it into a fully-fledged EJB that can be injected into other managed beans using the @EJB annotation.
@Stateless(name = "EJBExample")
public class EJBExampleBean {
public Map<FxType, Integer> getInstanceCounts() throws FxApplicationException {
final Map<FxType, Integer> result = new HashMap<FxType, Integer>();
final FxEnvironment environment = CacheAdmin.getEnvironment();
// Invoke fleXive query through EJB and collect the results
for (FxFoundType foundType : new SqlQueryBuilder().select("@pk").getResult().getContentTypes()) {
result.put(environment.getType(foundType.getContentTypeId()), foundType.getFoundEntries());
}
return result;
}
}
/**
* Request-scoped JSF bean accessing the EJB.
*/
public class ExampleBean {
@EJB EJBExampleBean exampleEJB;
private Map<FxType, Integer> instanceCounts;
public Map<FxType, Integer> getInstanceCounts() throws FxApplicationException {
if (instanceCounts == null) {
instanceCounts = exampleEJB.getInstanceCounts();
}
return instanceCounts;
}
}
In our pom.xml
we add the [fleXive] EJB and JSF artifacts, as well as Glassfish itself to provide the EJB 3.1 APIs during compilation. It seems that Glassfish v3 Preview does not bring Sun’s EL-1.0 implementation (which we need for Facelets), so we have to add this too.
<properties>
<flexive.version>3.1-SNAPSHOT</flexive.version>
</properties>
<dependencies>
<dependency>
<groupId>com.flexive</groupId>
<artifactId>flexive-ejb</artifactId>
<type>ejb</type>
<version>${flexive.version}</version>
</dependency>
<dependency>
<groupId>com.flexive</groupId>
<artifactId>flexive-plugin-jsf-core</artifactId>
<version>${flexive.version}</version>
</dependency>
<dependency>
<groupId>com.sun.el</groupId>
<artifactId>el-ri</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.javaee</artifactId>
<version>3.0-Prelude-b28b</version>
<scope>provided</scope>
</dependency>
</dependencies>
The pom.xml
also expands the [fleXive] EJBs into the WEB-INF/classes folder of the web application, because Glassfish v3 Prelude Preview does not yet support EJB-JAR deployments:
<!--
Unpack the flexive-ejb artifact and add it to WEB-INF/classes
(Glassfish v3 Prelude does not support EJB-JAR deployment yet)
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<!-- Copy the EJBs to target/flexive -->
<execution>
<id>copy-ejb</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.flexive</groupId>
<artifactId>flexive-ejb</artifactId>
<version>${flexive.version}</version>
<overWrite>true</overWrite>
<outputDirectory>target/flexive/WEB-INF/classes</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<webResources>
<resource>
<directory>target/flexive</directory>
</resource>
</webResources>
</configuration>
</plugin>
Invoke mvn package
to compile and package the application into target/webapp-test.war
.
Glassfish v3 Prelude Preview setup
Download and install Glassfish v3 Preview.
Before deploying a [fleXive] application, you need to perform additional setup steps described in the reference documentation:
- Download the [fleXive] distribution
- Install the required libraries to [glassfish-home]/glassfish/domains/domain1/lib/ext
- Add the datasources
- Initialize the database schema as described here
Deploying the WAR application to Glassfish
Finally, start Glassfish with bin/asadmin start-domain
and deploy the WAR file from your project directory with [glassfish-home]/bin/asadmin deploy --force=true target/webapp-test.war
. Deployment should only take a few seconds, and the application should be running and display the output from calling our EJB at http://localhost:8080/webapp-test/.
A note on JSF2
[fleXive] is a JSF 1.2 application. As such, it should work without changes in a JSF2 container. However, we ran into some issues, mostly due to RichFaces’ Ajax4JSF implementation. In the backend application, you need to force client-side state saving (through a config parameter in the web.xml), and some administration pages don’t work yet. The JSF components themselves appear to be working without problems, however they are still based on JSF 1.2 and Facelets – thus they cannot be used in a true JSF2 application.