This page last changed on Sep 16, 2004 by vitorsouza.

Lesson 3: Actions and Results

Actions are the basic unit of execution. An action is a class that is registered under WebWork's configuration to respond to a specific request. In a Model-View-Controller approach, the Action is part of the Controller, leaving to JSP pages what they do best: being the View.

The following steps are a possible way of creating an action in WebWork:

  1. Create a JSP page that will call the action;
  2. Create the action class;
  3. Create a JSP page that will process the result;
  4. Register the action in xwork.xml.

The first example of this tutorial could be no other than "Hello, WebWorld!". The code below displays WebWork's configuration file xwork.xml with configuration for an action under the default package.

xwork.xml:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
	<!-- Include webwork defaults (from WebWork JAR). -->
	<include file="webwork-default.xml" />
	
	<!-- Configuration for the default package. -->
	<package name="default" extends="webwork-default">
		<!-- Default interceptor stack. --> 
		<default-interceptor-ref name="defaultStack" /> 
		
		<!-- Action: Lesson 03: HelloWebWorldAction. --> 
		<action name="helloWebWorld" class="lesson03.HelloWebWorldAction"> 
			<result name="success" type="dispatcher">ex01-success.jsp</result> 
		</action> 
	</package>
</xwork>

Don't worry about the default-interceptor-ref yet. For now we are interested in the action only. This configuration file is telling WebWork that there is an action called helloWebWorld which is implemented by the class lesson03.HelloWebWorldAction. For this action, we define a result under the name success which points to the web page ex01-success.jsp.
Read more: xwork.xml

Things should get clearer once we take a look at the code that calls the action:

ex01-index.jsp:

<html>
<head>
<title>WebWork Tutorial - Lesson 3 - Example 1</title>
</head>

<body>

<p>Click the button below to activate HelloWebWorldAction.</p>

<form action="helloWebWorld.action" method="post">
<p><input type="submit" value="Hello!" /></p>
</form>

</body>
</html>

This is how web pages can integrate with WebWork: by accessing *.action URLs. Recalling the previous lesson, that's why we registered WebWork's ServletDispatcher with mapping to *.action.

When we click the button in our example page, the browser will send the form data to the URL helloWebWorld.action. Since this URL fits under the mapping *.action, the Servlet container will activate WebWork's ServletDispatcher, which will read xwork.xml and look for an action called helloWebWorld. If the action is found, a new instance of the action class is created and the method execute() is called.

Let's see the action class, then:

HelloWebWorldAction.java:

package lesson03; 

import com.opensymphony.xwork.ActionSupport; 

public class HelloWebWorldAction extends ActionSupport { 
	String hello; 
	public String getHello() { 
		return hello; 
	}
	public String execute() throws Exception { 
		hello = "Hello, WebWorld!"; 
		return SUCCESS; 
	} 
}

First, notice that this class extends com.opensymphony.xwork.ActionSupport and implements the method public String execute(). For starters, all your action classes should do that. Second, notice that the method execute() only sets the value of the hello property and returns the constant SUCCESS, which is a String whose value is "success".

When the ServletDispatcher gets "success" as return from execute(), it looks again at xwork.xml for a result with that name, finds it, and moves on to ex01-success.jsp, as specified in the configuration.

Let's see what that page does:

ex01-success.jsp:

<%@ taglib uri="webwork" prefix="ww" %> 
<html> 
<head> 
<title>WebWork Tutorial - Lesson 3 - Example 1</title> 
</head> 
<body> 

<ww:property value="hello" /> 

</body> 
</html>

If you run the example, you will see that this page will display "Hello, WebWorld!". That happens because what the <ww:property value="hello" /> tag does is look for the property hello in the action class that just executed. Actually, it looks for an accessor method, so it ends up calling getHello(). Since HelloWebWorldAction was called and set the value of the hello property to "Hello, WebWorld!", getHello() will return that value and it will be displayed by the resulting JSP page.

Try the example!

Supplying Data to the Action

The previous example demonstrated how WebWork's actions work, but we can't do much if we're not able to supply data to our action. Let's see an example that does just that:

