Apache Struts 2 Web Application Development
Struts 2.1 is a modern, extensible, agile web application framework, which is suitable for
both small- and large-scale web applications.
The book begins with a comprehensive look at the basics of Struts 2.1, interspersed with
detours into more advanced development topics. You’ll learn about configuring Struts 2.1
actions, results, and interceptors via both XML and Java annotations. You’ll get an
introduction to most of the Struts 2.1 custom tags, and also learn how they can assist in
rapid application prototyping and development.
From there, you’ll make your way into Struts 2.1′s strong support for form validation and
type conversion, which allows you to treat your form values as domain objects without
cluttering your code. A look at Struts 2.1′s interceptors is the final piece of the Struts 2.1
puzzle, which allows you to leverage the standard Struts 2 interceptors, as well as
implement your own custom behavior.
After covering Struts 2.1, you’ll journey into the world of JavaScript (a surprisingly
capable language), the Document Object Model (DOM), and CSS, and learn how to
create clean and concise client-side behavior. You’ll leverage that knowledge as you
move on to Struts 2 themes and templates, which give you a powerful way to encapsulate
site-wide user interface behavior.
The book closes with a look at some tools that make the application development life
cycle easier to manage, particularly in a team environment, and more automatic.
What This Book Covers
Chapter 1 gives us a bird’s-eye view of Struts 2 and examines some useful techniques of
lightweight, agile development.
Chapter 2 gives an introduction to Struts 2 application configuration, using both XML
and annotations. It also covers the beginning of our sample application, RecipeBox.
Chapter 3 covers some of the functionality provided by Struts 2′s ActionSupport class,
including I18N, and a first look at form validation. It also covers some basic RecipeBox
functionality after gathering some user stories.
Chapter 4 examines several common, standard Struts 2 result types. It also covers how to
write our own custom result types.
Chapter 5 gives an in-depth look at the generic Struts 2 custom tags. These include tags
for iteration, list generation, conditionals, and internationalization (I18N).
Chapter 6 continues our exploration of Struts 2 custom tags, focusing especially on its
form tags.
Chapter 7 examines Struts 2 form validation, including both XML and
annotation-driven validation. It also teaches more about how Struts 2 converts
our form values into domain objects, and shows how to create our own type converters to
handle custom data types.
Chapter 8 finishes our comprehensive introduction to Struts 2, by checking out
the included Struts 2 interceptors. It also discusses how to write and configure our
own interceptors.
Chapter 9 looks at how to handle errors in Struts 2, as well as discusses error and
exception handling in general. It also covers some general Java logging topics, focusing
on using Apache Commons Logging and Log4J.
Chapter 10 explores how to best leverage JavaScript and how to keep it modular.
Chapter 11 covers the client-side functionality, which depends on more than JavaScript.
By using CSS and the DOM effectively, we can accomplish a lot with a minimal amount
of code.
Chapter 12 covers Struts 2 themes and templates. The themes and templates in Struts 2
allow for application-wide functionality on the client side, keeping our JSP pages
lightweight and adaptable. Rather than writing boilerplate HTML on our pages, we can
separate it into themes and templates.
Chapter 13 takes a look at some of Struts 2′s built-in support for Ajax using the Dojo
tags. It also covers the Struts 2 REST plug-in that furthers our “convention over
configuration” path.
Chapter 14 covers how to apply the TDD concepts to several testing aspects, including
unit, functional, and acceptance tests.
Chapter 15 looks at many aspects of documentation, including “self-documenting” code,
Javadocs, generators, methodologies, and so on, with a focus on automating
as much documentation as possible.
Documenting our Application
Every developer’s favorite task is documenting their application (or so I’ve heard).
As irritating as documentation can be, delivering a complete solution implies
comprehensive, usable documentation. This goes beyond (but includes) typical
Javadocs. However, more is required in order to understand how a particular
application works, how its parts fit together, where dependencies lie, and so on. Even
us, the developers, benefit from having a wide variety of documentation available.
In this chapter, we’ll look at the ways in which we can document our applications,
coding styles that can aid in understanding, tools and techniques for creating
documentation from application artifacts, different types of documentation for
different parties, and so on.
Documenting Java
Everybody knows the basics of documenting Java, so we won’t go into much
detail. We’ll talk a bit about ways of writing code whose intention is clear, mention
some Javadoc tricks we can use, and highlight some tools that can help keep our
code clean. Clean code is one of the most important ways we can document our
application. Anything we can do to increase readability will reduce confusion later
(including our own).
Self-documenting code
We’ve all heard the myth of self-documenting code. In theory, code is always clear
enough to be easily understood. In reality, this isn’t always the case. However, we
should try to write code that is as self-documenting as possible.
Keeping non-code artifacts in sync with the actual code is difficult. The only artifact
that survives a project is the executable, which is created from code, not comments.
This is one of the reasons for writing self-documenting code. (Well, annotations,
XDoclet, and so on, make that somewhat less true. You know what I mean.)
There are little things we can do throughout our code to make our code read as much
like our intent as possible and make extraneous comments just that: extraneous.
Document why, not what
Over-commenting wastes everybody’s time. Time is wasted in writing a comment,
reading it, keeping that comment in sync with the code, and, most importantly, a lot
of time is wasted when a comment is not accurate.
Ever seen this?
a += 1; // increment a
This is the most useless comment in the world.
Firstly, it’s really obvious we’re incrementing something, regardless of what that
something is. If the person reading our code doesn’t know what += is, then we
have more serious problems than them not knowing that we’re incrementing, say,
an array index.
Secondly, if a is an array index, we should probably use either a more common array
index or make it obvious that it’s an array index. Using i and j is common for array
indices, while idx or index is less common. It may make sense to be very explicit in
variable naming under some circumstances. Generally, it’s nice to avoid names such as
indexOfOuterArrayOfFoobars. However, with a large loop body it might make sense
to use something such as num or currentIndex, depending on the circumstances.
With Java 1.5 and its support for collection iteration, it’s often possible to do away
with the index altogether, but not always.
Make your code read like the problem
Buzzphrases like Domain Specific Languages (DSLs) and Fluent Interfaces
are often heard when discussing how to make our code look like our problem.
We don’t necessarily hear about them as much in the Java world because other
languages support their creation in more “literate” ways. The recent interest in
Ruby, Groovy, Scala, and other dynamic languages have brought the concept back
into the mainstream.
A DSL, in essence, is a computer language targeted at a very specific problem. Java
is an example of a general-purpose language. YACC and regular expressions are
examples of DSLs that are targeted at creating parsers and recognizing strings of
interest respectively.
DSLs may be external, where the implementing language processes the DSL
appropriately, as well as internal, where the DSL is written in the implementing
language itself. An internal DSL can also be thought of as an API or library, but one
that reads more like a “little language”.
Fluent interfaces are slightly more difficult to define, but can be thought of as an
internal DSL that “fl ows” when read aloud. This is a very informal definition, but
will work for our purposes.
Java can actually be downright hostile to some common DSL and fl uent techniques for
various reasons, including the expectations of the JavaBean specification. However, it’s
still possible to use some of the techniques to good effect. One typical practice of fl uent
API techniques is simply returning the object instance in object methods. For example,
following the JavaBean specification, an object will have a setter for the object’s
properties. For example, a User class might include the following:
public class User {
private String fname;
private String lname;
public void setFname(String fname) { this.fname = fname; }
public void setLname(String lname) { this.lname = lname; }
}
Using the class is as simple as we’d expect it to be:
User u = new User();
u.setFname("James");
u.setLname("Gosling");
Naturally, we might also supply a constructor that accepts the same parameters.
However, it’s easy to think of a class that has many properties making a full
constructor impractical. It also seems like the code is a bit wordy, but we’re
used to this in Java. Another way of creating the same functionality is to include
setter methods that return the current instance. If we want to maintain JavaBean
compatibility, and there are reasons to do so, we would still need to include normal
setters, but can still include “fl uent” setters as shown here:
public User fname(String fname) {
this.fname = fname;
return this;
}
public User lname(String lname) {
this.lname = lname;
return this;
}
This creates (what some people believe is) more readable code. It’s certainly shorter:
User u = new User().fname("James").lname("Gosling");
There is one potential “gotcha” with this technique. Moving initialization into
methods has the potential to create an object in an invalid state. Depending on the
object this may not always be a usable solution for object initialization.
Users of Hibernate will recognize the “fl uent” style, where method chaining is used
to create criteria. Joshua Flanagan wrote a fl uent regular expression interface, turning
regular expressions (already a domain-specific language) into a series of chained
method calls:
Regex socialSecurityNumberCheck =
new Regex(Pattern.With.AtBeginning
.Digit.Repeat.Exactly(3)
.Literal("-").Repeat.Optional
.Digit.Repeat.Exactly(2)
.Literal("-").Repeat.Optional
.Digit.Repeat.Exactly(4)
.AtEnd);
Whether or not this particular usage is an improvement is debatable, but it’s certainly
easier to read for the non-regex folks.
Ultimately, the use of fl uent interfaces can increase readability (by quite a bit in most
cases), may introduce some extra work (or completely duplicate work, like in the
case of setters, but code generation and/or IDE support can help mitigate that), and
may occasionally be more verbose (but with the benefit of enhanced clarity and IDE
completion support).
Personally, I’m of the opinion that regular expressions are so incredibly important
that it’s worth learning them in their native form, as they can be used in many
environments, including the IDEs so loved by Java developers. Large expressions can
be broken down into components and created by concatenating strings. But the point
here is more about the style of fl uent programming, rather than this specific example.
Contract-oriented programming
Aspect-oriented programming (AOP) is a way of encapsulating cross-cutting
functionality outside of the mainline code. That’s a mouthful, but essentially it
means is that we can remove common code that is found across our application and
consolidate it in one place. The canonical examples are logging and transactions, but
AOP can be used in other ways as well.
Design by Contract (DbC) is a software methodology that states our interfaces
should define and enforce precise specifications regarding operation.
"Design by Contract" is a registered trademark of Interactive Software
Engineering Inc. Other terms include Programming by Contract (PbC),
or my personal favorite, Contract Oriented Programming (COP), which
is how I'll refer to it from now on. I have a lot of respect for Eiffel and its
creator, but this type of trademarking bothers me. Maybe I'll trademark
"Singleton"?!
How does COP help create self-documenting code? Consider the following portion
of a stack implementation:
public void push(final Object o) {
stack.add(o);
}
This seems simple enough. The information available to us is that we can push an
object, whatever pushing means.
What happens if we attempt to push a null? Let’s assume that for this
implementation, we don’t want to allow pushing a null onto the stack.
/**
* Pushes non-null objects on to stack.
*/
public void push(final Object o) {
if (o == null) return;
stack.add(o);
}
Once again, this is simple enough. We’ll add the comment to the Javadocs stating
that null objects will not be pushed (and that the call will fail/return silently). This
will become the “contract” of the push method—captured in code and documented
in Javadocs.
The contract is specified twice—once in the code (the ultimate arbiter) and again
in the documentation. However, the user of the class does not have proof that the
underlying implementation actually honors that contract. There’s no guarantee that
if we pass in a null, it will return silently without pushing anything.
The implied contract can change. We might decide to allow pushing nulls. We
might throw an IllegalArgumentException or a NullPointerException on a
null argument. We’re not required to add a throws clause to the method declaration
when throwing runtime exceptions. This means further information may be lost in
both the code and the documentation.
As hinted, Eiffel has language-level support for COP with the require/do/ensure/
end construct. It goes beyond the simple null check in the above code. It actively
encourages detailed pre- and post-condition contracts. An implementation’s push()
method might check the remaining stack capacity before pushing. It might throw
exceptions for specific conditions. In pseudo-Eiffel, we’d represent the push()
method in the following way:
push (o: Object)
require
o /= null
do
-- push
end
A stack also has an implied contract. We assume (sometimes naively) that once
we call the push method, the stack will contain whatever we pushed. The size
of the stack will have increased by one, or whatever other conditions our stack
implementation requires.
One aim of COP is to formalize the nature of contracts. Languages such as Eiffel
have one solution to that problem, and having it built-in at the language level
provides a consistent means of expressing contracts.
Java, of course, doesn’t have built-in contracts. However, it does contain a mechanism
that can be used to get some of the benefits for a conceptually-simple price. The
mechanism is not as complete, or as integrated, as Eiffel’s version. However, it
removes contract enforcement from the mainline code, and provides a way for both
sides of the software to specify, accept, and document the contracts themselves.
Removing the contract information from the mainline code keeps the implementation
clean and makes the implementation code easier to understand. Having programmatic
access to the contract means that the contract could be documented automatically
rather than having to maintain a disconnected chunk of Javadoc.
SpringContracts
SpringContracts is a beta-level Java COP implementation based on Spring’s AOP
facilities, using annotations to state pre- and post-contract conditions. It formalizes
the nature of a contract, which can ease development.
Let’s consider our VowelDecider that was developed through TDD. We can also use
COP to express its contract (particularly the entry condition). This is a method that
doesn’t alter state, so post conditions don’t apply here.
Our implementation of VowelDecider ended up looking (more or less) like this:
public boolean decide(final Object o) throws Exception {
if ((o == null) || (!(o instanceof String))) {
throw new IllegalArgumentException(
"Argument must be a non-null String.");
}
String s = (String) o;
return s.matches(".*[aeiouy]+.*");
}
Once we remove the original contract enforcement code, which was mixed
with the mainline code, our SpringContracts @Precondition annotation looks
like the following:
@Precondition(condition="arg1 != null && arg1.class.name == 'java.
lang.String'", message="Argument must be a non-null String")
public boolean decide(Object o) throws Exception {
String s = (String) o;
return s.matches(".*[aeiouy]+.*");
}
The pre-condition is that the argument must not be null and must be (precisely)
a string. (Because of SpringContracts’ Expression Language, we can’t just say
instanceof String in case we want to allow string subclasses.)
We can unit-test this class in the same way we tested the TDD version. In fact,
we can copy the tests directly. Running them should trigger test failures
on the null and non-string argument tests, as we originally expected an
IllegalArgumentException. We’ll now get a contract violation exception
from SpringContracts.
One difference here is that we need to initialize the Spring context in our test. One
way to do this is with JUnit’s @BeforeClass annotation, along with a method that
loads the Spring configuration file from the classpath and instantiates the decider as
a Spring bean. Our class setup now looks like this:
@BeforeClass public static void setup() {
appContext = new ClassPathXmlApplicationContext(
"/com/packt/s2wad/applicationContext.xml");
decider = (VowelDecider)
appContext.getBean("vowelDecider");
}
We also need to configure SpringContracts in our Spring configuration file. Those
unfamiliar with Spring’s (or AspectJ’s) AOP will be a bit confused. However, in the
end, it’s reasonably straightforward, with a potential “gotcha” regarding how Spring
does proxying.
<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop:config>
<aop:aspect ref="contractValidationAspect">
<aop:pointcut id="contractValidatingMethods"
expression="execution(*
com.packt.s2wad.example.CopVowelDecider.*(..))"/>
<aop:around pointcut-ref="contractValidatingMethods"
method="validateMethodCall"/>
</aop:aspect>
</aop:config>
<bean id="contractValidationAspect"
class="org.springcontracts.dbc.interceptor.
ContractValidationInterceptor"/>
<bean id="vowelDecider"
class="com.packt.s2wad.example.CopVowelDecider" />
If most of this seems like a mystery, that’s fine. The SpringContracts documentation
goes into it a bit more and the Spring documentation contains a wealth of
information regarding how AOP works in Spring. The main difference between
this and the simplest AOP setup is that our autoproxy target must be a class,
which requires CGLib. This could also potentially affect operation.
The only other modification is to change the exception we’re expecting to
SpringContract’s ContractViolationCollectionException, and our test
starts passing. These pre- and post-condition annotations use the @Documented
meta-annotation, so the SpringContracts COP annotations will appear in the
Javadocs. It would also be possible to use various other means to extract and
document contract information.
Getting into details
This mechanism, or its implementation, may not be a good fit for every situation.
Runtime performance is a potential issue. As it’s just some Spring magic, it can be
turned off by a simple configuration change. However, if we do, we’ll lose the value
of the on-all-the-time contract management.
On the other hand, under certain circumstances, it may be enough to say that once
the contracts are consistently honored under all of the test conditions, the system
is correct enough to run without them. This view holds the contracts more as
an acceptance test, rather than as run-time checking. Indeed, there is an overlap
between COP and unit testing as the way to keep code honest. As unit tests aren’t
run all the time, it may be reasonable to use COP as a temporary runtime unit test or
acceptance test.






August 25, 2009
Uncategorized