Meyyappan has posted 101 posts at DZone. View Full User Profile

Struts 2 CRUD Tutorial

06.15.2012
| 77175 views |
  • submit to reddit

In this example you will see how to perform Create, Read, Update and Delete (CRUD) operations. I will be explaining only the points that is not covered in the previous examples.

Let's get started, the screen shot of the example is shown below.

You will have options to edit and delete in addition to the one we saw before. ( Struts 2 Hibernate Integration )

The directory structure of the example.

Let's see the flow from the back-end.

The UserDAOImpl has four methods to perform the various CRUD operations.

package com.vaannila.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;
import com.vaannila.domain.User;

public class UserDAOImpl implements UserDAO {
	
	@SessionTarget
	Session session;
	
	@TransactionTarget
	Transaction transaction;

	/**
	 * Used to save or update a user.
	 */
	@Override
	public void saveOrUpdateUser(User user) {
		try {
			session.saveOrUpdate(user);
		} catch (Exception e) {
			transaction.rollback();
			e.printStackTrace();
		}
	}

	/**
	 * Used to delete a user.
	 */
	@Override
	public void deleteUser(Long userId) {
		try {
			User user = (User) session.get(User.class, userId);
			session.delete(user);
		} catch (Exception e) {
			transaction.rollback();
			e.printStackTrace();
		} 
	}
	
	/**
	 * Used to list all the users.
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<User> listUser() {
		List<User> courses = null;
		try {
			courses = session.createQuery("from User").list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return courses;
	}

	/**
	 * Used to list a single user by Id.
	 */
	@Override
	public User listUserById(Long userId) {
		User user = null;
		try {
			user = (User) session.get(User.class, userId);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return user;
	}

}

The org.hibernate.Session and org.hibernate.Transaction objects are injected using the Full Hibernate Plug-in 1.4 GA.

The User domain object with the JPA annotations to create the USER table.

package com.vaannila.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="USER")
public class User {

	private Long id;
	private String name;
	private String gender;
	private String country;
	private String aboutYou;
	private Boolean mailingList;
	
	@Id
	@GeneratedValue
	@Column(name="USER_ID")	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	
	@Column(name="USER_NAME")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@Column(name="USER_GENDER")
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	
	@Column(name="USER_COUNTRY")
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	
	@Column(name="USER_ABOUT_YOU")
	public String getAboutYou() {
		return aboutYou;
	}
	public void setAboutYou(String aboutYou) {
		this.aboutYou = aboutYou;
	}
	
	@Column(name="USER_MAILING_LIST")
	public Boolean getMailingList() {
		return mailingList;
	}
	public void setMailingList(Boolean mailingList) {
		this.mailingList = mailingList;
	}

}

Our UserAction implements ModelDriven interface, so the domain object User will be exposed as a model object. Use ActionContext.getContext().get(ServletActionContext. HTTP_REQUEST) method to access the HttpServeletRequest object in action.

package com.vaannila.web;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.vaannila.dao.UserDAO;
import com.vaannila.dao.UserDAOImpl;
import com.vaannila.domain.User;

public class UserAction extends ActionSupport implements ModelDriven<User> {

	private static final long serialVersionUID = -6659925652584240539L;

	private User user = new User();
	private List<User> userList = new ArrayList<User>();
	private UserDAO userDAO = new UserDAOImpl();
	
	@Override
	public User getModel() {
		return user;
	}
	
	/**
	 * To save or update user.
	 * @return String
	 */
	public String saveOrUpdate()
	{	
		userDAO.saveOrUpdateUser(user);
		return SUCCESS;
	}
	
	/**
	 * To list all users.
	 * @return String
	 */
	public String list()
	{
		userList = userDAO.listUser();
		return SUCCESS;
	}
	
	/**
	 * To delete a user.
	 * @return String
	 */
	public String delete()
	{
		HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get( ServletActionContext.HTTP_REQUEST);
		userDAO.deleteUser(Long.parseLong( request.getParameter("id")));
		return SUCCESS;
	}
	
	/**
	 * To list a single user by Id.
	 * @return String
	 */
	public String edit()
	{
		HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get( ServletActionContext.HTTP_REQUEST);
		user = userDAO.listUserById(Long.parseLong( request.getParameter("id")));
		return SUCCESS;
	}
	
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public List<User> getUserList() {
		return userList;
	}

	public void setUserList(List<User> userList) {
		this.userList = userList;
	}

}

