Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Anchor
top
top

This article will help you migrate applications using Hibernate 3.2 as the ORM tool from JBoss Application Server 4.2.1 to Apache Geronimo 12.0.

Hibernate is a powerful, high performance object/relational persistence and query service. It helps in the development of persistent (POJO) classes which have the getter and setter methods for attributes that are then mapped to fields in the database. You may follow object-oriented idiom - including association, inheritance, polymorphism, composition, and collections. Hibernate allows you to express queries in its own portable SQL extension (HQL), as well as in native SQL, or with an object-oriented Criteria and Example API.

...

These properties are common to any application server including Apache Geronimo v1v2.0.

However, JBoss (more specifically the Hibernate MBean) provides two additional deployment mechanisms.

...

The following table provides a feature-to-feature comparison between these two applicaiton servers.

Feature

Apache Geronimo v2.0

JBoss v4.2.1

Apache Geronimo v1.0

Container-managed datasource Supported. Hibernate can lookup a datasource from JNDI given its JNDI name.

Supported. Hibernate is able to use a datasource given its JNDI name. This is because it is running in the same thread as the application.

Supported. Hibernate can lookup a datasource from JNDI given its JNDI name.

Automatic JNDI binding

Not Supported.

Supported. Once the property is set the session factory is bound to the JNDI context. Not Supported.

JTA Session binding

Supported out of the Box. Hibernate provides a lookup class for the JBoss Transaction Manager.

This feature is not supported out of the box. We need to write a lookup for the Geronimo Transaction Manager to enable this.

Supported out of the Box. Hibernate provides a lookup class for the JBoss Transaction Manager.

JMX deployment

JMX deployment

Supported. Hibernate is distributed with org.hibernate.jmx.HibernateService which can be deployed on JBoss.

Not Supported out of the box. Can be implemented by writing a GBean and a Hibernate Connection Provider class.

Supported. Hibernate is distributed with org.hibernate.jmx.HibernateService which can be deployed on JBoss.

Hibernate Archive (HAR)

Not Supported. Hibernate classes are deployed as a part of the J2EE archives.

Supported. A HAR packages the configuration and mapping files enabling extra server support to deployment.

Not Supported. Hibernate classes are deployed as a part of the J2EE archives.

Caching

You can use caching mechanisms provided by hibernate. Integration with JBoss Cache is also supported.

You can use caching mechanisms provided by hibernate. Integration with JBoss Cache is also supported.

Session Management

Not Supported. It is required to manually open sessions. Only the transaction needs to be closed.

The Hibernate Session's lifecycle can be automatically bound to the scope of a
JTA transaction. This means you no longer have to manually open and close the Session, this becomes the job of a JBoss EJB interceptor. Not Supported. It is required to manually open sessions. Only the transaction needs to be closed.

Hibernate Mapping Files

We need to specify the locations of the Hibernate mapping files.

If we use HAR deployment JBoss will automatically lookup the Hibernate mapping files.

We need to specify the locations of the Hibernate mapping files.

Back to Top

Sample application
Anchor
sampleApp
sampleApp

...

The following figure illustrates the application flow:
First, the user accesses the Login page. From the Login page the user enters the user name and password. If the user name or password is not valid the application throws an error message and rejects the user's login attempt. If the user name and password are correct, the user is taken to the Available Stocks page where he/she can view all the stocks that are present for sale at that time.
The user can choose to buy as many stocks as wanted, depending on the available money in the account, by clicking the Buy button. After the transaction completes successfully the user is brought back to the Available Stocks page where he/she can buy more stocks if required. If the user has insufficient funds to buy stocks the application will throw an error and will not process the transaction. The error message is shown at the top of the Available Stocks page. There is a User Info button on this page. By clicking this button the user is taken to the User Info page and shown the user details.
From the Available Stocks page there is a View your Portfolio link that shows all the stocks that the user owns. In that page, the user can select the stocks and quantity to sell. This page also shows the user's available cash in the User Cash field. If the user tries to sell more stocks than he/she has, the application will throw an error. The error message will be displayed on the same page. For each successful sale, the sale amount is added to the user's cash balance. The quantity text box shows the quantity of stocks of a particular company that the user has. The Quantity to Sell field allows the user to enter the quantity of stocks to sell for a specific company. For selling and buying, the radio button should be checked. This should be done after entering the values. If either the quantity to sell textbox is not filled or the selection box is not checked and you press on sell a JavaScript alert will be triggered saying that the required field is empty. On entering non numeric characters for quantity another alert will be triggered. This behavior is similar for the Available Stocks page as well.
New users can register by clicking the Register button in the login page. In the Registration page the user will enter a user id, user name, password, address and available cash.
Back to Top

