Create your first WebWork action An action is a piece of code that is executed when a particular URL is requested. After actions are executed, a result visually displays the outcome of whatever code was executed in the action. A result is generally an HTML page, but it can also be a PDF file, an Excel spreadsheet, or even a Java applet window. In this book, we’ll primarily focus on HTML results, because those are most specific to the Web. As Newton’s Third Law states, “every action must have a reaction.” (An action doesn’t technically have to have a result, but it generally does.) Although not “equal and opposite,” a result is always the reaction to an action being executed in WebWork.Suppose you want to create a simple “Hello, World” example in which a message is displayed whenever a user goes to a URL such as http://localhost/helloWorld.action. Because you’ve mapped WebWork’s servlet to *.action, you need an action named helloWorld. To create the “Hello, World” example, you need to do three things:Create an action class: HelloWorldCreate a result: hello.jspConfigure the action and resultLet’s begin by writing the code that creates the welcome message. Saying hello, the WebWork wayStart by creating the action class, HelloWorld.java, as shown in the listing below.HelloWorld.java package ch2.example1;import com.opensymphony.xwork.Action;public class HelloWorld implements Action { private String message; public String execute() { message = "Hello, World!n"; message += "The time is:n"; message += System.currentTimeMillis(); return SUCCESS; } public String getMessage() { return message; } } The first and most important thing to note is that the HelloWorld class implements the Action interface. All WebWork actions must implement the Action interface, which provides the execute() method that WebWork calls when executing the action. Inside the execute() method, you construct a “Hello, World” message along with the current time. You expose the message field via a getMessage() JavaBean-style getter. This allows the message to be retrieved and displayed to the user by the JSP (JavaServer Pages) tags.Finally, the execute() method returns SUCCESS (a constant for the string "success"), indicating that the action successfully completed. This constant and others, such as INPUT and ERROR, are defined in the Action interface. All WebWork actions must return a result code—a string indicating the outcome of the action execution.Note that the result code doesn’t necessarily mean a result will be executed, although generally one is. You’ll soon see how these result codes are used to map to results to be displayed to the user. Now that the action is created, the next logical step is to create an HTML display for this message. Displaying output to the Web browserWebWork allows many different ways of displaying the output of an action to the user, but the simplest and most common approach is to show HTML to a Web browser. Other techniques include displaying a PDF report or a comma-separated value (CSV) table. You can easily create a JSP page that generates the HTML view: <%@ taglib prefix="ww" uri="webwork" %> <html> <head> <title>Hello Page</title> </head> <body> The message generated by my first action is: <ww:property value="message"/> </body> </html> The taglib definition in the first line maps the prefix ww to the URI webwork. (Note that the URI is the same as that in the web.xml file.) A prefix of ww indicates that all the WebWork tags will start with ww:.As you can see, this is a simple JSP page that uses one custom WebWork tag: property. The property tag takes a value attribute and attempts to extract the content of that expression from the action. Because you created a getMessage() method in the action, a property value of message results in the return value of a getMessage() method call. Save this file in the root of your Web application, and call it hello.jsp. Configuring your new actionNow that you’ve created both the action class and the view, the final step is to tie the two together. You do so by configuring the action to a particular URL and mapping the SUCCESS result to the JSP you just created. Recall that when you created the skeleton layout, you generated a nearly empty xwork.xml file. You’ll now add some meaningful values to this file and see the final WebWork action work.When you’re configuring a WebWork action, you must know three things:The full action class name, including the complete packageThe URL where you expect the action to exist on the WebAll the possible result codes the action may returnAs you know from the previous Java code, the action class name is ch2.example1.HelloWorld. The URL can be anything you like; in this case, we choose /helloWorld.action. You also know that the only possible result code for this action is SUCCESS. Armed with this information, let’s modify xwork.xml to define the action: <!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.0.dtd"> <xwork> <include file="webwork-default.xml"/> <package name="default" extends="webwork-default"> <default-interceptor-ref name="completeStack"/> <action name="helloWorld" class="ch2.example1.HelloWorld"> <result name="success">hello.jsp</result> </action> </package> </xwork> In this file, you’ve now made a direct correlation between an action name (helloWorld) and the class you wish to be executed. So, any HTTP request to /helloWorld.action will invoke your new action class. You also made a direct correlation between the result code SUCCESS (a string constant for "success") and the JSP that you just created to display the message.With xwork.xml saved, the action class compiled and copied to WEB-INF/ classes, and hello.jsp added to the root of the Web application, you’re ready to fire up the application server and try this new action. Consult your application server’s documentation for detailed instructions on how to start, stop, and deploy Web applications like this one. And that’s it! You can now point your Web browser to the action URL, such as http://localhost/helloWorld.action, to see the final product shown in Figure 1. (Depending on the servlet container and the configuration, this URL could include a port number like 8080.)As you can see, this isn’t the most exciting Webpage, so let’s spice it up. You’ll make the greeting generated by this action customizable by letting users enter their name and be personally greeted. Up to this point, you’ve seen an action that is read-only; now you’ll learn how to handle inputs and read-write actions.Dealing with inputsNow that you know how to build a simple action, let’s take it up one notch and add the ability to personalize the message. You’ll build on the existing code. First, create another HTML page that asks for the user’s name. Create the following file, name.jsp, in the same directory as hello.jsp: <html> <head> <title>Enter your name</title> </head> <body> Please enter your name: <form action="helloWorld.action"> <input type="textfield" name="name"/> <input type="submit"/> </form> </body> </html> Note that the form is being submitted to helloWorld.action—the same location you used to display the previous example. Since you’re expanding on the previous example, you’ll continue to use this location. Another important point is that the textfield input is named name. Just as message was the property you used to display (get) the message, name is the property you use to write (set) the user’s name.Next, you need to tweak the HelloWorld action to construct the personalized message. The new action code looks like this: package ch2.example1;import com.opensymphony.xwork.Action;public class HelloWorld implements Action { private String message; private String name; public String execute() { message = "Hello, " + name + "!n"; message += "The time is:n"; message += System.currentTimeMillis(); return SUCCESS; } public String getMessage() { return message; } public void setName(String name) { this.name = name; } public String getName(){ return this.name; bb} } This code adds two things to the previous example. The first new item is a field and corresponding JavaBean-style set method named name. This must match exactly the name of the textfield you used in name.jsp. You also personalize the message that is constructed by including the name in the message during the execute() method. In WebWork, values are always set (via the setXxx() methods such as setName()) before the execute() method is called. That means you can use the variables in the execute() method while assuming they have already been populated with the correct value. That’s it! Recompile the action class, and start your application server. Now point your Web browser to http://localhost/name.jsp, enter a name, and see that the message (shown in Figure 2) is now personalized.As easy as that was, a few problems can result. For instance, what if the user doesn’t enter any data? The greeting will end up saying “Hello, !” Rather than show an ugly message, it might be better to send the user back to the original page and ask them to enter a real name. Let’s add some advanced control flow to this action.Advanced control flowBecause you want the action to show either the message result (hello.jsp) or the original input form (name.jsp), you have to define another result in xwork.xml. You do this by changing the action entry to the following: <action name="helloWorld" class="ch2.example1.HelloWorld"> <result name="success">hello.jsp</result> <result name="input">name.jsp</result> </action> Now, if the execute() method in the HelloWorld action returns the string "input" (also defined as a constant, INPUT, in the method), the result of the action will be name.jsp rather than hello.jsp. In order to spice up this example a little more, let’s also not allow the string "World" to be entered as a name. Editing the action to support these checks results in the following execute() method: public String execute() { if (name == null || "".equals(name) || "World".equals(name)) { return INPUT; } message = "Hello," + name + "!n"; message += "The time is:n"; message += System.currentTimeMillis(); } If the name doesn’t pass your validation rules, you return a result code of INPUT and don’t prepare the message. With just a couple lines of code, the control flow of this action has doubled the number of possible results the action can display. However, this still isn’t as interesting as it could be, for two reasons:When you return to the INPUT, users can’t see why they’re back on this page. Essentially, there is no error message.Users can’t tell what they originally entered as the name value. It might be nothing, or it might be World. It would be better if the input box displayed what the user originally entered.In order to address both concerns, let’s modify the input result to display an error message. You can reuse the message property from the success result. Then, add logic to display an error message as well as make the textfield input display the previous name in the event of an error. With the modifications in place, name.jsp now looks like this: <%@ taglib prefix="ww" uri="webwork" %> <html> <head> <title>Enter your name</title> </head> <body> <ww:if test="message != null"> <font color="red"> <ww:property value="message"/> </font> </ww:if> Please enter your name: <form action="/helloWorld.action"> <input type="textfield" name="name" value="<ww:property value="name"/>"/> <input type="submit"/> </form> </body> </html> This code adds two significant things to the JSP. First, if an error message exists, it’s printed in a red font. You use the ww:if tag to see whether the message property exists; if it does, you print it. If a user goes to this page directly, the test fails, and no error message is reported—exactly the behavior you’re striving for.Second, you add a value attribute to the input HTML element. This attribute defines the default value to be displayed when the page is first loaded. Because the ww:property tag returns an empty String if a property isn’t found, it also results in the desired behavior. After the action has been submitted once, the property exists. As such, if the INPUT result occurs, the value previously entered is displayed.Finally, let’s modify the action’s execute() method one more time. This time, you’ll make sure an error message is set in the message property just before the action returns with the INPUT code. The new method looks like this: public String execute() { if (name == null || "".equals(name) || "World".equals(name)) { message = "Blank names or names of 'World' are not allowed!"; return INPUT; } message = "Hello," + name + "!n"; message += "The time is:n"; message += System.currentTimeMillis(); return SUCCESS; } The most important thing to note here is that the execute() method is prevented from finishing and returns with INPUT if the name fails the validation check.With these small changes, you’re ready to try the new behaviors. Start your application server, and point your browser to http://localhost/name.jsp. Enter in the value World for the name textfield and submit the form, and you should see the screen shown in Figure 3.This type of control flow, validation, and error reporting is often required for forms in Web applications. Rather than leave the developer to handle these tasks, WebWork provides help that does almost all the work for you. Heading up Jive Software’s Professional Services organization, Patrick Lightbody has worked for various technology companies, ranging from well-established giants such as Cisco Systems to tiny Silicon Valley startups. He is the author of Java Open Source Programming and spends his spare time contributing to various OpenSymphony projects, including WebWork and OSWorkflow. While he grew up in the heart of the Silicon Valley, Lightbody now resides in Portland, Oregon. Jason Carreira has been developing and architecting J2EE applications for six years. For the last five, he’s been designing and building enterprise financial software products from the ground up. He recently joined ePlus where he is working on the next generation of eProcurement solutions. In his spare time, Carreira is a core developer of the XWork command pattern framework and WebWork MVC Web framework at OpenSymphony. He lives in Rochester, New York, with his wife Cyndy and three children. Web DevelopmentSoftware DevelopmentJava