Apache Struts 2 Web Application Development

By Dave Newton
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Struts and Agile Development

About this book

Struts 2.1 is a modern, extensible, agile web application framework suitable for both small- and large-scale web applications.

The book begins with a comprehensive look at Struts 2.1 basics, 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 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, allowing 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.

Publication date:
June 2009
Publisher
Packt
Pages
384
ISBN
9781847193391

 

Chapter 1. Struts and Agile Development

Congratulations! Our team has been airdropped into brand-new Java web application with a non-existent specification and a ridiculous deadline. Thought it couldn’t happen? Many factors can conspire to create development nightmares. Staying light on our feet allows us to outmaneuver changes.

We've chosen Struts 2 for our framework. Our deliverables not only include the application and its associated industry-standard buzzwords, but also include complete testing (including unit, functional, and acceptance tests), along with full documentation.

Fortunately for our team (and the client), this is possible and enjoyable! Struts 2 not only meets the requirements of a modern web application development, but it exceeds them. Struts 2 fits nicely into the world of Web 2.0, and allows a rapid development cycle, necessary for both the client and developer to remain competitive.

Struts 2 in a nutshell

Struts 2 began as WebWork. It was an answer to some of the perceived deficiencies in Struts 1—arguably the most popular and long-lived Java web application framework. Struts 1 was tied closely to the servlet specification and contained several Struts 1-specific constructs. This made testing difficult. In addition, because the constructs were Struts 1-specific, using them in non-Struts applications was more difficult than necessary.

Struts 2 reduces (and in most cases eliminates) ties to the servlet specification, making the testing process substantially easier. Struts 2 also allows Dependency Injection (DI) at many levels, meaning that both testability and re-usability are enhanced.

Note

Dependency Injection (DI) or Inversion of Control (IoC) will be covered throughout the book, from several angles. In a nutshell, this means that rather than a class deciding which implementation it wants to use, it is told which implementation to use through one of several mechanisms. If you're familiar with Spring or an equivalent, then it is probable that you're already quite comfortable with the idea.

Architecturally, S2 is conceptually simple, if somewhat more complex in practice. The request cycle process can be summarized as: "Requests are filtered through interceptors and are implemented by actions. The actions return results, which are executed and returned to the browser."

The filter dispatcher

Under standard configuration, Struts 2 gets a chance to process every incoming request. It is implemented as a filter (Struts 1 used a servlet) and mapped to all of the requests (Struts 1 was generally mapped to an extension such as *.do). The reason Struts 2 (usually) needs to examine all of the requests will be discussed later. However, for now, it's enough to know that the filter is the first step in processing a Struts 2 request.

Interceptors

Interceptors are similar to Servlet Filters, but specific to Struts 2. Interceptors are configurable for an entire application, groups of Struts 2 actions, a single action, or any combination thereof. Interceptors provide the bulk of the core framework functionality of Struts 2. Most of the "cool stuff" lives in the interceptors!

Validation, page setup, access to session and request parameters, and so on, are all provided by interceptors. They're great for providing wide-ranging functionality that cuts across an entire web application or parts thereof.

For those of us familiar with Struts 1, the (somewhat close) corollary is the Struts 1 request processor. Once, where we might have extended the request processor, we might now configure or implement an interceptor.

Many application will need only the interceptors provided by Struts 2, although we might need to configure them differently. However, many applications can benefit from even very simple custom interceptors. We'll cover details of the most useful and common Struts 2 interceptors as we go along. We will also cover (in: Chapter 8) detailed interceptor configuration and implementation to add impressive and quick-to-implement functionality.

Actions

"Struts 2's actions are POJOs! Struts 2's actions are POJOs!". You'll hear that a lot. Note the following things about Struts 2's actions:

  • Struts 2's actions are not (generally) tied to the servlet spec.

  • They are not required to use any Struts 2-specific constructs.

  • The actions handle form data more elegantly than Struts 1's ActionForm and return simple strings instead of the ActionForward used in Struts 1.

Every Struts 2 action could be a POJO. Unless we want the cool built-in functionality of Struts 2 such as form validation, I18N, and little things like that.

Let's put it this way: Struts 2's actions are more like POJO than ever before and aren't tied to the servlet spec (unless we specifically tie them to it, which is necessary on some occasions). The non-POJO aspects are wrapped up in the ActionSupport superclass, which provides a default implementation of the most useful non-POJO functionality.

This makes testing and reusing actions much easier, and eliminates one of the biggest Struts 1 headaches (we'll cover actions in depth in: Chapter 3).

Results

Results determine what will be sent back to the browser, typically a JSP that produces HTML. Struts 2 has several other result types defined in addition to the standard dispatch to a JSP. These include redirection, redirection to actions, action chaining, FreeMarker templates, file streaming, JasperReports, and more.

We can also create and configure our own result types to provide additional application functionality that is not available in the standard Struts 2 distribution. We'll cover results, configuration, and creation of custom result types in: Chapter 4.

Plug-ins

Struts 2 is extensible using its plug-in mechanism. Plug-ins can be used to provide additional functionality such as the JasperReports result. They could also be used to completely change the way we use Struts 2. An example of this is the REST plug-in, which provides Ruby on Rails-like URL handling and lessens our XML configuration. Plug-ins are a neat way to encapsulate functionality that can be used across our own applications, or even released into the wild for others to use.

 

Struts 2 in a nutshell


Struts 2 began as WebWork. It was an answer to some of the perceived deficiencies in Struts 1—arguably the most popular and long-lived Java web application framework. Struts 1 was tied closely to the servlet specification and contained several Struts 1-specific constructs. This made testing difficult. In addition, because the constructs were Struts 1-specific, using them in non-Struts applications was more difficult than necessary.

Struts 2 reduces (and in most cases eliminates) ties to the servlet specification, making the testing process substantially easier. Struts 2 also allows Dependency Injection (DI) at many levels, meaning that both testability and re-usability are enhanced.

Note

Dependency Injection (DI) or Inversion of Control (IoC) will be covered throughout the book, from several angles. In a nutshell, this means that rather than a class deciding which implementation it wants to use, it is told which implementation to use through one of several mechanisms. If you're familiar with Spring or an equivalent, then it is probable that you're already quite comfortable with the idea.

Architecturally, S2 is conceptually simple, if somewhat more complex in practice. The request cycle process can be summarized as: "Requests are filtered through interceptors and are implemented by actions. The actions return results, which are executed and returned to the browser."

The filter dispatcher

Under standard configuration, Struts 2 gets a chance to process every incoming request. It is implemented as a filter (Struts 1 used a servlet) and mapped to all of the requests (Struts 1 was generally mapped to an extension such as *.do). The reason Struts 2 (usually) needs to examine all of the requests will be discussed later. However, for now, it's enough to know that the filter is the first step in processing a Struts 2 request.

Interceptors

Interceptors are similar to Servlet Filters, but specific to Struts 2. Interceptors are configurable for an entire application, groups of Struts 2 actions, a single action, or any combination thereof. Interceptors provide the bulk of the core framework functionality of Struts 2. Most of the "cool stuff" lives in the interceptors!

Validation, page setup, access to session and request parameters, and so on, are all provided by interceptors. They're great for providing wide-ranging functionality that cuts across an entire web application or parts thereof.

For those of us familiar with Struts 1, the (somewhat close) corollary is the Struts 1 request processor. Once, where we might have extended the request processor, we might now configure or implement an interceptor.

Many application will need only the interceptors provided by Struts 2, although we might need to configure them differently. However, many applications can benefit from even very simple custom interceptors. We'll cover details of the most useful and common Struts 2 interceptors as we go along. We will also cover (in: Chapter 8) detailed interceptor configuration and implementation to add impressive and quick-to-implement functionality.

Actions

"Struts 2's actions are POJOs! Struts 2's actions are POJOs!". You'll hear that a lot. Note the following things about Struts 2's actions:

  • Struts 2's actions are not (generally) tied to the servlet spec.

  • They are not required to use any Struts 2-specific constructs.

  • The actions handle form data more elegantly than Struts 1's ActionForm and return simple strings instead of the ActionForward used in Struts 1.

Every Struts 2 action could be a POJO. Unless we want the cool built-in functionality of Struts 2 such as form validation, I18N, and little things like that.

Let's put it this way: Struts 2's actions are more like POJO than ever before and aren't tied to the servlet spec (unless we specifically tie them to it, which is necessary on some occasions). The non-POJO aspects are wrapped up in the ActionSupport superclass, which provides a default implementation of the most useful non-POJO functionality.

This makes testing and reusing actions much easier, and eliminates one of the biggest Struts 1 headaches (we'll cover actions in depth in: Chapter 3).

Results

Results determine what will be sent back to the browser, typically a JSP that produces HTML. Struts 2 has several other result types defined in addition to the standard dispatch to a JSP. These include redirection, redirection to actions, action chaining, FreeMarker templates, file streaming, JasperReports, and more.

We can also create and configure our own result types to provide additional application functionality that is not available in the standard Struts 2 distribution. We'll cover results, configuration, and creation of custom result types in: Chapter 4.

Plug-ins

Struts 2 is extensible using its plug-in mechanism. Plug-ins can be used to provide additional functionality such as the JasperReports result. They could also be used to completely change the way we use Struts 2. An example of this is the REST plug-in, which provides Ruby on Rails-like URL handling and lessens our XML configuration. Plug-ins are a neat way to encapsulate functionality that can be used across our own applications, or even released into the wild for others to use.

 

Agile in a nutshell


Extreme Programming (XP) was the buzzword several years ago. It involves test-first development, pair programming, on-site customers, and more. Compare and contrast this with the waterfall method (or BDUF: Big Design Up Front), where detailed requirements are built upfront, followed by the application design. Finally, comes the implementation, verification, and maintenance part. It's still (arguably) the most common development model, despite repeated failures.

Many companies are pretty firmly entrenched in the waterfall method (XP or anything like it borders on heresy). The problem is that as soon as the toner on the specification has cooled, it's probably already incomplete or incorrect. As soon as development begins, the unanticipated will almost certainly appear.

At this point, either the original spec (or more likely, an emailed copy of a Word document with a date appended to the filename) might be updated to reflect the new reality, or the software will continue developing until it barely resembles the original design document. Generally, there will either be a formal change management process, or a customer that doesn’t end up with what they wanted. (Or ends up with what they thought they wanted, but they were wrong.).

If the application and specification are significantly out-of-sync, the specification is no longer a useful document. A developer being introduced to the project for the first time needs to either ignore the specification and look only at the code, or reconcile differences between the two.

Whether or not a client buys in to a full-blown agile methodology may not be up to us (the consultant). However, by picking and choosing components typically associated with the agile development, we can get many of the benefits.

User stories

One of the more useful XP concepts is the "user story". User stories capture system interaction at a fairly high level. Details that are unable to be determined without testing, or that are not as important as the basic functionality, may be omitted during the design phase (and may never be formally specified). We'll cover user stories as we develop the sample application.

Testing

One of the most important aspects of agile development is testing and testability. It allows for both minor and localized changes, as well as sweeping application changes, while ensuring that the functionality isn't broken.

Applications can be tested at various levels. At one end of the spectrum is unit testing, focusing on small units of functionality, and preferably not involving any of the other system's components.

Functional testing focuses on the overall system, and can consist of testing the application by using a browser driven by any of several methods. We'll discuss several types of testing in depth in Chapter 14. However, we will touch upon testing issues throughout the book.

Refactoring

Refactoring includes the process of identifying and consolidating similar functionality at any level in the application. Consistent and correct refactoring is made possible (or at least made much easier and more reliable) by the presence of tests. Without the ability to test easily, refactoring becomes an error-prone, hit-or-miss proposition.

Aggressive refactoring at all levels in the application (Java, JSP, HTML, CSS, and so on) can significantly reduce absolute code size, along with the cognitive overhead needed to understand the application.

Short iterations

Which one of the following options would you choose:

  1. 1. Design and code an application, present it to the client, and be presented with a list of changes that necessitate changing the internals of the application itself.

  2. 2. Present small chunks of functionality, so that changes in design or implementation are identified early, and hence the impact is as minimal as possible.

Yes, the first option gives us a chance to do the mythical "complete rewrite". However, clients rarely seem willing to fund the development of the same application twice. Moreover, refactoring is, in essence, a chance to rewrite early and often.

XP's take on this (and it is extreme) is that there should be a client on site during much of the development, providing immediate feedback on the direction of application development. This gives the developers a chance to nip problems in the bud, whether they're issues with the domain model, user interface, documentation, and so on.

While an on-site client might not be possible (or desirable!) it’s easy to give clients access to the work-in-progress. This allows the client to review functionality and provide feedback early in the process. Both functionality and design can be addressed in parallel. This can help identify usability issues, application flow changes, functional requirement changes, and so on.

However, along with shorter iterations comes a responsibility to keep the client informed about the real cost of change, both now and in the future. Big changes (or lots of little ones) may require a change in the schedule, the deliverable, or both.

 

Real applications in a nutshell


Real-world web applications are much more than just the underlying web framework. Database access, CSS, Ajax, reporting, testing, the build and deploy cycle, documentation, and administration, all factor in to deliver a complete application that can be handed off to a client.

Making it pretty

We'll cover some of the most basic aspects of making our application look good, using CSS and Struts 2’s themes and templates. These offload the bulk of "prettification" to FreeMarker templates and keep our JSP (or FreeMarker) pages fairly clean.

We'll include some CSS basics, while focusing on separating content from presentation. We will also see how we can use CSS, along with JavaScript, to provide us with easy ways to enhance functionality, usability, and testability. Along with making our applications look nice, markup that is intelligent and semantic also gives us more ways to manipulate our pages with JavaScript and Ajax.

JavaScript

We'll spend some time looking at JavaScript, which is the dominant player in the browser. While this isn't a complete JavaScript book, it's very important to understand how to use it to good effect, as it's a remarkably powerful language.

Grasping some of the more advanced topics makes working with existing libraries (for example, jQuery, which is used later in the book) much easier. It also makes our own JavaScript much cleaner, safer, and easier to maintain. Like any other language, using JavaScript effectively takes time, but the time it saves over using it poorly is well worth the effort.

Documentation

Documentation, perhaps one of the least entertaining aspects of application development, can be made to be a relatively automated process by using a combination of existing tools and custom tools. A small amount of effort throughout the life of a project can make a big difference and enhance our final deliverable.

All of the rest

Scattered throughout the book will be tips and tricks that can be used to ease our development process, facilitate the creation of useful tools, and open the development process for automation. These tips and tricks enhance our "bag of tricks", making our lives easier, and our clients happier.

 

Getting started


At the time of writing this book, the most recent version of Struts is 2.1.6. Downloading a release is straightforward, just follow the links on the Struts website. There are currently five downloads: "all", "apps", "lib", "docs", and "src". The "all" download, of course, includes everything. The "apps" download includes all of the Struts 2 sample applications, including the "blank" application (which isn't totally blank, but close).

The "lib" download includes all of the libraries required by Struts 2. This includes Struts 2 core libraries, Struts 2 plug-in libraries, and all of their dependencies. The "docs" download contains...wait for it...the documentation, including the API JavaDocs for both Struts 2 and XWork, as well as the entire Struts 2 documentation wiki. Finally, the "src" download contains the source for Struts 2, but not for XWork.

Creating our own applications

There are several ways in which we can create a Struts 2 application:

  1. 1. By copying the "blank" sample application

  2. 2. By manually using the libraries download

  3. 3. By using a Maven archetype

AppFuse also allows the use of Struts 2 for the backend.

Again, we're assuming some general familiarity with JEE web application development, and comfort with whatever development environment we're using.

Doing it "by hand"

We could just grab the necessary libraries from the "lib" distribution and do things completely by hand. It works, and it's simple (in a way). Determining which libraries are necessary can be surprisingly irritating. However, poking inside the blank sample application tells us that we really only need a few.

Note

Getting that list of libraries is left as an exercise for the reader. This seems unnecessarily cruel. However, I really want to foster an attitude of exploration, discovery, and familiarization, with the framework and the tools we can use to expand our own knowledge and skills. Yes, I'm a little mean. By poking around we learn much more than having all the answers handed to us on a silver platter. (Especially, as it's a simple matter of looking inside the blank application WAR file. That’s a hint for the future.)

The biggest drawback to this approach, despite its simplicity, is that as soon as we start adding libraries (which we do in the next chapter), we don't necessarily understand the relationships between required libraries. In other words, we may not understand which libraries depend on which other libraries.

Using Maven

One of the tasks Maven was created to tackle is transitive dependencies. Simply put, Maven allows us to say: "I want to use so-and-so library", and Maven will respond with: "Oh, okay, you also need these other libraries in order to do that, and here they are for you." (Maven is actually capable of much more.)

When we look at the source for the blank sample application, we start getting a handle on how Maven works (sort of), so that we can declare a project's dependencies. However, some of the magic is hidden, as the blank application relies on a non-local resource that declares the bulk of the dependencies.

Another option is to use a Maven "archetype". In this case, it would be a representative Struts 2 application that includes everything necessary to get started. There are a few Struts 2 Maven archetypes, including a generic blank application, a RESTful application (discussed later), and so on. The Struts 2 documentation wiki explains the process of using Maven archetypes. However, you are encouraged to read the Maven documentation if that's the chosen path.

Note

This book takes a non-committal approach to its source. The apps are available as Maven projects, or as complete non-Maven bundles. If you're interested in using Maven archetypes and typing the code yourself (or copying the source into a Maven project), then that's fine. For the most part, I will completely ignore environmental issues to focus solely on the issue(s) at hand.

 

Summary


Struts 2 is a flexible web application framework that can be used to create highly-functional applications very quickly. The features provided by Struts 2 give developers many ways to increase functionality, while keeping the development cost low and the client happy. By leveraging the power of standard browser technologies, along with a combination of existing and custom tools, Struts 2 can be used as an integral part of an agile development process, which eases the creation of complete applications, satisfies the client, and helps the consultant look good in the process.

About the Author

  • Dave Newton

    Dave Newton, a Struts PMC member, has been a professional developer for over twenty years, getting his start in Lisp and Smalltalk development, moving on to a lengthy stint in embedded system, game, and device driver development, before (confusingly) finding himself writing Java-based web applications for a variety of clients.

    He is a strong proponent of agile practices and tool creation and use, particularly in relationship to documentation generation and testing. He's a regular (if crabby) fixture on the Struts user mailing list, prodding people to read the documentation and think outside the box.

    Browse publications by this author
Book Title
Access this book, plus 8,000 other titles for FREE
Access now