Friday, July 6, 2012

Creating A Simple Web Application Using Struts 2 and Spring 3.0


In this article we’ll create a simple User Registration form using Struts 2 and configure it with Spring 3.0

Technologies used:
Java 6
Struts 2
Spring 3.0
Maven 3.0

This example application is named ‘CeylonCuisine’. I’m using Maven as the build tool, the pom.xml file including the required libraries will be shown later in this article.

We are applying the MVC pattern:
Model – Java domain object : User
View – JSP file : register.jsp
Controller – Struts 2 Action class : RegisterAction

User.java
package com.ceyloncuisine.domain;

import java.io.Serializable;

public class User implements Serializable {

 private static final long serialVersionUID = 1L;
 private long id;
 private String fname;
 private String lname;
 private char sex;
 private String email;

 public long getId() {
  return id;
 }

 public String getFname() {
  return fname;
 }

 public String getLname() {
  return lname;
 }

 public char getSex() {
  return sex;
 }

 public String getEmail() {
  return email;
 }

 public void setId(long id) {
  this.id = id;
 }

 public void setFname(String fname) {
  this.fname = fname;
 }

 public void setLname(String lname) {
  this.lname = lname;
 }

 public void setSex(char sex) {
  this.sex = sex;
 }

 public void setEmail(String email) {
  this.email = email;
 }

}


Add the above file to src\main\java folder.

We are going to store the User’s first name, last name, sex and email address in database. The code to insert the user details to db is not included in this tutorial.

Now we will create the register.jsp file to present the user with a form to insert required details. With Struts 2 tags , creation of forms is very easy.

Place register.jsp file in src\main\webapp folder.

register.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>

<%@ taglib prefix="s" uri="/struts-tags"%>



Ceylon Cuisine - Register


 

  
  
  
  

  

 



<%@ taglib prefix="s" uri="/struts-tags"%>
We need to include this line in our jsp file in order to use Struts 2 tag libraries.
Now we can begin with ‘<s:’ to use Struts 2 tags as in ‘<s:form action="register">’.

<s:form action="register">
Struts 2 form tag will create a simple form for you. By default the form method will be ‘post’. When the user fills in the form and press the submit button, the ‘register’ action will be called. ‘register’ action is the java controller class which will process the form data.
We have to relate this action to the java controller class by specifying it in the struts.xml configuration file.

<s:textfield name="userBean.fname" label="First Name" />
This will create a text field inside your form. When the user provides input and clicks on the ‘submit’ button, the form data will be sent to the action class.
‘userBean.fname’ is interpreted inside the action class as ‘setUserBean() and setFname()’. Struts 2 will look for a method called setUserBean() and upon the returned object it will then call setFname() with the user provided String value.
Therefore we need to define a variable userBean in the ‘RegisterAction’ class.

RegisterAction.java
package com.ceyloncuisine.action;

import com.ceyloncuisine.domain.User;
import com.ceyloncuisine.mgr.UserMgr;
import com.opensymphony.xwork2.ActionSupport;

public class RegisterAction extends ActionSupport {

 private static final long serialVersionUID = 1L;

 User userBean;

 UserMgr userMgr;

 @Override
 public String execute() throws Exception {
  // Insert user to db
  userMgr.addUser(userBean);
  return SUCCESS;
 }

 public User getUserBean() {
  return userBean;
 }

 public void setUserBean(User userBean) {
  this.userBean = userBean;
 }

 public UserMgr getUserMgr() {
  return userMgr;
 }

 public void setUserMgr(UserMgr userMgr) {
  this.userMgr = userMgr;
 }

}
Place the above file in src\main\java folder.

Struts 2 action classes must extend ActionSupport class which comes with the xwork2 dependent libraries.
‘userBean’ is the model class to which we’ll be storing the information received from the register.jsp as mentioned earlier. Struts 2 framework will create an instance of ‘User’ and assign it to ‘userBean’ using the setter provided in action class.

‘userMgr’ is a service class that will be invoked to insert the User data to database. (The DAO layer operations will be internally called by this)
To inject the dependency for ‘userMgr’ we need Spring configuration. For the moment ignore this part, we’ll be discussing it later.

The execute() method is inherited from ActionSupport class and overridden to invoke service methods after processing form.

Now we’ll configure the struts.xml file to relate this ‘RegisterAction’ class to Register form.

struts.xml


 

  
   /thankyou.jsp
   


 



Save this file in src\main\resources folder.

Using the <action> tag we specify the action name as ‘register’ and relate it to our controller class.
Set the Action’s method as ‘execute’ to indicate this action will look for the execute() method in RegisterAction class and invoke it.

Upon successful invocation of the execute() method, the controller will then load ‘thankyou.jsp’ which will display a thank you note to the user for registering.
Create thankyou.jsp in src\main\webapp folder.

thankyou.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>