Application classes and JSP pages

...

Code Block
xml
xml
borderStylesolid
titlemysql-geronimo-plan.xml
<?xml version="1.0" encoding="UTF-8"?>
<connector configId="user/database-pool-HibernateDS/1/car" xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.02">
  <dep:dependencyenvironment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.01">
    <dep:uri>mysql/mysql-connector-java/3.1.10-bin/jar</dep:uri>
  </dep:dependency>
  <resourceadapter>
    moduleId>
	  <dep:groupId>user</dep:groupId>
	  <dep:artifactId>database-pool-HibernateDB</dep:artifactId>
	  <dep:version>2.0</dep:version>
	  <dep:type>car</dep:type>
	</dep:moduleId>
	<dep:dependencies>
	  <dep:dependency
	    <dep:groupId>mysql</dep:groupId>
		<dep:artifactId>mysql-connector-java</dep:artifactId>
		<dep:version>3.1.10-bin</dep:version>
		<dep:type>jar</dep:type>
	  </dep:dependency>
	</dep:dependencies>
  </dep:environment>
  <resourceadapter>
    <outbound-resourceadapter>
      <connection-definition>
        <connectionfactory-interface>javax.sql.DataSource</connectionfactory-interface>
        <connectiondefinition-instance>
          <name>HibernateDS</name>
          <config-property-setting name="Password">password</config-property-setting>
          <config-property-setting name="CommitBeforeAutocommit">false</config-property-setting>
          <config-property-setting name="Driver">com.mysql.jdbc.Driver</config-property-setting>
          <config-property-setting name="ExceptionSorterClass">
	                                 org.tranql.connector>org.tranql.connector.AllExceptionsAreFatalSorter</config-property-setting>
          <config-property-setting name="UserName">root</config-property-setting>
          <config-property-setting name="ConnectionURL">jdbc:mysql://localhost:3306/adi</config-property-setting>
          <connectionmanager>
            <local-transaction/>
            <single-pool>
              <max-size>10</max-size>
              <min-size>0</min-size>
              <blocking-timeout-milliseconds>5000</blocking-timeout-milliseconds>
              <idle-timeout-minutes>30</idle-timeout-minutes>
              <match-one/>
            </single-pool>
          </connectionmanager>
        </connectiondefinition-instance>
      </connection-definition>
    </outbound-resourceadapter>
  </resourceadapter>
</connector>

...

Depending on your environment you should see a confirmation message similar to this one:

No Format
bgColor#000000#FFFFFF
borderStylesolid
E:\geronimo-1.0\bin>deploy --user system --password manager deploy \brokerage\plan\mysql-geronimo-plan.xml
..\repository\tranql\rars\tranql-connector-1.1.rar
    Deployed user/database-pool-HibernateDS/1/car

...

Code Block
java
java
borderStylesolid
titleHibernateUtil.java for Geronimo
package com.dev.trade.util;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

/**
 * Configures and provides access to Hibernate sessions, tied to the
 * current thread of execution.  Follows the Thread Local Session
 * pattern, see {@link http://hibernate.org/42.html}.
 */
public class HibernateUtil {

    /** location of the Hibernate Configuration File */
    private static String CONFIG_FILE_LOCATION = "hibernate.cfg.xml";

    /** Holds a single instance of Session */
    private static final ThreadLocal threadLocal = new ThreadLocal();

    /** The single instance of hibernate configuration */
    private static final Configuration cfg = new Configuration();

    /** The single instance of hibernate SessionFactory */
    private static org.hibernate.SessionFactory sessionFactory;

    /**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *
     *  @return Session
     *  @throws HibernateException
     */
    public static Session getCurrentSession() throws HibernateException {
        Session session = (Session) threadLocal.get();

        if (session == null || ! session.isConnected()) {
            if (sessionFactory == null) {
                try {
                    cfg.configure(CONFIG_FILE_LOCATION);
                    sessionFactory = cfg.buildSessionFactory();
                }
                catch (Exception e) {
                    System.err.println("%%%% Error Creating SessionFactory %%%%");
                    e.printStackTrace();
                }
            }
            session = sessionFactory.openSession();
            threadLocal.set(session);
        }

        return session;
    }

