Migrating to a standalone Spring Hibernate application

Look here for updated version http://cuppajavamattiz.com/2013/01/16/polishing-the-standalone-spring-hibernate-example/

An interesting experiment. I am trying to run a proof-of-concept standalone spring-hibernate application. I modified the jsf-spring-hibernate web application to run as a standalone: http://cuppajavamattiz.com/2007/09/15/a-simple-spring-hibernate-example/ It proved challenging but jsf backing beans not being strongly tied to the request-response mechanism helped and there was minimum possible modification.

I have used Eclipse for the following project.

Add the following jars to the classpath section of your eclipse project:

All jars from spring-framework-2.5.4-with-dependencies.zip under the following folders:
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\dist
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\dist\modules
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\hibernate
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\log4j
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\jakarta-commons – minus commons-attributes-compiler.jar
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\dom4j
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\ehcache
spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\c3p0

An extra download would be for jta.jar.

And of course you would have to add the mysql driver to the classpath. I am using
mysql-connector-java-5.0.8-bin.jar.

MySql database is the same as used in the previous example.

The configuration file for spring-hibernate is mattiz.xml placed in >resources< folder under root.

mattiz.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
 
<beans>
    <bean id="mattiz.hibernate.dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/AUTHORS" />
        <property name="user" value="admin" />
        <property name="password" value="admin" />
    </bean>
    <bean id="mattiz.abstract.hibernate.sessionfactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
        abstract="true" lazy-init="true">
        <property name="dataSource">
            <ref local="mattiz.hibernate.dataSource" />
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQLDialect
</prop>
                <prop key="hibernate.show_sql">false</prop>
            </props>
        </property>
    </bean>
    <bean id="mattiz.pageSize" class="java.lang.Integer">
        <constructor-arg value="5000"></constructor-arg>
    </bean>
    <bean id="mattiz.hibernate.sessionfactory" parent="mattiz.abstract.hibernate.sessionfactory">
        <property name="mappingResources">
            <list>
                <value>resources/Authors.hbm.xml</value>
            </list>
        </property>
    </bean>
    <bean id="mattiz.transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="mattiz.hibernate.sessionfactory" />
        </property>
    </bean>
    <bean id="mattiz.hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory">
            <ref bean="mattiz.hibernate.sessionfactory" />
        </property>
    </bean>
    <bean id="mattiz.mattizDAO" class="com.mattiz.persistence.data.AuthorLookupBean"
        singleton="true">
        <property name="hibernateTemplate">
            <ref bean="mattiz.hibernateTemplate" />
        </property>
    </bean>
    <bean id="mattiz.client" class="com.mattiz.web.managedbeans.AuthorSearchCreateBean"
        singleton="true">
        <property name="serviceManager" ref="mattiz.service.manager" />
    </bean>
    <bean id="mattiz.service.manager" class="com.mattiz.service.spring.DefaultServiceManager"
        singleton="true">
        <property name="authorLookup" ref="mattiz.mattizDAO" />
    </bean>
</beans>

Note
Though this is a standalone app, in a spring web application you can have mattiz.xml file instead of applicationcontext.xml as the spring configuration file. ContextLoaderListener is a ServletContextListener that initializes when your webapp starts up. By default, it looks for Spring’s configuration file at WEB-INF/applicationContext.xml. You can change this default value by specifying a context-param element named “contextConfigLocation.” Example:

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/mattiz.xml</param-value>
        </context-param>
    </listener-class>
</listener>

To define hibernate mapping file in a spring web app add the hibernate mapping file entry in mapping resource inside Spring’s applicationContext file in the web/WEB-INF directory or in mattiz.xml as in the standalone example above.

<property name="mappingResources">
    <list>
        <value>resources/Authors.hbm.xml</value>
    </list>
</property>
</bean>

resources folder under root also contains the mapping hibernate file:

Authors.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <class name="com.mattiz.persistence.beans.Authors" table="AUTHORS"
        lazy="false">
        <id name="isbn_Code" type="java.lang.String" column="ISBN_CODE"
            length="10" />
        <property name="author" type="java.lang.String" column="AUTHOR"
            length="50" />
    </class>
</hibernate-mapping>

The classes from the jsf spring hibernate example have been reused with minor changes:

Client Side code:

AuthorSearchCreateBean.java

package com.mattiz.web.managedbeans;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mattiz.service.spring.AuthorsBean;
import com.mattiz.service.spring.DefaultServiceManager;
import com.mattiz.service.spring.ServiceManager;

public class AuthorSearchCreateBean {
	private ApplicationContext applicationContext;
	private String isbnCode;
	private String author;
	private AuthorsBean authorsBean;
	private ServiceManager serviceManager;

	public ServiceManager getServiceManager() {
		serviceManager = (DefaultServiceManager) applicationContext
				.getBean("mattiz.service.manager");
		return serviceManager;
	}