xwork.xml:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
	<!-- Include webwork defaults (from WebWork JAR). -->
	<include file="webwork-default.xml" />
	
	<!-- Configuration for the default package. -->
	<package name="default" extends="webwork-default">
		<!-- Default interceptor stack. --> 
		<default-interceptor-ref name="defaultStack" /> 
		
		<!-- Action: Lesson 03: HelloAction. -->
		<action name="hello" class="lesson03.HelloAction">
			<result name="error" type="dispatcher">ex02-index.jsp</result>
			<result name="success" type="dispatcher">ex02-success.jsp</result>
		</action>
	</package>
</xwork>

HelloAction.java:

package lesson03;

import com.opensymphony.xwork.ActionSupport;

public class HelloAction extends ActionSupport {
	String person;
	public String getPerson() {
		return person;
	}
	public void setPerson(String person) {
		this.person = person;
	}
	public String execute() throws Exception {
		if ((person == null) || (person.length() == 0)) return ERROR;
		else return SUCCESS;
	}
}

ex02-index.jsp:

<html>
<head>
<title>WebWork Tutorial - Lesson 3 - Example 2</title>
</head>

<body>

<p>What's your name?</p>

<form action="hello.action" method="post">
<p><input type="text" name="person" /><input type="submit" /></p>
</form>

</body>
</html>

ex02-success.jsp:

<%@ taglib uri="webwork" prefix="ww" %>
<html>
<head>
<title>WebWork Tutorial - Lesson 3 - Example 2</title>
</head>
<body>

Hello, <ww:property value="person" />

</body>
</html>

Let's analyse the differences: in this example we are sending form data via POST, under the name of person. Because of that, after a new instance of HelloAction is created, WebWork's ServletDispatcher will try to fill the action's property person with the data that was sent, therefore calling the mutator method setPerson() (actually, that is done by the ParametersInterceptor, which we will only learn about later, in lesson 5 – for now, know that when the action is executed, the property is already set).

If you look at the action class' code, you will see that during execute(), it checks if the property was filled (i.e. if data was supplied in the form field). If it was, it returns SUCCESS, therefore dispatching the request to ex02-success.jsp, otherwise, it returns ERROR, moving back to ex02-index.jsp.
Try the example!

Types of Result

On the examples above, when we say that a result is of type "dispatcher" it means that WebWork looks for a result-type called dispatcher and finds out which result class implements it. An instance of that class is activated whenever the action returns that type of result.

Result classes are implement the com.opensymphony.xwork.Result interface. WebWork comes with some result classes already implemented, but you can build your own, if you want. WebWork's result types are already configured in webwork-default.xml:

  • dispatcher (com.opensymphony.webwork.dispatcher.ServletDispatcherResult): forwards the result to the specified location;
  • redirect (com.opensymphony.webwork.dispatcher.ServletRedirectResult): redirects the result to the specified location. Unlike the dispatcher, the redirection does not send form data (via POST or GET) to the specified page;
  • velocity (com.opensymphony.webwork.dispatcher.VelocityResult): uses a Velocity template as the result. You could use the dispatcher to forward results to Velocity pages if you have VelocityServlet configured in web.xml, but using the Velocity result is a better approach. More on Velocity on lesson 4.2;
  • chain (com.opensymphony.xwork.ActionChainResult): chains an action on another, i.e., the result of an action is another action;
  • xslt (com.opensymphony.webwork.views.xslt.XSLTResult): uses an XML document transformed by an XSLT style sheet as the result.

Read more: Result Types

Moving on

These examples illustrate the main concept of actions and results: they are units of execution that respond to requests, do some processing and, depending on the result, dispatch the request to some other location. Although that might seem very simple, it's just the core of WebWork's functionality.

Here are some other things that can be done with actions, just so you know what WebWork can do before we move on to other lessons:

  • With interceptors, it can log every action execution an even clock the execution time (lesson 5);
  • The action could work directly with your business object by implementing the ModelDriven interface;
  • With XML files, configure the validation of the data that is sent to the action. If some data is not valid according to your specification, the action is not executed and error messages are attached to the action (reference: Validation);
  • By using WebWork UI Tags in association with the validation framework, forms will automatically display error messages due to invalid data input (lesson 4.1.1);
  • WebWork can provide to some actions instances of components (in different scopes) automatically, allowing Inversion of Control (reference: [Inversion of Control & Components]);

The next lessons will talk about the different types of views that can be used by WebWork.


Previous Lesson | Next Lesson
Document generated by Confluence on Dec 14, 2004 16:36