Anchor | ||||
---|---|---|---|---|
|
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 | Not Supported out of the box. Can be implemented by writing a GBean and a Hibernate Connection Provider class. | Supported. Hibernate is distributed with |
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 | ||
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. |
Sample application
Anchor | ||||
---|---|---|---|---|
|
...
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 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 | ||||
---|---|---|---|---|
| ||||
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 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
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 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
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 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 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 | ||||||||
xml | xml | |||||||
borderStyle | solid | |||||||
title | geronimo-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 thehibernate_home>/lib/hibernate3.jar
file.
...