	public void setServiceManager(ServiceManager serviceManager) {
		this.serviceManager = serviceManager;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getIsbnCode() {
		return isbnCode;
	}

	public void setIsbnCode(String isbnCode) {
		this.isbnCode = isbnCode;
	}

	public String addAuthor() {
		serviceManager = getServiceManager();
		serviceManager.addAuthor(isbnCode, author);
		return "two";
	}

	public String findAuthor() {
		serviceManager = getServiceManager();
		authorsBean = serviceManager.findAuthor(isbnCode);
		isbnCode = authorsBean.getIsbnCode();
		author = authorsBean.getAuthor();
		return author;
	}

	public AuthorsBean getAuthorsBean() {
		return authorsBean;
	}

	public void setAuthorsBean(AuthorsBean authorsBean) {
		this.authorsBean = authorsBean;
	}

	public static void main(String[] args) {
        AuthorSearchCreateBean authorSearchCreateBean = new AuthorSearchCreateBean();
        authorSearchCreateBean.applicationContext = new ClassPathXmlApplicationContext(
                "resources/mattiz.xml");
        authorSearchCreateBean.isbnCode = "007";
        authorSearchCreateBean.author = "Bond";
        authorSearchCreateBean.addAuthor();
        authorSearchCreateBean.isbnCode = "007";
        String authorFromDB = authorSearchCreateBean.findAuthor();
        System.out.println("AUTHOR IS " + authorFromDB);
    }
}

Note
While Bean Factory is used for simple applications, the Application Context is spring’s more advanced container. Like ‘BeanFactory’ it can be used to load bean definitions, wire beans together and dispense beans upon request. It also provide
1) a means for resolving text messages, including support for internationalization.
2) a generic way to load file resources.
3) events to beans that are registered as listeners.

Because of additional functionality, ‘Application Context’ is preferred over a BeanFactory. Only when the resource is scarce like mobile devices, ‘BeanFactory’ is used. One of the commonly used implementation of ‘Application Context’ is the ClassPathXmlApplicationContext. It Loads context definition from an XML file located in the classpath, treating context definitions as classpath resources. The application context is loaded from the application’s classpath by using the code:

AuthorSearchCreateBean authorSearchCreateBean = new AuthorSearchCreateBean();
authorSearchCreateBean.applicationContext = new ClassPathXmlApplicationContext("resources/mattiz.xml");
....
serviceManager = (DefaultServiceManager) applicationContext.getBean("mattiz.service.manager");

Service layer classes:

DefaultServiceManager.java

package com.mattiz.service.spring;

import com.mattiz.persistence.data.AuthorLookupBean;
import com.mattiz.service.spring.AuthorsBean;

public class DefaultServiceManager implements ServiceManager {
	private AuthorLookupBean authorLookup;

	public void addAuthor(String isbnCode, String author) {
		authorLookup.insertAuthor(isbnCode, author);
	}

	public AuthorsBean findAuthor(String isbnCode) {
		AuthorsBean authorsBean = authorLookup.lookupIsbn(isbnCode);
		return authorsBean;
	}

	public AuthorLookupBean getAuthorLookup() {
		return authorLookup;
	}

	public void setAuthorLookup(AuthorLookupBean authorsLookup) {
		this.authorLookup = authorsLookup;
	}
}

ServiceManager.java

package com.mattiz.service.spring;
public interface ServiceManager {
public void addAuthor(String isbnCode, String author);
public AuthorsBean findAuthor(String isbnCode);
}

Value Object Class:

AuthorsBean.java

package com.mattiz.service.spring;

public class AuthorsBean {
	String author;
	String isbnCode;

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getIsbnCode() {
		return isbnCode;
	}

	public void setIsbnCode(String isbnCode) {
		this.isbnCode = isbnCode;
	}
}

The DAO class:

AuthorLookupBean.java

package com.mattiz.persistence.data;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.mattiz.persistence.beans.Authors;
import com.mattiz.service.spring.AuthorsBean;

public class AuthorLookupBean {
	private HibernateTemplate hibernateTemplate;

	public AuthorsBean lookupIsbn(String isbn) throws DataAccessException {
		// List l = getHibernateTemplate().find(
		// "from Authors author where author.isbnCode = ?", isbn);//use when
		// isbn is not PK
		Authors author = null;
		author = (Authors) getHibernateTemplate().load(Authors.class, isbn);
		AuthorsBean authorsBean = new AuthorsBean();
		authorsBean.setAuthor(author.getAuthor());
		authorsBean.setIsbnCode(author.getIsbn_Code());
		return authorsBean;
	}

	public void insertAuthor(String isbn, String authorName)
			throws DataAccessException {
		Authors authors = new Authors();
		authors.setAuthor(authorName);
		authors.setIsbn_Code(isbn);
		HibernateTemplate template = getHibernateTemplate();
		template.saveOrUpdate(authors);
		System.out.println("Inserted/Updated Author, ISBN " + authorName + " "
				+ isbn);
	}

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
}

The interface for the DAO:

IAuthorLookupBean

package com.mattiz.persistence.data;

import org.springframework.dao.DataAccessException;
import com.mattiz.service.spring.AuthorsBean;

public interface IAuthorLookupBean {
	public AuthorsBean lookupIsbn(String isbn) throws DataAccessException;

	public void insertAuthor(String isbn, String authorName);
}

The Domain object:

Authors.java

package com.mattiz.persistence.beans;

public class Authors {
	String author;
	String isbn_Code;

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getIsbn_Code() {
		return isbn_Code;
	}

	public void setIsbn_Code(String isbn_Code) {
		this.isbn_Code = isbn_Code;
	}
}

Run AuthorSearchCreateBean.java as a standalone.
The output would be something like this:


Inserted/Updated Author, ISBN Bond 007
AUTHOR IS Bond

I have used a main method in AuthorSearchCreateBean.java to insert/update and retrieve data from the existing database. There is much to be desired. A GUI interface for entering data and displaying data could be developed. You could try a hand at a Swing based data entry/display mechanism to enhance the P-O-C. Good luck!

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Comments are closed.