Monday, October 8, 2012

Spring MVC, Security + Hibernate + DWR - Page 3



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

OK, time for DWR ;)

the DWR servlet and Spring configuration:

in you web.xml edit the line to add a new file called dwr-context.xml
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/hibernate-context.xml,/WEB-INF/dwr-context.xml</param-value>
and add the DWR servlet and associate it with /dwr/* requests.
<servlet>
	<servlet-name>dwr</servlet-name>
	<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
	<init-param>
		<param-name>debug</param-name>
		<param-value>true</param-value>
	</init-param>
</servlet>
<servlet-mapping>
	<servlet-name>dwr</servlet-name>
	<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

dwr-context.xml:

under /WEB-INF create a new file called dwr-context.xml, the file will configure the integration points between Spring and DWR.
<?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:dwr="http://www.directwebremoting.org/schema/spring-dwr"
       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.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

       <dwr:configuration />
       <dwr:annotation-config id="dwrAnnotationConfig"/>
       <dwr:annotation-scan base-package="com.mtz.spring.dto"/>

</beans>
this file defines three configurations:
1- a default dwr configuration: the default configurations is fine as we are relying mostly on annotatios.
2- annotation config: DWR will scan spring beans for certain annotations.
3- annotation scan: DWR will scan the class path for certain annotations.


simply, if you have service class and want this service to be exposed to dwr you have two options, either, create a spring bean or let dwr scan its path, both ways, those classes had to have certain annotations.

the User class

as the User is under the package com.mtz.spring.dto and no Spring beans were (and mostly will never) created from that class, we need DWR to scan the classes under this package.
the class has been mentioned before, what needs to be explained
@DataTransferObject: DWR will marshal and unmarshal this object using a certain converter, in our example it is type="hibernate3", converter=H3BeanConverter.class, also for each property you need on the javascript object you have to expose it using the annotation @RemoteProperty

DAO and Service

in the package com.mtz.spring.dao

create the interface UserDAO

package com.mtz.spring.dao;

import com.mtz.spring.dto.User;
import java.util.List;

/**
 *
 * @author salemmo
 */
public interface UserDAO {
    public User getUser(int id);
    public User addUser(User user);
    public User removeUser(User user);
    public List<User> getAllUsers();
}

in the package com.mtz.spring.dao

create the class UserDAOImpl

package com.mtz.spring.dao;

import com.mtz.spring.dto.User;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

/**
 *
 * @author salemmo
 */
public class UserDAOImpl implements UserDAO{

    public User getUser(int id) {
        Session session = sessionFactory.getCurrentSession();
        User u = (User) session.get(User.class, id);
        return u;
    }

    public User addUser(User user) {
        Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(user);
        return user;
    }

    public User removeUser(User user) {
        Session session = sessionFactory.getCurrentSession();
        session.delete(user);
        return user;
    }

    public List<User> getAllUsers() {
        Session session = sessionFactory.getCurrentSession();
        return session.createQuery("from User").list();
    }
    
    private SessionFactory sessionFactory;
    /**
     * @return the sessionFactory
     */
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    /**
     * @param sessionFactory the sessionFactory to set
     */
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    
}
in the package com.mtz.spring.service

create the interface UserService

package com.mtz.spring.service;

import com.mtz.spring.dto.User;
import java.util.List;

/**
 *
 * @author salemmo
 */
public interface UserService {
    public User getUser(int id);
    public User addUser(User user);
    public User removeUser(User user);
    public List<User> getAllUsers();
}
in the package com.mtz.spring.service

create the class UserServiceImpl

package com.mtz.spring.service;

import com.mtz.spring.dao.UserDAO;
import com.mtz.spring.dto.User;
import java.util.List;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author salemmo
 */
@RemoteProxy
public class UserServiceImpl implements UserService{

    
    @RemoteMethod
    @Transactional
    public User getUser(int id) {
        return getUserDAO().getUser(id);
    }

    @Transactional
    @RemoteMethod
    public User addUser(User user) {
        return getUserDAO().addUser(user);
    }
    
    @Transactional
    @RemoteMethod
    public User removeUser(User user) {
        return getUserDAO().removeUser(user);
    }