    /**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();


        if (session != null) {
            session.close();
        }
    }



}

HibernateUtil.java is located in the <brokerage_home>/src/com/dev/trade/util directory. For your convenience, a copy of this file is already provided with the sample application.

...

Hibernate comes with transaction manager lookup classes for many application servers. Unfortunately hibernate Hibernate 3.1 2 does not have a lookup class specific for Apache Geronimo, so we need to write our own. The code for the Geronimo specific transaction manager lookup is shown in the following example.

Code Block
java
java
borderStylesolid
titleGeronimoTransactionManagerLookup
package org.hibernate.transaction;

import java.util.Iterator;
import java.util.Properties;
import javaxjava.managementutil.ObjectNameSet;

import javax.transaction.TransactionManager;
import org.hibernate.HibernateException;
import org.hibernate.transaction.TransactionManagerLookup;

public class GeronimoTransactionManagerLookup
    implements TransactionManagerLookup
{
   public static final String TransactionMgrGBeanName="geronimo.server:J2EEApplication=null,
      J2EEModule=geronimo/j2ee-server/1.0/car,J2EEServer=geronimo,j2eeType=TransactionManager,import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.AbstractNameQuery;
import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.kernel.KernelRegistry;
import org.apache.geronimo.kernel.proxy.ProxyManager;

public class GeronimoTransactionManagerLookup implements
        TransactionManagerLookup  name=TransactionManager";
{

    public static final String UserTransactionName = "java:comp/UserTransaction";

    public TransactionManager getTransactionManager(Properties props) throws HibernateException {
   try {    /*
         Class kernelClass* try { Kernel kernel = ClassKernelRegistry.forName("org.apache.geronimo.kernel.Kernel");getSingleKernel(); ProxyManager
         Class* kernelRegistryClassproxyManager = Classkernel.forName("org.apache.geronimo.kernel.KernelRegistry");getProxyManager(); AbstractNameQuery query =
         Class* proxyManagerClass = Class.forName("org.apache.geronimo.kernel.proxy.ProxyManager");new AbstractNameQuery(TransactionManager.class.getName()); Set names =
         ObjectName TransactionManagerName = new ObjectName(TransactionMgrGBeanName);
  * kernel.listGBeans(query); AbstractName name = null; for (Iterator it =
       Object kernel =* kernelRegistryClassnames.getMethod("getSingleKernel", null).invoke(null, null);
iterator(); it.hasNext();) name = (AbstractName) it.next();
         * Object proxyManagertransMg = kernelClass.getMethod("getProxyManager",null).invoke(kernel,null);(Object) proxyManager.createProxy(name,
         Class[] clzArray = {ObjectName.class,Class.class};* TransactionManager.class); return (TransactionManager)transMg; }catch
         Object[] objArray =* (Exception e) {TransactionManagerName, TransactionManager.class};
   e.printStackTrace(); System.out.println(); throw new
      return (TransactionManager)proxyManagerClass.getMethod("createProxy",clzArray).
  * HibernateException("Geronimo Transaction Manager        invoke(proxyManagerLookup Failed", objArraye); }

       }catch (Exception e) { */
       try {
   throw new HibernateException("Geronimo Transaction ManagerKernel Lookupkernel Failed", e= KernelRegistry.getSingleKernel();
       }
}

AbstractNameQuery query = public String getUserTransactionName() {new AbstractNameQuery(TransactionManager.class.getName ());
       returnSet<AbstractName> UserTransactionName;
names   }
}
= kernel.listGBeans(query);
       if (names.size() != 1) {
           throw new IllegalStateException("Expected one transaction manager, not " + names.size());
       }
       AbstractName name = names.iterator().next();
       TransactionManager transMg = (TransactionManager)
       kernel.getGBean(name);
       return (TransactionManager)transMg;
       } catch (Exception e) {
           e.printStackTrace();
           System.out.println();
           throw new HibernateException("Geronimo Transaction Manager Lookup Failed", e);
       }
   }

    public String getUserTransactionName() {
        return UserTransactionName;
    }
}

For your convenience this class is already provided in the <brokerage_home>/TransactionManager directory. Create the following directory structure and copy the GeronimoTransactionManagerLookup.java there.

...

