Spring's Struts integration

Spring MVC relies on DispatcherServlet, which sends requests to controllers that are configurable mapping handlers with view and theme resolution. In Struts, the controller's name is Action. While Action instances will be instantiated for every request in Struts 2 to tackle the thread safety issue, Spring MVC creates controllers once, and each controller's instance serves all requests.

To enable Spring integration with Struts 2, Struts provides struts2-spring-plugin. In Struts 2.1, Struts introduced the convention plugin (struts2-convention-plugin), which simplified the creation of Action classes (by annotation) without any configuration file (struts.xml). The plugin expects a set of naming conventions for the Action class, package, and view naming that will be explained in this section.

To integrate Struts 2 with Spring, you need to add these dependencies:

<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-core</artifactId>
  <version>2.3.20</version>
</dependency>
<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-spring-plugin</artifactId>
  <version>2.3.20</version>
</dependency>
<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-convention-plugin</artifactId>
  <version>2.3.20</version>
</dependency>

The struts2-convention-plugin plugin searches for packages with the strings "struts", "struts2", "action", or "actions", and detects Action classes either whose names end with Action (*Action) or who implement the interface com.opensymphony.xwork2.Action (or extend its subclass com.opensymphony.xwork2.ActionSupport). The code for the ViewOrderAction class is as follows:

package com.springessentialsbook.chapter7.struts;
...
@Action("/order")
@ResultPath("/WEB-INF/pages")
@Result(name = "success", location = "orderEntryForm.jsp")
public class ViewOrderAction extends ActionSupport {
  @Override
  public String execute() throws Exception {
    return super.execute();
  }
}

@Action maps /order (in the request URL) to this action class and @ResultPath specifies where views (JSP files) exist. @Result specifies navigation to the next page up to the string value of the execute() method. We created ViewOrderAction to be able to navigate to a new page and to perform an action (business logic) when submitting a form within a view (orderEntryForm.jsp):

package com.springessentialsbook.chapter7.struts;
…...
@Action("/doOrder")
@ResultPath("/WEB-INF/pages")
@Results({
  @Result(name = "success", location = "orderProceed.jsp"),
  @Result(name = "error", location = "failedOrder.jsp")
})
public class DoOrderAction extends ActionSupport {
  @Autowired
  private OrderService orderService;
  private OrderVO order;

  public void setOrder(OrderVO order) {
    this.order = order;
  }
  
  public OrderVO getOrder() {
    return order;
  }

  @Override
  public String execute( ) throws Exception {
    if ( orderService.isValidOrder(order.getOrderId())) {
      order.setOrderName(orderService.placeAnOrder(order.getOrderId()));
      return SUCCESS;
    }
    return ERROR;
  }

Also, here is the JSP code that calls the Action class. Notice the form's doOrder action, which calls the DoOrderAction class (using @Action("doOrder")).

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div align="center">
      <h1>Spring and Struts Integration</h1>
      <h2>Place an order</h2>
      <s:form action="doOrder" method="post">
        <s:textfield label="OrderId" name="order.orderId" />
        <s:submit value="Order" />
      </s:form>
    </div>
  </body>
</html>

As you can see, we used OrderVO, whose code is as follows, as the data model in the view. Any changes to this object in the JSP code or action class will be carried forward to the next page:

public class OrderVO {
  private String orderName;
  private String orderId;

  public String getOrderName() {
    return orderName;
  }
  public void setOrderName(String orderName) {
    this.orderName = orderName;
  }
  public String getOrderId() {
    return orderId;
  }
  public void setOrderId(String orderId) {
    this.orderId = orderId;
  }

In the DoOrderAction action class, in the method execution, we implement the business logic and return the string value of the method specified in the navigation logic in the presentation layer. Here, the action class either goes to orderProceed.jsp (if it is a valid order) or failedOrder.jsp (in the case of a failure). Here is the orderProceed.jsp page, to which a success order will be forwarded:

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div align="center">
      <h1>Order confirmation</h1>
      <s:label label="OrderId" name="order.orderId" />, <s:label label="OrderName" name="order.orderName" /> <br/>
      has been successfully placed.
    </div>
  </body>
</html>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset