OC4J (Oracle Containers for Java) 11g (currently a "Technology Preview" release) is Oracle's JEE 5 application server. We will will start by looking at the building and deploying the Hotel Booking example application which comes with Seam, and then at deploying a project generated by seam-gen. This project will integrate Seam, RichFaces Ajax and components, Seam Security (with Drools), Facelets and JPA provided by Hibernate.
This section 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/.
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.
First, lets look at the dependencies of the booking example. Armed with this knowledge we can look at the extra dependencies requirements that OC4J adds.
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-beanutils
jboss-seam-debug.jar
jsf-facelets.jar
richfaces-api.jar — which requires Apache commons-digester and commons-beanutils
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 three jars (hibernate3.jar, hibernate-annotations.jar, hibernate-entitymanager.jar) and their dependencies (jboss-common.jar, jboss-archive-browsing.jar and ejb3-persistence.jar). You can find these in the hibernate/lib directory in the Seam distribution.
thirdparty-all.jar — a selection of third party libraries on which Seam depends (like javassist).
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:
antlr-2.7.6.jar — needed for Seam Text (not used in the example).
jbpm-jpdl.jar — needed for Seam's JBPM integration (not used in the example).
Drools — needed for Seam Security. We aren't using Seam security with Drools, but have to include it. Drools consists of 5 jars - drools-core-4.0.0.jar, drools-compiler-4.0.0.jar, janino-2.5.7.jar, mvel14-1.2rc1.jar and antlr-runtime-3.0.jar. 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 JEE 5 application servers - for example OC4J and Glassfish.
<ejb-local-ref> <ejb-ref-name> jboss-seam-jee5/AuthenticatorAction/local </ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local-home/> <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:
<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 following files in the project:
build.xml — Un-comment the OC4J-related libraries
resources/META-INF/persistence.xml — Comment out the Glassfish properties and un-comment the OC4J properties.
Build the demo app by running ant. The build target is dist/jboss-seam-jee5.ear
Copy hsqldb.jar to OC4J: 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)
This mini-tutorial describes the (fairly tedious) steps required to deploy a JEE 5 application to OC4J. It 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.
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
Edit the OC4J datasource $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 OC4J: $ORACLE_HOME/bin/oc4j -start
You will be asked to set the admin password if this is the first time you've started OC4J
Checkout the app at: http://localhost:8888/seam-jee5
You can stop the server by pressing CTRL-C in the console on which the server is running.
The following explanation assumes you are using the command line and a simple text editor, but of course you can use your favourite IDE - seam-gen projects come with support for Eclipse and Netbeans.
We start by creating a pretty simple application using seam-gen. seam-gen uses Hibernate Tools to reverse engineer a database schema to JPA entity beans; it also genereates Seam Application Framework components and JSF views for CRUD. This tutorial uses MySQL (but of course you could use any database, altering the SQL as appropriate); install, configure and run MySQL, then create a database with some sample data.
Next, run ./seam setup in the seam directory.
> ./seam setup Buildfile: build.xml setup: [echo] Welcome to seam-gen :-) [input] Enter your Java project workspace (the directory that contains your Seam projects) [/home/pmuir/workspace] [/home/pmuir/workspace] [input] Enter your JBoss home directory [/home/pmuir/java/jboss-4.2.1.GA] [/home/pmuir/java/jboss-4.2.1.GA] [input] Enter the project name [oc4j-example] [oc4j-example] [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 [org.jboss.seam.tutorial.oc4j.action] [org.jboss.seam.tutorial.oc4j.action] [input] Enter the Java package name for your entity beans [org.jboss.seam.tutorial.oc4j.model] [org.jboss.seam.tutorial.oc4j.model] [input] Enter the Java package name for your test cases [org.jboss.seam.tutorial.oc4j.test] [org.jboss.seam.tutorial.oc4j.test] [input] What kind of database are you using? [mysql] (hsql, [mysql], oracle, postgres, mssql, db2, sybase, enterprisedb, ) [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/mysql.jar] [lib/mysql.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:///oc4j] [jdbc:mysql:///oc4j] [input] Enter database username [user] [user] [input] Enter database password [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? [y] ([y], n, ) [input] Do you want to drop and recreate the database tables and data in import.sql each time you deploy? [n] (y, [n], ) [propertyfile] Updating property file: /home/pmuir/workspace/jboss-seam/seam-gen/build.properties [echo] Installing JDBC driver jar to JBoss server [echo] Type 'seam new-project' to create the new project BUILD SUCCESSFUL
Type ./seam new-project to create your project and cd to the newly created project.
Type ./seam generate-entities to run create the entities, the Seam Application Framework classes and the relevant views.
We now need to make some changes to the generated project. Let's start with the configuration files:
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).
Add the properties (described above):
<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:
<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:
<persistence:managed-persistence-context name="entityManager" auto-create="true" entity-manager-factory="#{oc4jEntityManagerFactory}" />
You need to declare all your EJBs here. Remember to include the Seam container managed transaction integration:
<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>
Now, lets add in the extra dependencies:
Hibernate —
Copy the jars from hibernate/lib directory in the Seam distribution oc4j-example/lib: cp ../jboss-seam/hibernate/lib/*.jar lib/
Alter the build.xml to include them in the ear - add these includes underneath the other libraries being copies:
<include name="lib/hibernate-annotations.jar" /> <include name="lib/hibernate-entitymanager.jar" /> <include name="lib/hibernate3.jar" /> <include name="ejb3-peristence.jar" /> <include name="lib/jboss-archive-browsing.jar" /> <include name="lib/jboss-common.jar" />
thirdparty-all.jar — alter the build.xml to include it - add this include:
<include name="lib/thirdparty-all.jar" />
antlr-2.7.6.jar — alter the build.xml to include it - add this include:
<include name="lib/antlr-*.jar" />
As 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):
cp ../jboss-seam/seam-gen/lib/org.eclipse.jdt.core*.jar lib/
Alter the build.xml to include them in the ear:
<include name="lib/org.eclipse.jdt.core*.jar" />
You should end up with something like:
<fileset dir="${basedir}"> <!-- other libraries added by seam-gen --> <include name="lib/hibernate-annotations.jar" /> <include name="lib/hibernate-entitymanager.jar" /> <include name="lib/hibernate3.jar" /> <include name="lib/jboss-archive-browsing.jar" /> <include name="lib/jboss-common.jar" /> <include name="lib/thirdparty-all.jar" /> <include name="lib/antlr-*.jar" /> <include name="lib/org.eclipse.jdt.core*.jar" /> </fileset>
Finally, lets link our User entity into Seam Security (we have a User table with a username column and a password column). We're going to make our authentictor a Stateless Session Bean (OC4J is a EJB3 container after all!):
Add the @Stateless annotation.
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:
@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>
Now you can go on and customize your application.
To deploy your application use the deployment instructions above in conjunction with these deployment descriptors:
<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>
<application name="oc4j-example" path="../../home/applications/oc4j-example.ear" parent="default" start="true" />
<web-app application="oc4j-example" name="oc4j-example" load-on-startup="true" root="/oc4j-example" />