Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

Starting out with Struts on Tomcat

  
  
  

Apache Struts is a free, open source framework for creating Java web applications. It's designed to make it easy to use a Model-View-Controller architecture, which can help your app remain clear, straightforward, and easy to maintain. When the time comes to deploy your app, Apache Tomcat is a great complement for Struts, geared as it is to Java servlets. Let's see how to make a basic Struts/Tomcat application; I'll assume you already have a functional Tomcat setup and want to start using Struts apps with it.

The latest production release of Struts, 2.3.4.1, is available to download or via your distribution's package manager. The .zip file you download from the project's website contains the required .jar files along with documentation and sample apps.

It's incredibly straightforward to deploy one of the samples on Tomcat. Simply copy struts-2.3.4.1/apps/struts2-blank.war into $CATALINA_HOME/webapps, restart Tomcat, then go to http://localhost:8080/struts2-blank/example/HelloWorld.jsp to see the HelloWorld sample app in action.

How does it all work? When you restart Tomcat, it unwraps the .war archive into the correct directory structure, including all the necessary .jar files:

  • webapps/struts2-blank is the context root, where .html and .jsp files live.
  • webapps/struts2-blank/WEB-INF contains configuration files, such as web.xml.
  • webapps/struts2-blank/WEB-INF/src contains source files.
  • webapps/struts2-blank/WEB-INF/classes contains Java classes.
  • webapps/struts2-blank/WEB-INF/lib contains runtime libraries for this app.
  • webapps/struts-blank/META-INF contains meta information such as taglibs.

When you write your own Struts apps, you need to make sure to set up this structure yourself. To create a brand new Struts app, first set up a directory structure like this, under $CATALINA_HOME, where mystruts is the name of your app:

  • webapps/mystruts
  • webapps/mystruts/WEB-INF
  • webapps/mystruts/WEB-INF/src
  • webapps/mystruts/WEB-INF/classes
  • webapps/mystruts/WEB-INF/lib

Copy the .jar files you'll need over from struts2-blank:

cd $CATALINA_HOME/webapps/struts2-blank/WEB-INF/lib/ 
cp commons-fileupload-1.2.2.jar commons-io-2.0.1.jar commons-lang3-3.1.jar \\ 
freemarker-2.3.19.jar javassist-3.11.0.GA.jar ognl-3.0.5.jar \\ 
struts2-core-2.3.4.1.jar xwork-core-2.3.4.1.jar $CATALINA_HOME/webapps/mystruts/WEB-INF/lib

Create mystruts/WEB-INF/web.xml, a Tomcat filter that will make sure that all URLs are handled by Struts:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <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>
</web-app>

