Getting Started with Apache Struts

Tutorial – Apache Struts 2 – From Soup to Nuts

TedHusted
Struts2

The man who managed the Apache Struts 2.0 release, Ted Husted gives us a quick-start guide into the enterprise-ready Java web framework

Background

Apache Struts 2 simplifies
enterprise-ready web development by providing a flexible set of
custom tags and an extensible application
architecture.
The framework is designed for professional
developers creating sophisticated web applications that integrate
with databases and other enterprise services. Originally known as
WebWork, Struts 2 has been continuously maintained since
March 2002
, and most recently updated with the April 2012
release (2.3.3).
Struts 2 is product of the Apache Software Foundation and
distributed to the general public at no charge under the
business-friendly Apache Software License 2.0. The ASF provides
product support only through a public mailing list
frequented by volunteer developers and users.

Getting Started

Struts 2 is directly supported by
the three most popular integrated development environments (IDEs)
for Java: IntelliJ IDEA by JetBrains,
MyEclipse
by Genutec
, and
NetBeans
. For example, to create a Struts 2 application in
IntelliJ IDEA, you can select the Struts
2 facet, and the IDE will download the JARs and setup a Java web
application structure, ready for you to add your own pages and
other Struts 2 elements.  

Figure
1 – IntelliJ IDEA ready for your Struts 2 elements

IntelliJ IDEA’s
support for Struts 2 includes configuration via dedicated Struts 2
facet – with fileset manager, library validator, and configuration
detector, dedicated Struts 2 structure tool windows, code
inspectors that spot Struts 2-specific code issues, support for
inplace Javascript and CSS code, smart coding completion within
Struts elements, Struts 2-ready refactorings, and Struts 2-aware
project navigation across Java, JSP and XML
files.
 

Likewise, with MyEclipse, you can add Struts 2 capabilities to a
web project, including wizards to create new Struts 2 elements or
edit existing elements. The wizards are context-sensitive and
provide input assistance and validation as you edit Struts 2
elements. Not to be left behind, NetBeans offers its own
set of wizards to create an example Struts 2 application, register
the necessary library files, and then edit the various Struts 2
elements. In addition, NetBeans supports hyperlinking and code
completion in Struts 2 configuration files. Struts 2 also provides
a Maven prototype you can use to bootstrap a project, if
you are so inclined, and, of course, the distribution has all the
usual assets for hardcore hand-coders.

In Brief – The Elements of Struts
Design

A dynamic Struts 2 application has
seven building blocks:

  1. Pages with Struts Tags
  2. Message Properties
  3. Actions
  4. Interceptors
  5. Validators
  6. Results
  7. Annotations and Deployment Descriptors

 The elements can be organized
into three groups:

  • Pages and Message Properties are used to create the application
    user interface.
  • Actions, Interceptors, and Validators process an incoming
    request, in order to render a page, or some other Result.
  • Annotations and Deployment Descriptors are used to define the
    initial state for the other elements of a Struts 2
    application.

 Let’s take a look at each
element in turn…

    
   

Terminally Pretty – Struts
Tags

Often, much of the coding effort in
a web application goes into the pages. The Struts 2 Tags help us
create localized, dynamic web applications with a minimum of
coding, reducing effort by reducing code. The
listing “A localization-ready form using Struts tags.” shows the
source code for a simple input form. 

A
localization-ready form using Struts tags
<s:actionerror/>
<s:form action="RegisterSave" validate="true">
<s:textfield key"username"/>
<s:password key="password"/>
<s:password key=password2.label" name="Password2"/>e
<s:submit key="save"/>
<s:submit key="cancel" action="MainMenu"
onclick="form.onsubmit=null"/>
</s:form>

The key attribute refers to a Message Properties
file, in the standard Java format, that contains the text to use as
the label, along with other terms, such as error messages. The
listing “A message properties file” shows a simple properties file
for our form.

A message properties file

 

username = Username
password = Password
password2.label = Repeat password
save = Save
cancel = Cancel

The figure below “Struts 2 Data
Entry Form” shows the page rendered in a web browser.

Figure
– Struts 2 Data Entry Form

The two use cases for Message
properties are normalization and
localization. Many terms are
used more than once, and so should be defined only once. Also, many
enterprise applications are presented in multiple languages, and
Struts 2 supports adding Message Property files for different
locales. The key attribute can
also be used as the name of the property used to populate the field
from a dynamic value passed to the page.  

Telling it Like it is – Value
Stack

To manage values being passed to a
page, Struts 2 uses a “Value Stack”. When a Struts tag needs a
value, the framework searches the Value Stack in Last In First Out
order (LIFO). If you push a JavaBean with a Username property onto
the stack last, then the tag will find that value first. The Value
Stack encapsulates the standard Java scopes, along with framework
elements, and any custom objects you would like to push onto the
stack. The Struts 2 Validators use the Value Stack to redisplay
incorrect form input. A default value might have been set by a
database call, and another value entered by the user into a form.
The user’s value is last on stack, and so it’s found first if the
page is redisplayed. Figure 3 “Struts 2 Value Stack” illustrates
how the system searches for property values.  

Figure
3: Struts 2 Value Stack

The Value Stack
solves a thorny problem in validating input.
You might have
an Integer field on a JavaBean, but on the input form, the user
enters “Blue” instead of a number. The framework can’t store “Blue”
in an Integer field. So, we either have to throw-away the incorrect
value, or complicate how we store a value destined for an Integer
property. In Struts 1, for example, we use ActionForms to capture
and validate input as Strings.

Many developers would then code a
similar but different set of JavaBeans to capture the value in its
native type, for transfer to a database system. In Struts 2, the
framework can validate input and transfer it to a “POJO” JavaBean
with typed properties, without creating and maintaining a special
ActionForm. The Struts 2 Validators push the offending input onto
the Value Stack, so it can be validated and corrected before
populating a value object.

Hard Name, Easy Code – OGNL

Underlying the tags is a powerful
expression and binding language called OGNL, or Object Graph
Notation Language. Most Java web developers will find the feature
set similar to the JST Expression Language, but much more capable.
OGNL works hand-in-glove with the Value Stack, making it easy to
retrieve a value from a certain scope, or just the last value
pushed. 

  • Get the username from the User object in Session scope only:
    <p>Username: <s:property name=”#session.user.username”
    /> </p>
  • Get the username propery last pushed onto the stack:
    <p>Username: <s:property
    name=”username” /> </p>

New Tags for Old – Control, Data,
and UI

A variety of
custom
tags are available in Struts 2
, which can be grouped into three
flavors: Control, Data, and UI. The
Control tags
allow a page to 

  • change its presentation on the fly, by using operations like
    if, elseif, and else; or
  • generate markup with operations like append,
    iterator, merge, sort, and
    subset

The
Data tags mange dynamic values and
behaviors, with operations like
a, action,
bean,
date,
debug,
i18n,
include, param,
property, push, set, text, and url. The Form UI
Tags
replicate and extend the standard HTML
tags, with operations like
form, label checkbox,
radio,
optgroup, textfield,
textarea,
and
password – along with enhanced controls like checkboxlist,
combobox, doubleselect, among several
others.
Finally, Non-Form UI Tags, provide error
handling with operations like fielderror,
actionerror, and actionmessage.  

Less is More – Themes

Most often, the dynamic data
emitted by many of the tags is wrapped in a predictable envelope of
basic HTML. To make pages easier to build, the
UI Tags can include routine markup, so you don’t have to. The
framework ships with standard themes that include different sets of
standard markup.

  • The Simple Theme does not output markup. You can add your own – pretty much like a standard HTML
    tag.
  • The XHMTL Theme is the default theme, and does things
    like put forms into a two-column table layout, with labels, client
    and server-side validation, and error handling (just by specifying
    the field).
  • The CCS XHTML Theme is designed to replicate the XHTML
    theme, but entirely in CSS.

The listing “HTML source generated
by Struts Tags” shows the code the XHTML template generated for our
data entry form.  

HTML Source generated by Struts
Tags
<form id="RegistrationSave" name="RegistrationSave" action="/struts2-mailreader/RegistrationSave.do" method="post">
<table class="wwFormTable">
    <tr>
    <td class="tdLabel"><label for="Registration_save_username" class="label">Username:</label></td>
    <td><input type="text" name="username" value="" id="Registration_save_username"/></td>
    </tr>
    <tr>
    <td class="tdLabel"><label for="RegistrationSavePassword" class="label">Password:</label></td>
   <td><input type="password" name="password" value="" id="RegistrationSavePassword"/></td>
</tr>
    <tr>
    <td class="tdLabel"><label for="RegistrationSavePassword2" class="label">(Repeat) Password:</label></td>
    <td><input type="password" name="password2" id="RegistrationSavePassword2"/></td>
</tr>
</table></form>

The templating system is designed
so that you override the markup for a single control, or replace
all the standard markup with your own custom theme.

 
  

It Takes a Village – Actions,
Interceptors, Validators, Results

