Sunday, October 7, 2012

Spring MVC, Security + Hibernate + DWR - Page 2


Spring MVC, Security + Hibernate + DWR, Let's PLay

OK, our Spring MVC should be working by now, let's add Hibernate ;)

create a table with the following specifications

MySQL table SQL script:


CREATE TABLE `user_` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) DEFAULT NULL,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

now, configure your spring context to load a new file called hibernate-context.xml. edit your web.xml to add the mentioned file
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/hibernate-context.xml</param-value>

hibernate-context.xml:

create a new file called hibernate-context.xml under /WEB-INF with the following content
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
		p:location="/WEB-INF/jdbc.properties" />

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource"
		p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}"
		p:username="${jdbc.username}" p:password="${jdbc.password}" />

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

		<property name="dataSource">
			<ref bean="dataSource" />
		</property>

		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>

		<property name="annotatedClasses">
			<list>
				<value>com.mtz.spring.dto.User</value>
			</list>
		</property>

	</bean>

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager"
		p:sessionFactory-ref="sessionFactory" />

	<tx:annotation-driven />

</beans>
basically, this file defines the following:
propertyConfigurer: spring will look for a properties file called jdbc.properties to replace the place holders mentioned here which are related to the database connection arguments.
dataSource: the datasource object will be used by the Hibernate session factory to connect to the database.
sessionFactory: the session factory that will be used by Hibernate, and it defines an attribute called annotatedClasses which are Hibernate mapping objects
transactionManager: we define this bean so we can be able to do database queries in transactions. Transaction Annotations: we will configure transactions via annotations.
alternatively, you can configure the session factory to scan the class path
<property name="packagesToScan" value="com.mtz.spring.dto"/>

jdbc.properties:

under /WEB-INF create a new file named jdbc.properties with the following content, please edit for your test
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root

the User class

under the package com.mtz.spring.dto create a file named User.java
package com.mtz.spring.dto;

import java.io.Serializable;
import javax.persistence.*;
import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;
import org.directwebremoting.hibernate.H3BeanConverter;
/**
 *
 * @author salemmo
 */
@DataTransferObject(type="hibernate3", converter=H3BeanConverter.class)
@Entity
@Table(name="user_", catalog="spring")
public class User implements Serializable{
    @RemoteProperty
    private String name;
    @RemoteProperty
    private int age;
    @RemoteProperty
    private int id;

    /**
     * @return the name
     */
    @Column(name="name")
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the age
     */
    @Column(name="age")
    public int getAge() {
        return age;
    }

    /**
     * @param age the age to set
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * @return the id
     */
    @Id
    @GeneratedValue(strategy=javax.persistence.GenerationType.IDENTITY)
    @Column(name="id")
    public int getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }
}
here we define the mapping between this class and the database table using the annotations @Entity, @Table @Column and ID specific annotations (don't give so much attention to the @DataTransferObject and @RemoteProperty as they will be used by DWR later on)

OpenSssionInView Filter

we don't want to open session manually and maybe forget to close them, can we do it automatically? also, i have a lazy initialized property can't use it in my JSPs because the object sent to the view was de-attached from the Hibernate context. Well, Hibernate has a Filter called OpenSssionInView Filter that will solve both problems, and indeed, Spring has wrapped this filter. to enable this filter edit your web.xml to add
<filter>
	<filter-name>hibernateFilter</filter-name>
	<filter-class>
		org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
	</filter-class>
	<init-param>
		<param-name>sessionFactoryBeanName</param-name>
		<param-value>sessionFactory</param-value>
	</init-param>
</filter>

<filter-mapping>
	<filter-name>hibernateFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
of course the filter needs one session factory to create sessions.

Test it

no changes are expected, still we see our page, however, make sure that you did it right by not seeing any exceptions in the logs.

Next - Configuring DWR