The filter struts2 is linked to the class org.apache.struts2.dispatcher.FilterDispatcher, and all URLs (/*) are sent to this filter.

Our app structure will be Model-View-Controller. MyStruts.java will act as both the Model class, which stores the back end (in this case this is just a message), and the Action class, which responds to a user action by showing a particular view. (In a more complicated example, you would split out the Model and Action classes.) The input.jsp and response.jsp files act as different Views, showing information to the user.

Let's start with the View files. These both go in the top mystruts directory, $CATALINA_HOME/webapps/mystruts. The input.jsp code looks like this:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
   
<html>
<head>
  <title>My Struts</title>
</head>
<body>
  <h1>Whose Struts?</h1>
  <s:form action="MyStruts" >
    <s:textfield name="username" label="Name: " />
    <s:submit value="Send" />
  </s:form>
</body>
</html>

That taglib line at the top says that we'll be using the Struts tags, as per the given URI, and preceding them (for identification) with s. Farther down, we use the Struts tags to set up a form whose action is to call the MyStruts class. It has a textfield, called username, and a submit button. The format of the tags here should be fairly straightforward if you understand HTML.

The response.jsp file is simpler still:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
   
<html>
<head>
  <title>Whose Struts Response</title>
</head>
<body>
  <h1><s:property value="message" /></h1>
  <s:form action="/input.jsp" >
    <s:submit value="Back" />
  </s:form>
   
</body>
</html>

The header is the interesting line. The property value message calls the getMessage() method of the Action class, which here is MyStruts. (If the property value were ping, it would call the getPing() method.) The string returned by this method is then displayed to the user.

The form underneath simply returns the user to the input form.

Next, let's set up our Action class, mystruts/WEB-INF/src/example/MyStruts.java:

  package example;
    public class MyStruts {
  private String message;
  private String username;
  
  public String execute() {
    setMessage(getUsername() +"'s Struts");
    return "Success";
  }
  
  public String getMessage() {
    return message;
  }
  
  public void setMessage(String message) {
    this.message = message;
  }
  
  public String getUsername() {
    return username;
  }
  
  public void setUsername(String username) {
    this.username = username;
  }
}

This should all be pretty straightforward; the get and set methods do exactly what they say on the tin. Note that we must have an execute() method to run when the Action class is called.

Finally, we need to edit mystruts/WEB-INF/classes/struts.xml to tie all these classes together:

<?xml version="1.0" encoding="UTF-8" ?>
<!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="struts-default">
    <action name="MyStruts" class="example.MyStruts">
      <result name="Success">/response.jsp</result>
    </action>
  </package>
</struts>

This code associates a particular Action with a particular class. The action is called in input.jsp, and this code will direct it to the correct class and run the execute() method. The result of MyStruts.execute() is then associated with the response.jsp View.

To get everything running, we need to compile the files into the classes subdirectory:

cd $CATALINA_HOME/webapps/WEB-INF javac -d classes src/example/MyStruts.java

Restart Tomcat, and go look at http://localhost:8080/mystruts/input.jsp. You should see your form, and it should work when you enter a name and click Send.

So far, so good! However, if you look at http://localhost:8080/mystruts/MyStruts.action, it will send you straight to the response.jsp page, but since no name has been entered, it will use Null. To fix this, change the execute() method in MyStruts.java:

import com.opensymphony.xwork2.ActionSupport;
public class MyStruts extends ActionSupport {
  ...
  public String execute() {
    if (getUsername() != null) {
      setMessage(getUsername() +"'s Struts");
      return SUCCESS;
    } else {
      return NONE;
    }
  }
  ...
}

The ActionSupport class we're now extending references the Action interface, which looks like this:

public interface Action {
   public static final String SUCCESS = "success";
   public static final String NONE = "none";
   public static final String ERROR = "error";
   public static final String INPUT = "input";
   public static final String LOGIN = "login";
   public String execute() throws Exception;
}

You'll also need to edit struts.xml:

<action name="MyStruts" class="example.MyStruts">
  <result name="none" type="redirect">/input.jsp</result>
  <result name="success">/response.jsp</result>
</action>

This creates a redirect (which starts a new request from the client, losing any existing data – rather like a Cancel button) back to the original input page if there's no name stored.

Recompile the app and restart Tomcat, and http://localhost:8080/mystruts/MyStruts.action or http://localhost:8080/mystruts/MyStruts should both act as expected.

To make this work from http://localhost:8080/mystruts, add index.html in the root directory:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <META HTTP-EQUIV="Refresh" CONTENT="0;URL=MyStruts.action">
</head>
<body> <p>Loading MyStruts...</p> </body> </html>

There's no need to restart Tomcat after you create index.html.

Next steps and resources

That's a basic look at how Struts and Tomcat can work together. Once you've got the fundamental concepts down, there's plenty more information out there to get you to Struts expert status in no time. The Struts 2 docs are excellent and comprehensive, and include tutorials, guides, and a cookbook. There's also a collection of Struts 2 plugins available, although these are not part of the official Struts framework, so buyer beware. They can however be a great option if you don't want to reinvent the wheel; they can make your Struts webapp development run even faster.




This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

Comments

thanks for this post
Posted @ Sunday, July 07, 2013 8:15 AM by james
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics