Native Dependency Injection in Struts2

Struts2 Native Dependency Injection

Struts2 provides support for Dependency injection. You may use DI containers like “Spring” in your Struts2 application, or may use Native Dependency Injection available in Struts2 (XWork2) framework. It’s based on Google’s “guice” (both being made by same person).

In this sample application, I have made Two Action classes:

  1. AddProductAction           To Add new product
  2. ListProductAction            To List all products

Both actions are dependent on a “Business” class  : ProductManager. Instead of creating instance of ProductManager in each action class, I have created its instance through “bean” element in “struts.xml”.

<bean class="com.mahendra.ProductManager" name="man" />

The ObjectFactory available in Struts2 will create instance of ProductManager using default constructor and is made available to all other components using name : “man”.

Every Action class needs to have property of type “ProductManager” along with annotation:

@Inject("man")
private ProductManager manager;
// This method is used for Injecting Object
public void setManager(ProductManager manager) {
this.manager = manager;
}

Now, lets create an application.

Requirements:

  1. Java SDK 1.6 (or newer)
  2. Eclipse helios (or newer)
  3. Apache Tomcat 6.0 (or 7.0)
  4. Struts 2.1.x from apache

Steps to create application:

  1. Create new Dynamic Web Application.
  2. Copy all required JAR’s inside “web-inf/lib” folderJARS required:
    commons-fileupload
    commons-io
    commons-lang
    freemarker
    javassist
    ognl
    jstl (For JSTL Core Tags)
    struts2-core
    xwork-core
    
  3. Modify your “web.xml” to have Struts2 dispatcher filter.
    <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher
    </filter-class>
    </filter>
    <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    
  4. Create new “struts.xml” in your source folder:
    <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
    <struts><bean class="com.mahendra.ProductManager"
    name="man" />
    
    <package name="p1" extends="struts-default"
    namespace="">
    <action name="add"
    class="com.mahendra.AddProductAction">
    <result type="redirectAction">list</result>
    </action> 
    
    <action name="list"
    class="com.mahendra.ListProductAction">
    <result>list.jsp</result>
    </action>
    </package>
    
    </struts>
    
  5. Create Model class : Product
    package com.mahendra;
    public class Product {
    
    private String name;
    private String description;
    private double price;
    
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getDescription() {
    return description;
    }
    public void setDescription(String description) {
    this.description = description;
    }
    public double getPrice() {
    return price;
    }
    public void setPrice(double price) {
    this.price = price;
    }
    
    public Product(String name, String description, double price) {
    super();
    this.name = name;
    this.description = description;
    this.price = price;
    }
    
    public Product() {
    super();
    }
    
    }
    
  6. Shared “Business” class :
    ProductManager

    package com.mahendra;
    
    import java.util.*;
    
    public class ProductManager {
    private List<Product> products;
    
    public ProductManager() {
    System.out.println("Creating new manager...");
    products = new LinkedList<Product>();
    System.out.println("Empty Product list generated");
    }
    
    public void add(Product p) {
    products.add(p);
    }
    
    public Product search(String name) {
    Product p = null;
    for (int i = 0; i < products.size(); i++) {
    if (products.get(i).getName().equals(name)) {
    p = products.get(i);
    break;
    }
    }return p;
    }
    
    public void delete(String name) {
    Product p = search(name);
    if (p != null) {
    products.remove(p);
    }
    }
    
    public List<Product> getProducts() {
    return products;
    }
    
    public void setProducts(List<Product> products) {
    this.products = products;
    }
    }
    
  7. Create First Action class to add new product: AddProductAction
    package com.mahendra;
    import com.opensymphony.xwork2.ActionSupport;
    import com.opensymphony.xwork2.inject.Inject;
    public class AddProductAction extendsActionSupport {
    @Inject("man")
    private ProductManager manager;
    private Product product;
    public String execute() {
    manager.add(product);
    return SUCCESS;
    }
    public ProductManager getManager() {
    return manager;
    }
    
    // This method is used for Injecting Object
    public void setManager(ProductManager manager) {
    this.manager = manager;
    }
    
    public Product getProduct() {
    return product;
    }
    
    public void setProduct(Product product) {
    this.product = product;
    }
    }
    
  8. Create another action class to List all products: ListProductAction
    import java.util.List;
    import com.opensymphony.xwork2.inject.Inject;
    
    public   class ListProductAction {
    
    @Inject("man")// requires setter 
    private ProductManager manager; 
    private List<Product> productList;
    
    public  String execute() {
    setProductList(manager.getProducts());
    return "success";
    }
    
    public  ProductManager getManager() {
     return  manager;
    }
    
    public void  setManager(ProductManager manager) {
    this.manager = manager;
    }
    
    public  List<Product> getProductList() {
     return  productList;
    }
    
    public void setProductList(List<Product> productList) {
     this.productList = productList;
    }
    }
    
  9. Create new JSP page “index.jsp” and add following line to load “list” action.
    <% response.sendRedirect("list.action"); %>
    
  10. Create new JSP page “list.jsp” and add following lines to render form and list.
    <%@ taglib uri= "/struts-tags"  prefix= "s"%>
    <html>
    <head>
    <meta http-equiv= "Content-Type"  content= "text/html;charset=ISO-8859-1" >
    <title>Struts2 Dependency Demo</title>
    </head>
    <body>
    
    <s:form action="add"  method="post" >
    <s:textfield name= "product.name" label= "Name of product" />
    <s:textfield name= "product.description" label= "Description"/>
    <s:textfield name= "product.price" label= "Product Price"  />
    <s:submit value= "Save"  />
    </s:form>
    
    <h2>Available Products</h2>
    <table>
    <tr>
    <td>Product Name</td>
    <td>Description</td>
    <td>Price</td>
    </tr>
    <s:iterator value= "productList"  var= "p" >
    <tr>
    <td>${p.name }</td>
    <td>${p.description }</td>
    <td>${p.price }</td>
    </tr>
    </s:iterator>
    </table>
    </body>
    </html>
    