Web pages are only the last mile
between the user and the backend business logic. In order to acquire the data that a dynamic page needs, a
request passes through a set of handlers. The image below shows
this in context.

Lights, Cameras – Actions

Actions are the framework’s basic
unit of work. Most framework requests are
handled by an Action, with help from Interceptors, Results, and the
Struts Tags. An application can map an action handler to logical
resource names, like Welcome.action or AccountInsert.action. When a
browser submits a request for one of these resources, the framework
selects an Action class to handle the exchange. The input values
from the request (if any) are transferred to properties on an
Action class (or some other class of your choosing). The framework
then calls a method on the Action to invoke the business logic
associated with the request. The class can return a string token to
indicate the outcome of the transaction. Usually, these tokens are
generic terms like
“success”, “failure”,
“input”,
“error”, or
“cancel”. The framework passes the
token returned by an Action to a Result handler for further
processing.

Getting There from Here –
Results

The result handler either creates
output or dispatches to another resource, like a server page, to
create the output. There are several result handlers bundled with
the framework and several more are available as plugins. For
example, there are plugins for rendering reports with JFreeChart or
JasperReports.

Another plugin
converts output to JSON for AJAX applications.
Yet another
lets Struts 2 applications utilize JavaServer Faces components as a
result. Other custom results can be created and
plugged into the framework as needed. Each action handler can have
one or more result handlers, mapped to whatever result types are
needed.

Regardless of
what type of result is being generated, the action handler only
needs to return a logical name.
The action does not need to
know how the response is being handled.

Thank You Sir, May I have Another
– Interceptors

Most of the framework’s
business-logic utility is provided by Interceptors. All requests can be handled by a single set of
Interceptors, or different sets of Interceptors can handle
different requests.

Interceptors can invoke code both
before and after the Action executes, encapsulating standard
utility that can be shared between Actions into a reusuable object.
Services like property population, validation, and authorization
are provided by standard Interceptors.

The set of
Interceptors acts as a “gauntlet” for the request.
The
request object passes through each Interceptor in turn. The
Interceptor can ignore the request, or act on the request, as
appropriate.

Trust but Verify – Validators

Validators vet incoming data and
generate an error message when input is invalid. The framework
provides all the validators that most applications will need,
though custom Validators are easy to implement for special
situations.

Ready, Set, Go – Annotations and
Deployment Descriptors

A web application uses a deployment
descriptor to initialize resources like filters and listeners. The
web deployment descriptor is formatted as a XML document.
The web container reads the XML document and
creates an internal configuration object. When the container starts
up, it loads and configures the components specified by the
deployment descriptor.

Likewise, Struts
uses an internal configuration object to tie together various parts
of the application, like the Action and the Result.
An
application can specify the Struts configuration by using Java
annotations or by providing one or more XML documents.

  • web.xml – Standard web deployment descriptor with the
    framework’s bootstrap components, including the FilterDispacther
    that detects Action URLs.
  • struts.xml – Main configuration, contains result/view types,
    action mappings, interceptors, and so forth.
  • struts-plugin.xml – Optional configuration
    file for plugins.
    Each plugin JAR may have its own
    descriptor.

Below shows a typical XML-style
configuration for a logon action:

Example Logon XML Document

 

<struts>
  <package name="default"
    extends="struts-default">
    <action name="Logon"
      class="mailreader2.Logon">
      <result type="redirect-action">MainMenu</result>
      <result name="input">/pages/Logon.jsp</result>
      <result name="cancel"
       type="redirect-action">Welcome</result>
      <result name="expired"
        type="chain">ChangePassword</result>
    </action>
  </package>
</struts>

 

And the corresponding annotations for the same logon action:

Example Logon Java Annotation

 

@Results({
@Result(name="success", value="MainMenu"),
@Result(name="input", value="pages/Logon.jsp"),
@Result(name="cancel", value="Welcome",
type="redirect-action"),
@Result(name="expired", value="ChangePassword",
type="chain")})
public class Logon extends ActionSupport {
// .... 
}

 

Tip –
Configuration by Java annotation or by XML document are not
mutually exclusive.
We can use either or both in the same
application.

 
 

Same Stuff, Different Day – Struts
2 Life Cycle

A framework is a semi-complete
application. By providing a backbone structure,
the framework lets developers add the code that makes this
application unique, and reuse the underlying architecture again and
again.

The Struts 2
architecture strives for simple elegance.
When a web client
sends a request to a Struts 2 application, the framework provides a
seven step processing cycle

  1. Accept Request,
  2. Select Action,
  3. Push Interceptors,
  4. Invoke Action,
  5. Select Result,
  6. Pop Interceptors, and
  7. Return Response.

