SeamFramework.orgCommunity Documentation
OC4J (Oracle Containers for Java) 11g (currently a "Technology
Preview" release) is Oracle's JEE5 application server. Seam application
can be deployed to OC4J, but require some additional configuration
changes, and dependencies. This chapter will show you exactly what must be
done. We will start by looking at the building and deploying the JEE5 Hotel
Booking example application which comes with Seam. Then we will deploy a
project generated by seam-gen
. First a basic
seam-gen
application with RichFaces ajax
components, and facelets. Then expand that application to include Seam
security with Drools, JPA provided with hibernate, and automatic CRUD
reverse engineering of a MySQL database.
First we need to install the target container - OC4j. This chapter
requires you to use OC4J 11g Technology Preview (not OC4J 10g). You can
download OC4J 11g from
http://www.oracle.com/technology/tech/java/oc4j/11/
Below are instructions to install. launch, access, and shutdown the 11g
release. For further information on installing OC4J, consult the
readme.txt
distributed with OC4J, or the OC4J
installation guide and release notes.
Download and unzip OC4J
Make sure you have $JAVA_HOME
and
$ORACLE_HOME
set as environment
variables ( $ORACLE_HOME
is the
directory to which you unzip OC4J). For further information
on installing OC4J, consult the
readme.txt
distributed with OC4J
Applications (ear/war) are deployed to the
$ORACLE_HOME/j2ee/home/applications
directory.
Note that OC4J does not support hot deployment by default. This means every time you deploy the application you must restart the server.
Start OC4J: $ORACLE_HOME/j2ee/home/java
-jar -XX:MaxPermSize=256M oc4j.jar
You must override the default PermGen memory settings using above command. See OC4J release notes for details.
You will be asked to set the admin password if this is the first time you have started OC4J
Once deployed you can check out your applications at
http://localhost:8888/<your-app-path>
You can stop the server by pressing
CTRL-C
in the console on which the
server is running.
The jee5/booking
example is based on the Hotel
Booking example (which runs on JBoss AS). Out of the box it is designed to
run on Glassfish, but it's easy to build it for OC4J. It is located in the
$SEAM_DIST/examples/jee5/booking
directory.
First, lets look at the basic dependencies of the booking example. Armed with this knowledge we can look at the extra dependencies requirements that OC4J adds.
We will show you how to get these dependencies into the
application in Section 36.2.3, “ Building the jee5/booking
example
” below.
jboss-seam.jar
— We
declare this as an EJB3 module (why? well Seam needs to be
able to interact with container managed transactions;
this is implemented as an EJB3 Stateful Session Bean)
jboss-el.jar
jboss-seam-ui.jar
—
Seam's JSF controls depend on Apache's
commons-beanutilsjboss-seam-debug.jar
jsf-facelets.jar
richfaces-api.jar
,
richfaces-impl.jar
and
richfaces-ui.jar
— which
requires Apache commons-digester and
commons-beanutils Hibernate — of course, we decided to use Hibernate as the JPA provider (rather than TopLink Essentials which ships with OC4J).
To use Hibernate as your JPA provider you need the following jars:
hibernate.jar
hibernate-annotations.jar
hibernate-entitymanager.jar
hibernate-validator.jar
jboss-common-core.jar
commons-logging.jar
commons-collections.jar
Third party jars — various jars needed for seam and this example to run.
javaasist.jar
dom4j.jar
cglib.jar
asm.jar
commons-beanutils.jar
commons-digester.jar
concurrent.jar
log4j.jar
— This can be left out if you are not going
to configure log4j. If it is packaged but not
configured logging will be hidden in oc4j.
Extra OC4J jars — Running Seam on most application servers (such as JBoss AS or Glassfish) you only need to include the dependencies for those bits of Seam you actually use (e.g. if you use Seam Text you need to include ANTLR); but, on OC4J, due to its "interesting" classloading you must always include them:
hibernate-search.jar
hibernate-common-annotations.jar
— needed for hibernate search
lucene-core.jar
— needed for hibernate search
antlr.jar
— needed for Seam Text jbpm-jpdl.jar
— needed for Seam's JBPM quartz.jar
dbunit.jar
— needed for some testing classes
jboss-embedded-api.jar
— needed for some testing classes
Drools — needed for Seam Security. We aren't using Seam security with Drools, but have to include it. Drools consists of 6 jars:
drools-core.jar
drools-compiler.jar
janino.jar
mvel141.jar
core.jar
antlr-runtime.jar
Drools integration is not used in the example.
There are just a few changes to be made:
web.xml
You need to declare all your ejb's in the
web.xml
. This is a silly
requirement of a number of JEE5 application servers - for
example OC4J and Glassfish.
This is already done in the example's web.xml file, below is an example.
<ejb-local-ref>
<ejb-ref-name>
jboss-seam-jee5/AuthenticatorAction/local
</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>
org.jboss.seam.example.booking.Authenticator
</local>
<ejb-link>AuthenticatorAction</ejb-link>
</ejb-local-ref>
persistence.xml
You need to provide the correct configuration for your JPA implementation. We are using Hibernate and due to OC4J bundling an old ANTLR, we need to use an alternative query factory, we also want to use the OC4J transaction manager:
For our example modify the
resources/META-INF/persistence.xml
file. Comment out the Glassfish properties and
un-comment the OC4J properties.
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.query.factory_class"
value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.OrionTransactionManagerLookup"/>
Modify the build.xml
file in the
example:
Un-comment the labeled OC4J-related library properties. This will include all the extra dependencies discussed above.
It should look like the following:
<!-- add libs for oc4j (eager classloading) -->
<property name="jbpm.lib" value="true"/>
<property name="drools.lib" value="true"/>
<property name="quartz.lib" value="true" />
<property name="search.lib" value="true" />
<property name="dbunit.lib" value="true" />
<property name="jboss-embedded-api.lib" value="true" />
Build the demo app by running ant
in
the examples/jee5/booking
directory. The build target is
dist/jboss-seam-jee5.ear
Copy dist/jboss-seam-jee5.ear
following the instructions below.
This mini-tutorial describes the (fairly tedious) steps required
to deploy a JEE 5 application to OC4J. It assumes you have already
downloaded and installed it following the instructions in Section 36.1, “Installation and operation of OC4J”. It also assumes you are
deploying the jee5/booking
example, using the
embedded hsqldb database. To deploy another application you would need
to alter the datasource and application name.
Copy hsqldb.jar
to OC4J shared library
directory: cp $SEAM_HOME/lib/hsqldb.jar
$ORACLE_HOME/j2ee/home/applib/
(OC4J doesn't
come with an embedded database so we decided to use HSQLDB)
Edit the OC4J datasource file
$ORACLE_HOME/j2ee/home/config/data-sources.xml
and, inside <data-sources>
, add
<managed-data-source
connection-pool-name="jee5-connection-pool"
jndi-name="jdbc/__default"
name="jee5-managed-data-source" />
<connection-pool name="jee5-connection-pool">
<connection-factory
factory-class="org.hsqldb.jdbcDriver"
user="sa"
password=""
url="jdbc:hsqldb:." />
</connection-pool>
The jndi-name
is used as the
jta-data-source
in
persistence.xml
.
Edit
$ORACLE_HOME/j2ee/home/config/server.xml
and, inside <application-server>
, add
<application name="jboss-seam-jee5"
path="../../home/applications/jboss-seam-jee5.ear"
parent="default"
start="true" />
To keep things simple use the same names as you used for project.
Edit
$ORACLE_HOME/j2ee/home/config/default-web-site.xml
, and, inside
<web-site>
, add
<web-app application="jboss-seam-jee5"
name="jboss-seam-jee5"
load-on-startup="true"
root="/seam-jee5" />
The root
is the context path you will put
into your web browser to access the application.
Copy the application to OC4J: cp
dist/jboss-seam-jee5.ear
$ORACLE_HOME/j2ee/home/applications/
Start/stop OC4J following instructions in Section 36.1, “Installation and operation of OC4J” above.
Checkout the app at:
http://localhost:8888/seam-jee5
seam-gen
is a great tool for developers that
can quickly get you up and running with a full Seam application. However
the project that it created is configured to run on JBoss AS. This means
there are some extra steps needed to have it execute on OC4j. The
following explanation assumes you are using the command line and a
simple text editor, but of course you can use your favorite IDE.
seam-gen
projects come with support for Eclipse
and Netbeans.
We will start by creating and deploying a pretty simple application
using seam-gen
. Then we'll show you how easy it is
to use seam-gen
and Hibernate Tools to reverse
engineer a database schema into a functional CRUD application.
seam-gen
will create JPA entity beans, Seam
Application Framework components and JSF views for you. We will also add
Seam security using Drools.
This tutorial uses MySQL (but of course you could use any database,
altering the SQL and datasources as appropriate); install, configure
and run MySQL, then create a database with some sample data. Don't forget
to also download the
mysql-connector-java-X.jar
for jdbc support.
When setting up Seam security this tutorial will assume there is a table
named User
with columns
username
and password
with
at least one entry. Beyond that you can set up any type of sample data and
tables you would like.
First we need to tell the seam-gen
what we
want, run ./seam setup
in the seam
distribution directory. Follow the settings example below based on
your system and setup (ex. use your database name instead of
oc4jexample
).
> ./seam setup Buildfile: build.xml init: setup: [echo] Welcome to seam-gen :-) [input] Enter your Java project workspace (the directory that contains your Seam projects) [C:/Projects] [C:/Projects] /home/jbalunas/workspace [input] Enter your JBoss home directory [C:/Program Files/jboss-4.2.3.GA] [C:/Program Files/jboss-4.2.3.GA] /home/jbalunas/jboss/jboss-4.2.3.GA [input] Enter the project name [myproject] [myproject] oc4j_example [echo] Accepted project name as: oc4j_example [input] Select a RichFaces skin (not applicable if using ICEFaces) [blueSky] ([blueSky], classic, ruby, wine, deepMarine, emeraldTown, sakura, DEFAULT) [input] Is this project deployed as an EAR (with EJB components) or a WAR (with no EJB support) [ear] ([ear], war, ) [input] Enter the Java package name for your session beans [com.mydomain. oc4j_example] [com.mydomain.oc4j_example] org.jboss.seam.tutorial.oc4j.action [input] Enter the Java package name for your entity beans [org.jboss.seam. tutorial.oc4j.action] [org.jboss.seam.tutorial.oc4j.action] org.jboss.seam.tutorial.oc4j.model [input] Enter the Java package name for your test cases [org.jboss.seam. tutorial.oc4j.action.test] [org.jboss.seam.tutorial.oc4j.action.test] org.jboss.seam.tutorial.oc4j.test [input] What kind of database are you using? [hsql] ([hsql], mysql, oracle, postgres, mssql, db2, sybase, enterprisedb, h2) mysql [input] Enter the Hibernate dialect for your database [org.hibernate. dialect.MySQLDialect] [org.hibernate.dialect.MySQLDialect] [input] Enter the filesystem path to the JDBC driver jar [/tmp/seam/lib/hsqldb.jar] [/tmp/seam/lib/hsqldb.jar] lib/mysql-connector.jar [input] Enter JDBC driver class for your database [com.mysql.jdbc.Driver] [com.mysql.jdbc.Driver] [input] Enter the JDBC URL for your database [jdbc:mysql:///test] [jdbc:mysql:///test] jdbc:mysql:///oc4jexample [input] Enter database username [sa] [sa] username [input] Enter database password [] [] password [input] skipping input as property hibernate.default_schema.new has already been set. [input] Enter the database catalog name (it is OK to leave this blank) [] [] [input] Are you working with tables that already exist in the database? [n] (y, [n], ) y [input] Do you want to drop and recreate the database tables and data in import.sql each time you deploy? [n] (y, [n], ) n [input] Enter your ICEfaces home directory (leave blank to omit ICEfaces) [] [] [propertyfile] Creating new property file: /home/jbalunas/workspace/jboss-seam/seam-gen/build.properties [echo] Installing JDBC driver jar to JBoss server [copy] Copying 1 file to /home/jbalunas/jboss/jboss-4.2.3.GA/server/default/lib [echo] Type 'seam create-project' to create the new project BUILD SUCCESSFUL
Type ./seam new-project
to create your
project and cd
/home/jbalunas/workspace/oc4j_example
to the newly
created project.
We now need to make some changes to the generated project.
Let's start with the configuration files:
build.xml
Change the default target to archive (we aren't going to cover automatic deployment to OC4J).
<project name="oc4j_example" default="archive" basedir=".">
OC4J looks for the drools file
/security.drl
file in
the root of the war
file
instead of the root of the
ear
file so we need to have
the build.xml
move it to
the correct location at build time. The
following must be added at the top of the
<target name="war"
depends="compile" description="Build the
distribution .war file">
target.
<copy todir="${war.dir}">
<fileset dir="${basedir}/resources" >
<include name="*.drl" />
</fileset>
</copy>
resources/META-INF/persistence-dev.xml
Alter the
jta-data-source
to be
jdbc/__oc4jexample
(and use this as the
jndi-name
when creating
the data source in
data-sources.xml
later
during deployment).
Add the properties (described in
jee5/booking
example):
<property name="hibernate.query.factory_class"
value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory" />
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.OrionTransactionManagerLookup" />
<property name="hibernate.transaction.flush_before_completion"
value="true"/>
<property name="hibernate.cache.provider_class"
value="org.hibernate.cache.HashtableCacheProvider"/>
Remove the JBoss AS specific method of exposing the EntityManagerFactory:
<property
name="jboss.entity.manager.factory.jndi.name"
value="java:/oc4j_exampleEntityManagerFactory">
You'll need to alter
persistence-prod.xml
as well if you want to deploy to OC4J using the
prod profile.
resources/META-INF/jboss-app.xml
You can delete this file as we aren't deploying to
JBoss AS ( jboss-app.xml
is used
to enable classloading isolation in JBoss AS)
resources/*-ds.xml
You can delete these file as we aren't deploying to
JBoss AS (these files define datasources in JBoss AS,
in OC4J you have to edit the master
data-sources.xml
file)
resources/WEB-INF/components.xml
Enable container managed transaction
integration - add the
<transaction:ejb-transaction />
component, and it's namespace
declaration
xmlns:transaction="http://jboss.com/products/seam/transaction"
Alter the
jndi-pattern
to
java:comp/env/oc4j_example/#{ejbName}/local
We want to use a Seam Managed Persistence Context in our application. Unfortunately OC4J doesn't expose the EntityManagerFactory in JNDI, but Seam provides a built-in manager component. To activate add the following entry:
<persistence:entity-manager-factory
auto-create="true"
name="oc4jEntityManagerFactory"
persistence-unit-name="oc4j_example" />
We then need to tell Seam to use it, so we alter
the
managed-persistence-context
injecting the Entity Manager Factory into the
existing element:
<persistence:managed-persistence-context
name="entityManager"
auto-create="true"
entity-manager-factory="#{oc4jEntityManagerFactory}" />
resources/WEB-INF/web.xml
You must add the Seam container managed transaction integration EJB entry below. Remember for OC4j you need to declare all your EJBs here if you modify the application further.
<ejb-local-ref>
<ejb-ref-name>
oc4j_example/EjbSynchronizations/local
</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>
org.jboss.seam.transaction.LocalEjbSynchronizations
</local>
<ejb-link>EjbSynchronizations</ejb-link>
</ejb-local-ref>
resources/META-INF/orion-application.xml
This is a file that you must create so that RichFaces and Ajax4Jsf stylesheets will work with OC4J. This file basically tells OC4J not force its own inherited URL settings.
<?xml version = '1.0' encoding = 'utf-8'?>
<orion-application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/
orion-application-10_0.xsd"
schema-major-version="10"
schema-minor-version="0"
component-classification="internal">
<imported-shared-libraries>
<remove-inherited name="oracle.xml"/>
</imported-shared-libraries>
</orion-application>
Now you need to tell the
build.xml
file that it
needs to copy this file to the
ear
archive. Find the
<target name="ear"
description="Build the EAR">
target and modify the
<copy todir="${ear.dir}/META-INF">
section to look like the following:
<copy todir="${ear.dir}/META-INF">
<fileset dir="${basedir}/resources/META-INF">
<include name="application.xml" />
<include name="orion-application.xml"/>
<include name="jboss-app.xml" />
</fileset>
</copy>
This application has similar requirements as the
jee5/booking
example above.
The build.xml
must be modified to add
the jars listed below to the generated archive files. Look for the
<fileset dir="${basedir}">
section below and add the imports underneath the other libraries
being imported.
<target name="ear" description="Build the EAR">
<copy todir="${ear.dir}">
<fileset dir="${basedir}/resources">
<include name="*jpdl.xml" />
<include name="*hibernate.cfg.xml" />
<include name="jbpm.cfg.xml" />
<include name="*.drl" />
</fileset>
<fileset dir="${lib.dir}">
<include name="jboss-seam.jar" />
</fileset>
<fileset dir="${basedir}">
<include name="lib/jbpm*.jar" />
<include name="lib/jboss-el.jar" />
<include name="lib/drools-*.jar"/>
<include name="lib/janino*.jar"/>
<include name="lib/antlr-*.jar"/>
<include name="lib/mvel*.jar"/>
<include name="lib/richfaces-api*.jar" />
</fileset>
</copy>
<copy todir="${ear.dir}/META-INF">
<fileset dir="${basedir}/resources/META-INF">
<include name="application.xml" />
<include name="jboss-app.xml" />
</fileset>
</copy>
</target>
Hibernate:
<include name="lib/hibernate.jar"/>
<include name="lib/hibernate-annotations.jar"/>
<include name="lib/hibernate-commons-annotations.jar"/>
<include name="lib/hibernate-entitymanager.jar"/>
<include name="lib/hibernate-search.jar"/>
<include name="lib/hibernate-validator.jar"/>
<include name="lib/commons-logging.jar"/>
<include name="lib/commons-collections.jar"/>
<include name="lib/jboss-common-core.jar"/>
Drools — because we are using Drools to provide Seam Security rules, we need to add in Eclipse JDT compiler (you don't need this on JBoss AS; again this is due to OC4J's classloading):
<include name="lib/core.jar"/>
Third party jars — most of these are only needed because of OC4J's classloading:
<include name="lib/javassist.jar"/>
<include name="lib/quartz.jar"/>
<include name="lib/dbunit.jar"/>
<include name="lib/jboss-embedded-api.jar"/>
<include name="lib/dom4j.jar"/>
<include name="lib/lucene-core.jar"/>
<include name="lib/cglib.jar"/>
<include name="lib/asm.jar"/>
<include name="lib/commons-beanutils.jar"/>
<include name="lib/commons-digester.jar"/>
<include name="lib/concurrent.jar"/>
<include name="lib/antlr.jar"/>
You should end up with something like:
<fileset dir="${basedir}">
<include name="lib/jbpm*.jar" />
<include name="lib/jboss-el.jar" />
<include name="lib/drools-*.jar"/>
<include name="lib/janino*.jar"/>
<include name="lib/antlr-*.jar"/>
<include name="lib/mvel*.jar"/>
<include name="lib/richfaces-api*.jar" />
<include name="lib/hibernate.jar"/>
<include name="lib/hibernate-annotations.jar"/>
<include name="lib/hibernate-commons-annotations.jar"/>
<include name="lib/hibernate-entitymanager.jar"/>
<include name="lib/hibernate-search.jar"/>
<include name="lib/hibernate-validator.jar"/>
<include name="lib/commons-logging.jar"/>
<include name="lib/commons-collections.jar"/>
<include name="lib/jboss-common-core.jar"/>
<include name="lib/core.jar"/>
<include name="lib/javassist.jar"/>
<include name="lib/quartz.jar"/>
<include name="lib/dbunit.jar"/>
<include name="lib/jboss-embedded-api.jar"/>
<include name="lib/dom4j.jar"/>
<include name="lib/lucene-core.jar"/>
<include name="lib/cglib.jar"/>
<include name="lib/asm.jar"/>
<include name="lib/commons-beanutils.jar"/>
<include name="lib/commons-digester.jar"/>
<include name="lib/concurrent.jar"/>
<include name="lib/antlr.jar"/>
</fileset>
These instructions are very similar to the ones in Section 36.3, “Deploying the Seam application to OC4J” but with the correct references
for the oc4j_example
application.
Build your application by calling
ant
in the base directory of your
project (ex.
/home/jbalunas/workspace/oc4j_example
). The target of the build will be
dist/oc4j_example.ear
.
Copy the mysql-connector.jar
file
to the
$ORACLE_HOME/j2ee/home/applib
directory so that jdbc drivers are available.
$ORACLE_HOME/j2ee/home/config/data-sources.xml
<managed-data-source
connection-pool-name="oc4j-example-connection-pool"
jndi-name="jdbc/__oc4jexample"
name="oc4j-example-managed-data-source" />
<connection-pool
name="oc4j-example-connection-pool">
<connection-factory
factory-class="com.mysql.jdbc.Driver"
user="username"
password="password"
url="jdbc:mysql:///oc4j" />
</connection-pool>
$ORACLE_HOME/j2ee/home/config/server.xml
<application name="oc4j_example"
path="../../home/applications/oc4j_example.ear"
parent="default"
start="true" />
$ORACLE_HOME/j2ee/home/config/default-web-site.xml
<web-app application="oc4j_example"
name="oc4j_example"
load-on-startup="true"
root="/oc4j_example" />
Start/stop OC4J following instructions in the
Installation and operation of OC4J
section above.
Checkout the app at:
http://localhost:8888/oc4j_example
In this section we extend the basic
seam-gen
application into a full blown CRUD
application based on an existing database. Plus we will add
Drools
based security as well.
Type ./seam generate-entities
in the
base directory of your seam distribution. This will create the
entities, the Seam Application Framework classes and the
relevant views for the CRUD application.
That's it...no really...that's it. Build and deploy as before and see for yourself.
As stated above this section assumes your database had a
User
table with
username
and
password
columns with at least one entry.
If you don't have this you may need to modify the
authenticate
method below.
Lets link our User
entity into Seam
Security by making our authenticator class a Stateless Session
Bean (OC4J is a EJB3 container after all!):
Add the @Stateless
annotation to the
Authenticator
class.
Rename the class to
AuthenticatorAction
Create an interface called
Authenticator
which
AuthenticatorAction
implements (EJB3 requires session beans to have a
local interface). Annotate the interface with
@Local
, and add a single
method with same signature as the
authenticate
in
AuthenticatorAction
.
@Name("authenticator") @Stateless public class
AuthenticatorAction implements Authenticator {
@Local public interface Authenticator {
public boolean authenticate();
}
Use @PersistenceContext
to
inject an EntityManager by adding this line the
AuthenticatorAction
class:
@PersistenceContext private EntityManager entityManager;
Implement authenticate:
public boolean authenticate() {
List <User> users = entityManager .createQuery("select u from User u where
u.username = #{identity.username} and
u.password = #{identity.password}") .getResultList();
if (users.size() == 1) {
identity.addRole("admin");
return true;
} else {
return false;
}
}
And then add the EJB3 reference to
web.xml
:
<ejb-local-ref>
<ejb-ref-name>
oc4j_example/AuthenticatorAction/local
</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>
org.jboss.seam.tutorial.oc4j.action.Authenticator
</local>
<ejb-link>AuthenticatorAction</ejb-link>
</ejb-local-ref>
Build and deploy as before and notice that now only actual username and passwords are accepted.