Simple Blog type web-application using Struts+Hibernate+MySql

  1. Create table in database “mahendra”

create table blogEntry

(

blogid int primary key auto_increment,

username varchar(35)not null,

emailid varchar(60)not null,

message varchar(1000),

edate timestamp default now()

);

  1. Create new Dynamic Web Application using eclipse.
  2. Add required libraries into “lib” folder.
  3. Modify “web.xml” fileà add following lines:

<filter>

<filter-name>mahendra</filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

</filter>

<filter-mapping>

<filter-name>mahendra</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

  1. Create new JSP page inside “WebContent”à index.jsp
  2. Run your application for testing
  3. Create new “Source Folder” with name : “resources”
  4. Add new File with name: log4j.properties with following contents:

log4j.rootLogger = DEBUG, CA, FA

log4j.appender.CA = org.apache.log4j.ConsoleAppender

log4j.appender.CA.layout = org.apache.log4j.PatternLayout

log4j.appender.CA.ConversionPattern=%-5p %c %x {%m} %n

log4j.appender.FA = org.apache.log4j.FileAppender

log4j.appender.FA.layout = org.apache.log4j.PatternLayout

log4j.appender.FA.File=./sample.log

log4j.appender.FA.ConversionPattern=%-4r [%t] %-5p %c %x – %m%n

  1. Add new XML file with name “struts.xml” with following contents

<!DOCTYPE struts PUBLIC

“-//Apache Software Foundation//DTD Struts Configuration 2.0//EN”

http://struts.apache.org/dtds/struts-2.0.dtd&#8221;

>

<struts>

<package name=“default” extends=“struts-default” namespace=“”>

<action name=“review” class=“com.mahendra.ReviewsAction” method=“list”>

<result>/WEB-INF/pages/reviews.jsp</result>

<result name=“error”>/WEB-INF/pages/reviews.jsp </result>

</action>

<action name=“add_review” class=“com.mahendra.ReviewsAction” method=“add”>

<result name=“success” type=“chain”>review</result>

<result name=“error”>/WEB-INF/pages/reviews.jsp </result>

</action>

</package>

</struts>

  1. Create new class called “Reviews” (Model component)

package com.mahendra;

import java.sql.Timestamp;

import javax.persistence.*;

@Entity

@Table(name=”blogentry”)