Code Block
xml
xml
borderStylesolid
titlehibernate-cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
 <session-factory>
 <!-- properties -->
 <property name="connection.datasource">java:comp/env/jdbc/HibernateDB</property>
 <property name="hibernate.transaction.manager_lookup_class">
    org.hibernate.transaction.GeronimoTransactionManagerLookup
 </property>

  <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

 <!-- Disable the second-level cache  -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="hibernate.current_session_context_class">org.hibernate.context.JTASessionContext</property>
session_context_class">org.hibernate.context.JTASessionContext</property>
 <!-- Echo all executed SQL to stdout -->
 <property name="hibernate.show_sql">true</property>

 <!-- Drop and re-create the database schema on startup -->
<!--<property name="hibernate.hbm2ddl.auto">create</property> -->

 <!-- Echomapping all executed SQL to stdout -->
 <property name="hibernate.show_sql">true</property>

 <!-- Drop and re-create the database schema on startup -->
<!--<property name="hibernate.hbm2ddl.auto">create</property> -->

 <!-- mapping files -->
 <mapping resource="Stock.hbm.xml"/>
 <mapping resource="UserStock.hbm.xml"/>
 <mapping resource="User.hbm.xml"/>

 </session-factory>
</hibernate-configuration>

Additional details for the specific functions of each of these properties can be found in the hibernate manual.

One last step before building is to create a geronimo-web.xml file which is the Geronimo specific deployment descriptor as illustrated in the following example. Once again, for your convenience this file is also provided with the sample application in the <brokerage_home>/web/descriptors/geronimo directory.

files -->
 <mapping resource="Stock.hbm.xml"/>
 <mapping resource="UserStock.hbm.xml"/>
 <mapping resource="User.hbm.xml"/>

 </session-factory>
</hibernate-configuration>

Additional details for the specific functions of each of these properties can be found in the hibernate manual.

One last step before building is to create a geronimo-web.xml file which is the Geronimo specific deployment descriptor as illustrated in the following example. Once again, for your convenience this file is also provided with the sample application in the <brokerage_home>/web/descriptors/geronimo directory.

Code Block
xml
xml
borderStylesolid
titlegeronimo-web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.1" xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1">
    <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1">
	    <dep:moduleId>
		    <dep:groupId>BrokerageApp</dep:groupId>
			<dep:artifactId>MySqlDS</dep:artifactId>
			<dep:version>2.0</dep:version>
			<dep:type>car</dep:type>
		</dep:moduleId>

		<dep:dependencies>
		    <dep:dependency>
		        <dep:groupId>user</dep:groupId>
			    <dep:artifactId>database-pool-HibernateDB</dep:artifactId>
			    <dep:version>2.0</dep:version>
			    <dep:type>car</dep:type>
			</dep:dependency>
		</dep:dependencies>

		<dep:hidden-classes>
		    <dep:filter>org.springframework</dep:filter>
			<dep:filter>META-INF/spring</dep:filter>
			<!--dep:filter>antlr</dep:filter-->
		</dep:hidden-classes>
	</dep:environment>

	
Code Block
xmlxml
borderStylesolid
titlegeronimo-web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://geronimo.apache.org/xml/ns/web"
 xmlns:naming="http://geronimo.apache.org/xml/ns/naming" configId="BrokerageApp">
    <hidden-classes><filter>org.springframework</filter></hidden-classes>
    <hidden-classes><filter>antlr</filter></hidden-classes>
    <context-root>/brokerage</context-root>

    <resource-ref>
        <ref-name>jdbc/HibernateDB</ref-name>
        <resource-link>HibernateDS</resource-link>
    </resource-ref>
</web-app>

...

  • Add the hibernate jar to the classpath. You will now need to build hibernate with the GeronimoTransactionManagerLookup class. If you have not downloaded the hibernate source you can compile the class after putting the hibernate jar in the classpath and then manually add that class to the hibernate jar file.
    set CLASSPATH=%CLASSPATH%;<hibernate_home>/lib/hibernate3.jar
  • Add the Geronimo kernel to your classpath
    set CLASSPATH=%CLASSPATH%;<geronimo_home>/lib/geronimo-kernel-2.0.1.jar
  • To add the class manually, although not needed for this particular sample, you can use the tool of your preference and add the GeronimoTransactionManagerLookup.class to the org\hibernate\transaction directory in the hibernate_home>/lib/hibernate3.jar file.

...