    @Transactional
    @RemoteMethod
    public List<User> getAllUsers() {
        return getUserDAO().getAllUsers();
    }
    
    private UserDAO userDAO;

    /**
     * @return the userDAO
     */
    public UserDAO getUserDAO() {
        return userDAO;
    }

    /**
     * @param userDAO the userDAO to set
     */
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    
}

the important things to know about the UserServiceImpl are the annotations.
@RemoteProxy: tells DWR that you want this service to be exposed.
@RemoteMethod: tells DWR that you want this method to be exposed.
@Transactional: tells hibernate that you want this method to run in transaction.

Wrap it up in the applicationContext.xml

edit your applicationContext.xml to add the service bean
<bean class="com.mtz.spring.dao.UserDAOImpl" id="userDAO">
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean class="com.mtz.spring.service.UserServiceImpl" id="userService">
	<property name="userDAO" ref="userDAO"/>
</bean>

edit hello.jsp

edit /WEB-INF/jsp/hello.jsp to make use of DWR
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

	<%
		String contextPath=request.getContextPath();
	%>
	
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type='text/javascript' src='<%=contextPath%>/dwr/engine.js'></script>
        <script type='text/javascript' src='<%=contextPath%>/dwr/interface/UserServiceImpl.js'></script>
        <script type='text/javascript' src='<%=contextPath%>/dwr/util.js'></script>
        <title>Welcome to Spring Web MVC project</title>
        <script type="text/javascript">
            function goGetit(){
                UserServiceImpl.getUser(document.getElementById("userid").value, {
                    callback:function(user) { 
                        document.getElementById("userage").value=user.age;
                        document.getElementById("username").value=user.name;
                    }
                });
            }
            
            function goSaveit(){
                var user= {
                    id: document.getElementById("userid").value,
                    age:document.getElementById("userage").value,
                    name:document.getElementById("username").value
                };
                UserServiceImpl.addUser(user, {
                    callback:function(user) { 
                        var useraction = (document.getElementById("userid").value=="")? "added":"altered";
                        document.getElementById("message").innerHTML = "User "+useraction+" with the ID: "+user.id;
                        getAllUsers();
                    }
                });
            }
            
            function goRemoveit(){
                var user= {
                    id: document.getElementById("userid").value
                };
                UserServiceImpl.removeUser(user, {
                    callback:function(user) { 
                        document.getElementById("userid").value="";
                        document.getElementById("userage").value="";
                        document.getElementById("username").value="";
                        document.getElementById("message").innerHTML = "User removed with the ID: "+user.id;
                        getAllUsers();
                    }
                });
            }
            
            function getAllUsers(){
                
                UserServiceImpl.getAllUsers({
                    callback:function(users) {
                        var cellFunctions = [
                            function(user) { return user.id; },
                            function(user) { return user.age; },
                            function(user) { return user.name; }
                        ];
                        dwr.util.removeAllRows("allusers");
                        dwr.util.addRows( "allusers", users, cellFunctions,{ escapeHtml:false });
                    }
                });
            }
        </script>
    </head>

    <body onload="getAllUsers()">
        <H2>Hello! This is the default welcome page for a Spring Web MVC project.</H2>
        <h3>${message}<h3/>
            <input type="text" id="userid"><input type="button" value="Get User By ID" onclick="goGetit();"/>
            <hr width="70%"/>
            <div id="message"> </div>
            <table>
                <tr>
                    <td>Age:</td>
                    <td><input type="text" id="userage"></td>
                </tr>
                <tr>
                    <td>Name:</td>
                    <td><input type="text" id="username"></td>
                </tr>
                <tr>
                    <td><input type="button" value="Add/Edit User" onclick="goSaveit();"/></td>
                    <td><input type="button" value="Remove User" onclick="goRemoveit();"/></td>
                </tr>
            </table>
            <hr width="70%"/>
            <table border="1">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Age</th>
                        <th>Name</th>
                    </tr>
                </thead>
                <tbody id="allusers"> </tbody>
            </table>
    </body>
</html>

Test it

deploy the project and you should see the following page


Next - Configuring Spring Security