Ceylon Cuisine - Thank You


Thank  you for registering with us!





Now most of the application is complete, except for the integration with the services layer to actually insert the user object to database. Also we need to update web.xml file.
This article will not give you information about DAO layer or hibernate configuration, So I will outline only the interfaces here.


UserDao.java
package com.ceyloncuisine.dao;

import com.ceyloncuisine.domain.User;

public interface UserDao {

 public void addUser(User user);

}


UserMgr.java
package com.ceyloncuisine.mgr;

import com.ceyloncuisine.domain.User;

public interface UserMgr {
 
 public void addUser(User user);

}


As I have mentioned earlier, in RegisterAction class, in the execute() method, we call the service bean to persist the user input data.
userMgr.addUser(userBean);
We need to inject ‘userMgr’ bean to our action class using Spring. See below Spring configuration file.

SpringBeans.xml


 
  
 

 
 
 



Save SpringBeans.xml in src\main\resources folder.

Now we need to add few entries to web.xml file. (src\main\webapp\WEB-INF)

web.xml

 CeylonCuisine

 
  struts2
  org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
 

 
  struts2
  /*
 

 
  org.springframework.web.context.ContextLoaderListener
 
 
  contextConfigLocation
  classpath:SpringBeans.xml
 





We need to add a filter class mapping to enable Struts 2 to work with the web application. By specifying ‘/*’ in filter mapping, it indicates that this filter will be applied to all URLs in this web application.

A listener class is required to activate Spring framework on our application. By default the Spring framework looks for a file named ‘applicationContext.xml’ in src\main\webapp\WEB-INF folder to load configuration.
In this example, I have my Spring configuration saved in ‘SpringBeans.xml’ in src\main\resources folder. So have given the path to this using <context-param> tags.

Run ‘mvn clean install’ to compile the project and create the WAR file. Deploy this in your web server. (I use Tomcat)
Run your application by typing the below URL in your browser.

http://localhost:8080/CeylonCuisine/register.jsp


The pom.xml file with the required libraries is shown below.


 4.0.0
 CeylonCuisine
 CeylonCuisine
 0.0.1-SNAPSHOT
 war
 CeylonCuisine

 
  
   Java.Net
   http://download.java.net/maven/2/
  

  
   com.springsource.repository.bundles.release
   SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases
   http://repository.springsource.com/maven/bundles/release
  
  
   com.springsource.repository.bundles.external 
   SpringSource Enterprise Bundle Repository - External Bundle Releases
   http://repository.springsource.com/maven/bundles/external
  

 
 
  
  
   org.springframework
   org.springframework.core
   3.1.1.RELEASE
  

  
   org.springframework
   org.springframework.beans
   3.1.1.RELEASE
  

  
  
   asm
   asm
   3.3.1
  

  
  
   org.apache.struts
   struts2-spring-plugin
   2.3.4
  

  
  
   org.apache.struts
   struts2-core
   2.3.4
  
 

4 comments:

  1. Could you please me in this. The below mentioned update query transaction is not getting roll backed. Any thing I'm missing here ?

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:test_context.xml")
    @ActiveProfiles("dev")
    public class ControllerTest{

    @Autowired
    public void setDataSource(DataSource dataSource){
    this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Test
    @Rollback
    public void testDivision() throws Exception {
    String query = "UPDATE Customer SET Join_date = SYSDATE WHERE ROWNUM = 1";
    jdbcTemplate.update(query);
    query = "SELECT * from Customer WHERE Join_date IS NOT NULL AND ROWNUM = 1";
    request.setRequestURI("/customer/getDivision.action");
    List mrktDivisionList= jdbcTemplate.query(query,new DivisionMapper());
    Division mrktDivision = new Division();

    if(mrktDivisionList.size() > 0){
    mrktDivision = mrktDivisionList.get(0);
    }
    Assert.assertNotNull (mrktDivision.getDivisionName());
    Assert.assertNotNull(mrktDivision.getDivisionKey());
    Assert.assertNotNull(mrktDivision.getDivisionDate());
    }

    }

    ReplyDelete
    Replies
    1. Could you try with @Rollback(true) ?
      (in your code example I don't see the value set)

      Delete
  2. hello
    your apps is good and very useful for all learner and i want tell you what is the benefit to use maven in spite of using simple way..i mean without use maven...thnks

    ReplyDelete
    Replies
    1. Thanks Mugeesh.

      Maven is a build tool, and it makes things easier when compiling, linking and packaging the source files. You can run a small project without a build tool, but when the project grows it will be very difficult to keep track of the files you would want to link.
      In the above example, u can see that all required artifacts are listed in the pom.xml file. Once the project is building these artifacts will be checked and downloaded if anything is missing. This is lot easier for the developer than manually adding them.
      Therefore it's always advisable to use a build tool. (Most used build tools are Maven and Ant)

      Delete