Tuesday, January 30, 2007

Using Hibernate as a Pluggable EJB 3 JPA Provider

EJB 3 supports pluggable persistence contract that allows you to plug-in any persistence provider implementing JPA 1.0 with a container that supports JavaEE 5 / EJB 3 spec. It’s provides choice to users to choose their JPA provider of choice. I thought I would give a spin and check whether this plug-ability story really works and here is the result!


I used Oracle Application Server 10g 10.1.3.1 that has support for EJB 3.0 spec (not yet EJB 3 / Java EE 5 compliant) and Hibernate 3.2 that is JPA 1.0 compliant to see whether the plug ability story is real! Oracle Application Server by default uses TopLink Essentials as the JPA provider. Note that TopLink Essentials is the Reference Implementation for the JPA spec.

Loading the Hibernate Libraries in the server

In order to use Hibernate as a pluggable persistence provider, you have to make sure that Hibernate Entity Manager and related libraries are made available to the container class path.

I created a shared library in OC4J named Hibernate and uploaded the required jars. Following is the definition of the shared library:

<shared-library name="Hibernate" version="3.2">
<code-source path="hibernate-entitymanager.jar"/>
<code-source path="hibernate3.jar"/>
<code-source path="jboss-archive-browsing.jar"/>
<code-source path="dom4j-1.6.1.jar"/>
<code-source path="hibernate-annotations.jar"/>
<code-source path="javassist.jar"/>
<code-source path="commons-collections-2.1.1.jar"/>
<code-source path="ehcache-1.2.3.jar"/>
<code-source path="c3p0-0.9.1.jar"/>
<code-source path="concurrent-1.3.2.jar"/>
<code-source path="cglib-2.1.3.jar"/>
<code-source path="asm.jar"/>
<code-source path="asm-attrs.jar"/>
<code-source path="antlr-2.7.6.jar"/>
<code-source path="commons-logging-1.0.4.jar"/>
<code-source path="log4j-1.2.11.jar"/>
</shared-library>

Make sure that application imports the shared library. You can do so by either importing the library during deployment or packaging an orion-application.xml as follows:

<orion-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd" deployment-version="10.1.3.1.0" default-data-source="jdbc/OracleDS" component-classification="external"
schema-major-version="10" schema-minor-version="0" >
<imported-shared-libraries>
<import-shared-library name="Hibernate"/>
</imported-shared-libraries>
</orion-application>

Configuring the Persistence Unit

You need to configure the persistence unit to specify the persistence provider and other vendor specific properties in the persistence.xml. For my test application I created a simple entity class and packaged the following persistence.xml in my application that uses Hibernate 3.2 as the JPA provider.

<persistence>
<persistence-unit name="howto">
<jta-data-source>jdbc/OracleDS</jta-data-source>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.OC4JTransactionManagerLookup"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true" />

</properties>
</persistence-unit>
</persistence>

Note that in above I set provider class to org.hibernate.ejb.HibernatePersistence that tells the container to use Hibernate 3.2 as the persistence provider instead of using TopLink Essentials as the JPA provider.

Access to Transaction Manager

The primary reason behind the pluggable persistence provider is to provide facility to use JPA with a container managed Entity Manager and hence Hibernate needs to access the JTA Transaction Manager of the container.


Hibernate 3.2 does not use the JTA TransactionSynchronizationRegistry whose sole purpose is for such integration.

Instead it provides classes for each application server that looks up the Transaction Manager.
For example,org.hibernate.transaction.OC4JtransactionManagerLookup is provided with Hibernate as a persistence property to lookup OC4J’s transaction manager as follows:

<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.OC4JTransactionManagerLookup"/>

If you want to use another application server then you have to the class for that server.


Deploy and Run Your Application

You can package your entities and then deploy to the server

Now after you deploy your application into OC4J you should be able to run your application. If you used the property hibernate.show_sql to true, you will see similar output from Hibernate in your console.

07/01/30 12:11:54 Hibernate: insert into EMP (ename, sal, EMPNO) values (?, ?, ?
)
07/01/30 12:11:55 Hibernate: select employee0_.EMPNO as EMPNO0_0_, employee0_.en
ame as ename0_0_, employee0_.sal as sal0_0_ from EMP employee0_ where employee0_

Conclusion

I did some testing and the application works as expected and hence I conclude EJB 3 delivers on the plug-ability story and Oracle Application Server 10g is Hot Pluggable!

Monday, January 22, 2007

Using global-jndi-lookup-enable to lookup EJBs across applications

OC4J 10.1.3.1 allows lookup of EJBs across application by enabling the global JNDI lookup.

To use the global JNDI feature in OC4J, first you have to enable it.
1. Using a text editor, open config/server.xml.
2. Within the <application-server> element, add the global-jndi-lookup-enabled attribute and set it to true as follows:

<application-server global-jndi-lookup-enabled="true">
</application-server>

3. Save and close server.xml.

4. Restart the application server.

5. Deploy application that contains the EJB. Let us say the application name is APP2 that contains a remote EJB with JNDI location “EmployeeFacadeBean”.

To find the JNDI location look at the generated orion-ejb-jar.xml in the server’s application deployment directory. To configure a different JNDI location package an orion-ejb-jar.xml as follows:

<session-deployment name="EmployeeFacadeBean">
name="EmployeeFacadeBean" location="EmployeeFacadeBean"

</session-deployment >

The default JNDI name is the name of the remote interface of the session bean configured using the ejb-name element in ejb-jar.xml or name element of @Stateless or @Stateful annotations.

The client application that looks up the EJB must package the remote, home, interfaces to look up the remote EJB.

You can lookup the EJB from the client application using the JNDI location as follows:

Context ctx = new InitialContext();
employeeFacade = (EmployeeFacade) ctx.lookup("EmployeeFacadeBean");


Now you deploy your client application and the application should be able to lookup the EJB in APP2!

If you want to use in OC4J 10.1.3.0.0 then make sure that you apply 10.1.3.1 patchset!

Thursday, January 18, 2007

EJB 3 In Action: Code Samples

The code samples of EJB 3 In Action are now available from the Manning web site. We have made the source code available for Java EE SDK (Glassfish) and Oracle Application Server. You can download the code samples from the book site. All chapters of the book are available at the book site through the Manning's MEAP program. So ahead an pre-order a copy for yourself and read the final drafts of the book from the Manning site

Monday, January 08, 2007

Blogger ATOM Woes and RSS URL for blogger !

My transition to Blogger has been smooth except few hiccups. Few weeks back Blogger switched to ATOM 1.0 by default and many blog aggregators that do not support ATOM yet (such as Javablogs.com) stopped taking updates from my Blog. After a lot of research I found that Blogger provides an URL with RSS 2.0 feeds. For example you can get RSS 2.0 feed for my blog at http://debupanda.blogspot.com/feeds/posts/default?alt=rss

Happy New Year!!

Wish you a very happy and prosperous 2007! Now that I’m back from 5 weeks trip to India and back from jet lag. Ready to Blog, Stay Tuned!