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 26.2.3, “ Building the jee5/booking example ” below.
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:
Third party jars — various jars needed for seam and this example to run.
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:
Drools — needed for Seam Security. We aren't using Seam security with Drools, but have to include it. Drools consists of 6 jars:
Drools integration is not used in the example.
There are just a few changes to be made:
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>
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 26.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-gen/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 26.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.2.GA] [C:/Program Files/jboss-4.2.2.GA] /home/jbalunas/jboss/jboss-4.2.2.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 [lib/hsqldb.jar] [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.2.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:
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>
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.
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)
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)
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}" />
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>
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/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/antlr.jar"/> </fileset>
These instructions are very similar to the ones in Section 26.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.