1.5. Converting JSP Applications to Struts

Problem

You want to convert an existing JSP-based web application to a Struts application.

Solution

Take a refactoring-style approach by applying Struts as you add new features to your application. As you increase your Struts knowledge, you can re-architect the existing code to use Struts. If no new development is planned for the application, refactor the existing JSPs a page at a time.

Discussion

The level of difficulty to migrate an existing JSP application depends greatly on the complexity and architectural soundness of the application. If the application uses a Model 1 architecture—that is, all logic is contained in the JSP page—it could be quite a challenge. You may find that you need to redesign the application from scratch to separate out the business logic from the presentation before you begin.

If you are new to Struts, then learn Struts on development of a new application instead of attempting to retrofit Struts to an application well into development. Struts is not a technology that can easily be "bolted on" late in the development process. However, some projects have altered their architectural underpinnings in midstream. If you are in this situation, steer the project plan so Struts is applied to new development first and preferably to features not on the critical path. Once you increase your Struts knowledge, it will be easier to convert existing code.

To make this more concrete, consider a simple example consisting of three JSP pages. The first page is the main welcome page that displays a link to the second page. The second page displays two form input fields. When the user submits the form, the result of adding the values is displayed on the third JSP page.

First, Example 1-3 shows the index.jsp page that provides a link to the input page.

Example 1-3. Linking to an input page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
   <head>
      <title>Simple Calculator</title>
   </head>
   <body>
      <a href="get_input.jsp">Calculator</a>
   </body>
</html>

Example 1-4 shows the get_input.jsp page that submits the entered values.

Example 1-4. Submitting data

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
   <head>
      <title>Add Two Numbers</title>
   </head>
   <body>
      <form action="display_result.jsp">
         Value 1: <input name="value1" type="text"/><br/>
         Value 2: <input name="value2" type="text"/>
         <p>
            <input type="submit"/>
         </p>
      </form>
   </body>
</html>

The page in Example 1-4 submits the form to a JSP page for displaying results. This target page (shown in Example 1-6) utilizes a JavaBean to hold the values received in the request from the form. Before looking at the target JSP, Example 1-5 shows the code for the JavaBean that will store this data.

Example 1-5. Simple JavaBean

package com.oreilly.strutsckbk;

public class ValueHolder {
    private int value1;
    private int value2;

    public int getValue1( ) {
        return value1;
    }

    public void setValue1(int value1) {
        this.value1 = value1;
    }

    public int getValue2( ) {
        return value2;
    }
   
    public void setValue2(int value2) {
        this.value2 = value2;
    }
}

The display_result.jsp page, shown in Example 1-6, uses the JSP setProperty tag to populate the bean with the request values. The values are outputted using request-time expressions, and the sum is calculated using a scriptlet. Finally, this calculated sum is displayed.

Example 1-6. Displaying results

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
   <head>
      <title>Add Two Numbers</title>
   </head>
   <body>
      <jsp:useBean 
            id="valueHolder"
            class="com.oreilly.strutsckbk.ValueHolder">
         <jsp:setProperty name="valueHolder" property="*"/>
      </jsp:useBean>
      The sum of <%= valueHolder.getValue1( ) %> plus
      <%= valueHolder.getValue2( ) %> is:<p>
      <% int sum = valueHolder.getValue1( ) + valueHolder.getValue2( ); %>
      <%= sum %>.<p>
      <a href="get_input.jsp">Perform another calculation</a>      
   </body>
</html>

This application demonstrates some of the more undesirable approaches to using JSP. While the use of the JavaBean is laudable, the calculation is performed within the JSP using scriptlet. This results in a mixing of business logic with presentation, and scriptlets (embedded Java code) can lead to maintainability problems for JSP applications.

Formulating a strategy for converting this application to Struts is simple. Though this example may be trivial, the strategy followed will be applicable to more complex applications. Remove as much embedded Java code as possible from the JSP pages. Start with the scriptlet (<% %>); if possible, remove the request-time expressions (<%= %>). To accomplish this with the JSP, in Example 1-6, move the sum calculation into the JavaBean (from Example 1-5) by adding a method that calculates and returns the sum:

public int getSum(  ) {
   return value1 + value2;
}

Now change the JSP to use the bean:write tag:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
   <head>
      <title>Add Two Numbers</title>
   </head>
   <body>
      <jsp:useBean 
            id="valueHolder"
            class="com.oreilly.strutsckbk.ValueHolder">
         <jsp:setProperty name="valueHolder" property="*"/>
      </jsp:useBean>
      The sum of <bean:write name="valueHolder" property="value1"/> plus
      <bean:write name="valueHolder" property="value2"/> is:<p>
      <bean:write name="valueHolder" property="sum"/>.<p>
      <a href="get_input.jsp">Perform another calculation</a>      
   </body>
</html>

This is a significant improvement over the earlier version of this mini-application.

Tip

Before continuing with more changes, now would be a good time to rebuild and redeploy the application to ensure it still works.

The next step, integrating the Struts controller into the mix, requires more work. First, create a Struts Action, like the one in Example 1-7, that is responsible for receiving the values from the form on the get_input.jsp page. The values are retrieved as request parameters which the Action marshals into a JavaBean. The bean instance is set as a servlet request attribute. The Action then forwards to the display_result.jsp page.

Example 1-7. Adding a Struts action

package com.oreilly.strutsckbk;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public final class ProcessInputAction extends Action {
    public ActionForward execute(ActionMapping mapping,
                 ActionForm form,
                 HttpServletRequest request,
                 HttpServletResponse response)
            throws Exception {
        ValueHolder bean = new ValueHolder( );
        bean.setValue1( Integer.parseInt(
            request.getParameter("value1")) );
        bean.setValue2( Integer.parseInt(
            request.getParameter("value2")) );
        request.setAttribute( "valueHolder", bean );
        return (mapping.findForward("success"));
    }
}

Create an ActionMapping in your struts-config.xml file for the Action:

<!-- Process input data -->
<action    path="/processInput"
           type="com.oreilly.strutsckbk.ProcessInputAction">
  <forward name="success" path="/display_results.jsp"/>
</action>

To use this Action, change the target action for the form on the get_input.jsp page:

<form action="ProcessInput.do">
  Value 1: <input name="value1" type="text"/><br/>
  Value 2: <input name="value2" type="text"/>
  <p>
    <input type="submit"/>
  </p>
</form>

Once you have developed a new feature like this, linking to the new action from existing JSP pages is simple using the specified ActionServlet mapping (e.g., *.do). You can link back from the Struts-based pages to your existing JSPs using the JSPs' URLs.

See Also

Recipe 6.1 describes how to create a base action for additional common behavior to all of your actions. Recipe 9-1 details how to leverage the declarative exception handling of Struts. Recipe 5.6 discusses ways of integrating existing JavaBeans with Struts action forms.

Get Jakarta Struts Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.