public class Reviews implements java.io.Serializable{

private static final long serialVersionUID = 1L;

private int blogid;

private String username;

private String emailid;

private String message;

private Timestamp edate;

@Id

@GeneratedValue

public int getBlogid() {

return blogid;

}

public void setBlogid(int blogid) {

this.blogid = blogid;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getEmailid() {

return emailid;

}

public void setEmailid(String emailid) {

this.emailid = emailid;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

public Timestamp getEdate() {

return edate;

}

public void setEdate(Timestamp edate) {

this.edate = edate;

}

public Reviews(int blogid, String username, String emailid, String message

) {

super();

this.blogid = blogid;

this.username = username;

this.emailid = emailid;

this.message = message;

}

public Reviews() {

super();

}

}

  1. Create new class called “HibernateUtils” :

package com.mahendra;

import org.hibernate.*;

import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtils {

private static SessionFactory sessionFactory = buildFactory();

private static SessionFactory buildFactory(){

try{

return new AnnotationConfiguration().configure().buildSessionFactory();

}catch(Exception ex){

throw new ExceptionInInitializerError(“Unable to initialize session factory”);

}

}

public static SessionFactory getSessionFactory(){

return sessionFactory;

}

public static Session getSession()

{

return sessionFactory.getCurrentSession();

}

}

  1. Create new class “ReviewsManager”

package com.mahendra;

import java.util.List;

import org.hibernate.HibernateException;

import org.hibernate.*;

public class ReviewsManager {

@SuppressWarnings(“unchecked”)

public List<Reviews> getAllReviews(){

Session session = HibernateUtils.getSession();

List<Reviews> list = null;

Transaction tran = null;

try{

tran = session.beginTransaction();

list = (List<Reviews>)session.createQuery(“from Reviews”).list();

tran.commit();

}catch(HibernateException he){

tran.rollback();

throw new MyException(“Unable to retrieve list of Reviews”,he.getMessage());

}

return list;

}

public void addReview(Reviews review){

Session session = HibernateUtils.getSession();

Transaction tran = null;

try{

tran = session.beginTransaction();

session.save(review);

tran.commit();

}catch(HibernateException he){

throw new MyException(“Unable to add your review.”,he.getMessage());

}

}

}

  1. Create new Exception with name “MyException”

package com.mahendra;

public class MyException extends RuntimeException {

String technicalDetails;

public MyException() {

// TODO Auto-generated constructor stub

}

public MyException(String arg0) {

super(arg0);

// TODO Auto-generated constructor stub

}

public MyException(String arg0, String arg1) {

super(arg0);

technicalDetails = arg1;

}

public String getTechnicalDetails(){

return technicalDetails;

}

}

  1. Create “ReviewAction” (Action compoenet)

package com.mahendra;

import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

public class ReviewsAction extends ActionSupport{

private static final long serialVersionUID = 1L;

private ReviewsManager rman = null;

private Reviews review = null;

private List<Reviews> reviewList = null;

public ReviewsAction(){

rman = new ReviewsManager();

}

public String list()

{

try{

reviewList = rman.getAllReviews();

return “success”;

}catch(ExceptionInInitializerError ex){

addActionMessage(“Could not connect with database”);

addActionError(“ERROR: “+ex.getMessage());

return “error”;

}catch(MyException me){

addActionMessage(me.getMessage());

addActionError(me.getTechnicalDetails());

return “error”;

}

}

public String add(){

try{

rman.addReview(getReview());

return “success”;

}catch(MyException me){

addActionMessage(me.getMessage());

addActionError(me.getTechnicalDetails());

return “error”;

}

}

public Reviews getReview() {

return review;

}

public void setReview(Reviews review) {

this.review = review;

}

public List<Reviews> getReviewList() {

return reviewList;

}

public void setReviewList(List<Reviews> reviewList) {

this.reviewList = reviewList;

}

}

  1. Create new JSP page :  /WEB-INF/pages/reviews.jsp

<%@ 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”&gt;

<%@taglib uri=http://java.sun.com/jsp/jstl/core&#8221;  prefix=“c”%>

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

<html>

<head>

<meta http-equiv=“Content-Type” content=“text/html; charset=ISO-8859-1”>

<title>Insert title here</title>

</head>

<body>

list of reviews

<c:if test=${reviewList != null }>

<c:forEach items=${reviewList} var=“review”>

<table border=“1” width=“300” align=“right”>

<tr>

<td width=“100”>${review.blogid}</td>

<td>by ${review.username}</td>

<td>EMail: ${review.emailid}</td>

</tr>

<tr>

<td>Message: </td>

<td colspan=“2”>

${review.message }

</td>

</tr>

<tr>

<td colspan=“3” align=“right”>

recorder at : ${review.edate}

</td>

</tr>

</table> <br/>

</c:forEach>

</c:if>

<c:if test=“{reviewList is empty}”>

No reviews found!<br/>

Be First to add review..!

</c:if>

<s:form action=“add_review” method=“POST”>

<s:textfield name=“review.username” label=“Your name: “>

</s:textfield><br/>

<s:textfield name=“review.emailid” label=“Your Email ID:”></s:textfield><br/>

<s:textarea name=“review.message” label=“Your views:” rows=“4” cols=“40”>

</s:textarea><br/>

<s:submit value=“Submit”></s:submit>

</s:form>

<s:actionmessage/>

<font face=“Tahoma” size=“2” color=“red”>

<s:actionerror/>

</font>

</body>

</html>

  1. Create new JSP page index.jsp

<%@ 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”&gt;

<html>

<head>

<meta http-equiv=“Content-Type” content=“text/html; charset=ISO-8859-1”>

<title>Home page: Mahendra’s Blog</title>

</head>

<body>

<h2>Some topic…..</h2>

<p>

Some details here…..

</p>

<a href=“reviews”>View / Add Reviews</a>

</body>

</html>