At each step in the cycle,
developers can provide their own code to define how their
application reacts to a particular request.

  1. Accept Request: First, a web browser makes a request. The request might be
    for a resource like a HTML page, a PDF, or (among other things) the
    special “Action” resource that can create a dynamic
    response.
  2. Select Action: The incoming request is transferred to a Struts 2 component
    called a
    Filter Dispatcher. Whenever this request is for a Struts Action, our
    dispatcher passes the request through to the rest of the framework.
    (Otherwise, the request just passes through our dispatcher,
    untouched.)
  3. Push Interceptors:
    Whenever a request enters the framework, we
    might want to validate input, or transfer values to an internal
    object, or upload a file, or any combination of similar
    operations.
    (In other words, we want to intercept the request to
    do some housekeeping before going on to the main event.) The
    framework Interceptor components handle operations that need to be
    applied to more than one request.
  4. Invoke Action: Aside from the Interceptor operations, we will also want to
    invoke an operation unique to the request (the “main
    event”).
    For example, we might want to work with a database
    to store or retrieve information. After a request passes through
    the outer layer of Interceptors, a method on an Action class can be
    called to handle any special processing for the request.
  5. Select Result: After the Action method fires, we need to tell the rest of
    the framework what to do next. We’ve handled the request, and now
    we need to create the response (or “result”). As aforementioned, to
    bootstrap the response process, the Action method returns a string
    token representing the outcome of the request, such as “success”,
    “failure”, “cancel”, or something more specific, like
    “logon”.
    The framework matches that token with the name of a
    Result component. The Result is responsible for handling the
    response, either by rendering output for the browser, or by
    transferring control to another resource that will render the
    response. Most often, “another resource” will be
    a JavaServer Page formatted with Struts Tags.
  6. Pop Interceptors:
    After the Result handler fires, the request
    passes back through the set of Interceptors.
    Some
    Interceptors work with incoming requests, some work with outgoing
    requests, and some work with both.
  7. Return Response: The request exits the framework, and the web server sends
    our response back to the web browser.

Architecturally, Struts 2 is an

Enterprise Model View Controller framework
where the Action
provides the Model, the Result represents the Controller, and Tags
render the View.

But wait, there’s more –
Plugins

Struts 2 provides a simple plugin
architecture so that developers can extend the framework just by
adding a JAR to the application’s classpath. Since plugins are
contained in a JAR, they are easy to share with others. Here’s a
sampling of the many plugins available for Struts 2.


  • JQuery
    : Ajax functionality and UI Widgets based on the jQuery
    javascript framework.
  • Hibernate:
    Hibernate Validator integration, Hibernate Core Sessions and
    Transactions injection capabilities and a Configuration Management
    Web Tool.
  • Guice:
    Actions, Interceptors, and Results to be injected by Guice.
  • OSGI:
    starting an instance of Apache Felix inside a web application, and
    scanning installed bundles for Struts configuration
  • REST:
    provides tools to build RESTful applications
  • Sitemesh:
    Sitemesh templates functionality access Struts information.

Next Steps

If you’re ready to take Struts 2
for a spin, the simplest thing is to fire up your favorite editor
or IDE, and start coding.

To give you a
staring place, the Struts 2 distribution bundles a “Struts Blank”
application.
It’s a ready-to-deploy WAR, designed to serve
as a starting place for your applications.  

The Blank application is
internationalized and includes a number of example pages, to help
you get started.  

Of course, there
are a number of online resources for learning more about Struts 2,
most of which are documented on the official website at
struts.apache.org. Another great resource is
Struts 2 in Action
by Don Brown, et al.
Highly
recommended!

Ted Husted is the co-author of
Struts in Action (first edition), a former Struts committer, and
served as Release Manager for the initial Stuts 2 distribution.
When he can, Ted now helps out with the Vosao CMS project
(www.vosao.org), an open source web content management system for
the Google Apps Engine. Ted will be speaking at ApacheCon NA in
November 2010 on the “Secret Life of Open Source” and “.NET @
Apache.org”. He works as a Business Analyst with
NimbleUser, a technology company helping professional and trade
associations do more with web-based applications.

 

This article originally appeared in Java Tech Journal – Java Web
Frameworks – check out more
of that issue here
!


Author
TedHusted
Ted Husted is a business analyst, best-selling author, and regular speaker at ApacheCon and the Ajax Experience. He now works with NimbleUser, a systems integrator specializing in non-profits. Ted is also a former member of the Apache Struts project and co-founder of the Apache (Jakarta) Commons
Comments
comments powered by Disqus