In the struts configuration file we have four different actions corresponding to the different CRUD operations. During the save, update and delete operations, we need to update the list of users displayed below so we redirect the result to the listUser acion.

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
	<package name="default" extends="hibernate-default">
		<action name="saveOrUpdateUser" method="saveOrUpdate" class="com.vaannila.web.UserAction">
			<result name="success" type="redirect">listUser</result>
		</action>
		<action name="listUser" method="list" class="com.vaannila.web.UserAction">
			<result name="success">/register.jsp</result>
		</action>
		<action name="editUser" method="edit" class="com.vaannila.web.UserAction">
			<result name="success">/register.jsp</result>
		</action>
		<action name="deleteUser" method="delete" class="com.vaannila.web.UserAction">
			<result name="success" type="redirect">listUser</result>
		</action>
	</package>
</struts>

The hibernate.cfg.xml file contains the following configuration.

<?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>
		<property name="hibernate.connection.driver_class"> org.hsqldb.jdbcDriver </property>
		<property name="hibernate.connection.url"> jdbc:hsqldb:hsql://localhost </property>
		<property name="hibernate.connection.username">sa</property>
		<property name="connection.password"></property>
		<property name="connection.pool_size">1</property>
		<property name="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </property>
		<property name="show_sql">true</property>
		<property name="hbm2ddl.auto">create</property>
		<mapping class="com.vaannila.domain.User" />
	</session-factory>
</hibernate-configuration>

The deployment descriptor contains the following configuration.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Struts2Example19</display-name>
  <filter>
		<filter-name>struts2</filter-name>
		<filter-class>
			org.apache.struts2.dispatcher.ng.filter. StrutsPrepareAndExecuteFilter </filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

In the register.jsp page we use the Struts 2 tags to display the form elements.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Page</title>
<s:head />
<style type="text/css">
@import url(style.css);
</style>
</head>
<body>
<s:form action="saveOrUpdateUser">
	<s:push value="user">
		<s:hidden name="id" />
		<s:textfield name="name" label="User Name" />
		<s:radio name="gender" label="Gender" 
        	list="{'Male','Female'}" />
		<s:select name="country" list="{'India','USA','UK'}" 
        	headerKey="" headerValue="Select" 
            label="Select a country" />
		<s:textarea name="aboutYou" label="About You" />
		<s:checkbox name="mailingList"
			label="Would you like to join our mailing list?" />
		<s:submit />
	</s:push>
</s:form>

<s:if test="userList.size() > 0">
	<div class="content">
	<table class="userTable" cellpadding="5px">
		<tr class="even">
			<th>Name</th>
			<th>Gender</th>
			<th>Country</th>
			<th>About You</th>
			<th>Mailing List</th>
			<th>Edit</th>
			<th>Delete</th>
		</tr>
		<s:iterator value="userList" status="userStatus">
			<tr
				class="<s:if test="#userStatus.odd == true ">odd</s:if> <s:else>even</s:else>">
				<td><s:property value="name" /></td>
				<td><s:property value="gender" /></td>
				<td><s:property value="country" /></td>
				<td><s:property value="aboutYou" /></td>
				<td><s:property value="mailingList" /></td>
				<td>
                <s:url id="editURL" action="editUser">
					<s:param name="id" value="%{id}"></s:param>
				</s:url>
                <s:a href="%{editURL}">Edit</s:a>
                </td>
				<td>
                <s:url id="deleteURL" action="deleteUser">
					<s:param name="id" value="%{id}"></s:param>
				</s:url>
                <s:a href="%{deleteURL}">Delete</s:a>
                </td>
			</tr>
		</s:iterator>
	</table>
	</div>
</s:if>
</body>
</html>

The push tag is used to move the object to the top of the ValueStack. During add operation we will refer to the model object User exposed by the ModelDriven inteface, in this case the push tag is not necessary. But during update operation we refer to the JavaBean property user that is returned by the listUserById() method, now the push tag will be useful, it pushes the User object to the top of the ValueStack so we need not use the second-level OGNL expression language like user.name to access the domain object properties.

public String edit()
{
    HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get( ServletActionContext.HTTP_REQUEST);
    user = userDAO.listUserById(Long.parseLong(request. getParameter("id")));
    return SUCCESS;
}

The url tag is used to create a new URL. Along with the URL we append the id value, this can be done using the param tab. In the OGNL expression language we use "%{}" as the escape sequence to refer a value on the ActionContext.

You can download and try the Struts 2 CRUD Example here.

Source :Download (16 KB)
Source + Lib :Download (9.8 MB)



Published at DZone with permission of its author, Meyyappan Muthuraman.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Kuong Knight replied on Tue, 2014/04/01 - 2:03pm

thank you!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.