Apache Struts 2 Web Application Development - Newton Dave - E-Book

Apache Struts 2 Web Application Development E-Book

Newton Dave

0,0
19,35 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

In Detail

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.

This book provides an in-depth introduction to Struts 2 and crash-courses in JavaScript, CSS, Test-Driven Development, agile programming techniques, and tool development, focusing on the delivery of complete, documented, maintainable web applications.

Approach

This book takes a clear approach, focusing on one topic per chapter, but interspersing other issues in the mainline text and in chapter detours. Taking a practical approach, it discusses agile web development using Struts 2, with plenty of examples for better understanding.

Who this book is for

This book is for Java developers who are interested in developing web applications using Struts. If you need a comprehensive introduction to Struts 2.1, along with the most important aspects of additional web application development technologies, agile programming practices, tool creation, and application life cycle management this book is for you. You don't need to know JavaScript and CSS to use this book as the author will teach you the required basics.

If you are a Struts 1 or WebWork user and wish to go ahead and migrate to Struts 2, this practical guide is also for you.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 483

Veröffentlichungsjahr: 2009

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Table of Contents

Apache Struts 2 Web Application Development
Credits
About the Author
Acknowledgement
About the Reviewers
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code for the book
Errata
Piracy
Questions
1. Struts and Agile Development
Struts 2 in a nutshell
The filter dispatcher
Interceptors
Actions
Results
Plug-ins
Agile in a nutshell
User stories
Testing
Refactoring
Short iterations
Real applications in a nutshell
Making it pretty
JavaScript
Documentation
All of the rest
Getting started
Creating our own applications
Doing it "by hand"
Using Maven
Summary
2. Basic Configuration
Setting up our environment
A sanity-checking application
Configuring web.xml for Struts 2
Writing our first action
Configuring our first action with XML
Configuring our result
Choosing an action method
Getting started with our application
Gathering user stories—defining our application
Building skeletal applications using wildcards
Matching multiple wildcards
More wildcard tricks
Packages and namespaces
Creating site navigation
Including external configuration files
Our application so far
Examining our configuration
Configuration via convention and annotations
The Convention Plug-in and action-less actions
The Convention Plug-in and action configuration
Configuring the Convention Plug-in with annotations
Summary
3. Actions and ActionSupport
ActionSupport and its interfaces
The Action interface
Action's convenience strings
The TextProvider interface
Detour—action properties, JSPs, and more tags
Continuing with message lookup
Parameterized messages
The LocaleProvider interface
The Validateable and ValidationAware interfaces
Implementing our first user story
Refining our story
Creating the recipe form
Adding some validation
Displaying our error messages
More action interfaces
Detour—creating the list of interfaces to explore
Leveraging the IDE
Using the command line
Examining class files
Additional action interfaces
Preparable interface
Accessing scoped attributes (and request parameters)
Accessing servlet objects
Request parameter/action property filtering
Summary
4. Results and Result Types
The dispatcher result type
The redirect result type
The redirectAction result type
The chain result type (action chaining)
The parse parameter and a usecase detour
Displaying the form
Coding our action
Configuring our success result
Type conversion sneak attack
Coding the show action
The FreeMarker and Velocity result types
FreeMarker result configuration
The XSLT result type
The plaintext result
The stream result
The httpheader result
The Tiles and JasperReports results
Creating custom result types
Configuring our custom result type
Writing the action
Implementing our markdown result type
Summary
5. OGNL, the Value Stack, and Custom Tags
OGNL
Contents of the value stack and the <s:property> tag
Escaping values
Default values
Escaping values for JavaScript
Other value stack objects and the debug tag
A dirty EL trick
The <s:set> tag
Calling static methods from OGNL
Conditionals
Collections and iteration
The <s:iterator> tag
Tracking iteration status
CSS detour: Alternating table row background color
The <s:generator> tag
It's not a list, it's an iterator!
Silent death
Another potential stumper (Struts 2.0 only)
What is <s:generator> for?
The <s:append> tag
The <s:merge> tag
The <s:subset> tag
Arbitrary filtering with the <s:subset> tag
Dirty OGNL secrets
The <s:sort> tag
Are the collection tags useful?
Referencing other pages and actions
The <s:include> tag
The <s:action> tag
The <s:url> tag
Summary
6. Form Tags
Form tag basics
The "xhtml" theme in a nutshell
The <s:head> tag
The <s:form> tag
Common input element tag attributes
Values, labels, and names (and keys)
All the rest
Basic rendering
But I don't want tables
Basic form input elements
The <s:textfield>, <s:password>, and <s:hidden> tags
The <s:textarea> tag
The <s:label> tag
The <s:radio> tag
The <s:checkbox> tag
The <s:checkboxlist> tag
Using the <s:checkboxlist> tag to implement a user story
The <s:select> tag
The <s:optgroup> tag
The <s:submit> tag
The <s:reset> tag
Combination form tags
<s:combobox> tag
The <s:updownselect> tag
The <s:optiontransferselect> tag
The <s:doubleselect> tag
Uploading files
Preventing double submits with the <s:token> tag
Summary
7. Form Validation and Type Conversion
Form validation
Manual validation
Configuring XML validation
Customizing validation messages
What validations are available?
The requiredstring validator
The stringlength validator
Detour—playing games with validation messages
The required and int validators
But wait, there's more
The double validator
The email validator
The url validator
The date validator
The regex validator
The expression and fieldexpression validators
Combining validation methods
The conversion validator
The visitor validator
Configuring validation with annotations
The @Validation annotation
The @Validations annotation
The @SkipValidation annotation
The @RequiredFieldValidator annotation
The @IntRangeFieldValidator annotation
The @DoubleRangeFieldValidator annotation
The remaining validation annotations
Client-side validation
Custom validators
Type conversion
The problem
The solution
Defining our own converters
Type conversion usecase—trimmed BigDecimals
Configuring conversion across the entire application
Custom type conversion is handy
Collections
Usecase—adding a list of ingredients
Why add addIngredient()?
Updating our new recipe form
Map-based collections
Summary
8. Interceptors
The basics
Configuring interceptor stacks
Configuring interceptors
Configuring interceptors for individual actions
How interceptors work
Interceptors in the default stack
The exception interceptor
The alias interceptor
The servletConfig interceptor
The prepare interceptor
The i18n interceptor
The chain interceptor
The debugging interceptor
The profiling interceptor
The scopedModelDriven interceptor
The modelDriven interceptor
Getting back to the scopedModelDriven interceptor
The fileUpload interceptor
The checkbox interceptor
The staticParams interceptor
The params interceptor
Ordered parameters and ad hoc factory patterns
The conversionError interceptor
The validation interceptor
The workflow interceptor
Other important interceptors and interceptor stacks
The token interceptor
The store interceptor
The roles Interceptor
The clearSession interceptor
The paramsPrepareParamsStack interceptor stack
Writing our own interceptors
The trim interceptor
Configuring the trim interceptor
The Test Action
Testing the trim interceptor
Modifying application flow with interceptors
Configuring the result
Writing the ResultMappingInterceptor
Writing the ResultMappingInterceptor and making it work
Summary
9. Exceptions and Logging
Handling exceptions in Struts 2
Global exception mappings
Action-specific exception mappings
Accessing the exception
Architecting exceptions and exception handling
Checked versus unchecked exceptions
Application-specific exceptions
Abstracting underlying exceptions
Handling exceptions
Logging
Introduction to logging
Using the loggers
Configuring the loggers
Summary
10. Getting Started with JavaScript
Introduction to JavaScript
Playing with JavaScript
Minor syntax and language notes
Unicode
Whitespace
Semicolons
Null and undefined values
The equal and strict equal operators
The logical OR operator
Variables and scoping
JavaScript data types
Numbers
Decimal, hex, octal
Conversions
Strings
Length and conversions
Conversions to other types
Arrays
Array functions
Exception handling
Introduction to JavaScript objects and OOP
Open objects and object augmentation
Object values can be functions
Object maker functions
Functions
Function parameters
Some trickery
Inner functions
Closures
Introduction to JavaScript classes
Creating classes
Variable and function access
JavaScript's "this" keyword
Prototypes
JavaScript modules and OOP
Creating a namespace
Summary
11. Advanced JavaScript, the DOM, and CSS
The importance of markup
ID or style attribute?
Dressing up our form
JavaScript modules and jQuery
Adding onclick handlers
Using a function builder
Of what value is this
Accessing module data
The final trick
Adding dynamic form elements
Identifying where to add the elements
The JavaScript "Recipe" module
Summary
12. Themes and Templates
Extracting the templates
A maze of twisty little passages
Creating our theme
Other uses of templates
Summary
13. Rich Internet Applications
What this chapter is and isn't
Dojo tags
Simple use cases really are simple
The Dojo <sx:head> tag
The Dojo <sx:a> tag
A brief side journey on topics
The Dojo <sx:div> tag
Finishing our user story
Highlighting the need to know
Dojo and forms
The REST plug-in
REST in a nutshell
The REST plug-in in a nutshell
REST plug-in URLs
REST plug-in results
A web browser client example
The REST controller
REST controller responses
An example of a useful client
A command-line example
Custom content handler example
YAML in a nutshell
Writing our YAML handler
Configuring our YAML handler
Handling our YAML
Summary
14. Comprehensive Testing
Test-driven development
Pay as we go
Unit testing
Unit tests focus code intent
Keep tests small
Test, code, refactor—the "heartbeat" of TDD
JUnit
Revisiting our iterator filter
The test environment
The initial test stub
Testing vowel recognition
Testing non-string parameter exceptions
Test granularity and test setup
TestNG
Legacy code and unit testing
Simple action testing
Detour: Dependency Injection (Inversion of Control)
Dependency Injection helps us test
Detour: Struts and Spring in a nutshell
Spring web.xml configuration
Spring context configuration file
Testing Struts 2 in context
Testing a Struts interceptor
Client-side (functional) testing
Selenium
Selenium RC
The test scenario
Our first Selenium test
Other forms of testing
Acceptance testing
Load testing
Load testing with JMeter
Recovery testing
Summary
15. Documenting our Application
Documenting Java
Self-documenting code
Document why, not what
Make your code read like the problem
Contract-oriented programming
SpringContracts
Getting into details
Javadocs
Always write Javadocs!
The first sentence
Add information beyond the API name
Write for multiple formats
Generating targeted Javadocs
Visibility
The -exclude argument
The -use argument
Creating new Javadoc tags with the -tag argument
Never write Javadocs!
Never write inline Java comments!
Using UML
Package diagrams
Class diagrams
Sequence diagrams
Documenting web applications
High-level overviews
Documenting JSPs
Documenting JavaScript
Documenting interaction
More UML and the power of scribbling
Don't spend so much time making pretty pictures
User documentation
Documenting development
Source code control systems
Code and mental history
Commit comment commitment
When (and what) do we commit
Branching
Branching discipline
Issue and bug management
Linking to the SCCS
Wikis
RSS and IRC/chat systems
Word processor documents
Summary
Index

Apache Struts 2 Web Application Development

Dave Newton

Apache Struts 2 Web Application Development

Copyright © 2009 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, Packt Publishing, nor its dealers or distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

First published: June 2009

Production Reference: 2040609

Published by Packt Publishing Ltd. 32 Lincoln Road Olton Birmingham, B27 6PA, UK.

ISBN 978-1-847193-39-1

www.packtpub.com

Cover Image by Vinayak Chittar (<[email protected]>)

Credits

Author

Dave Newton

Reviewers

Sandeep Jadav

Dale Newfield

Michael Minella

Sharad Sharma

Acquisition Editor

Viraj Joshi

Development Editor

Ved Prakash Jha

Technical Editor

Gaurav Datar

Copy Editors

Sumathi Sridhar

Leonard D'Silva

Indexer

Monica Ajmera

Editorial Team Leader

Akshara Aware

Project Team Leader

Lata Basantani

Project Coordinator

Abhijeet Deobhakta

Proofreader

Joel T. Johnson

Production Coordinators

Shantanu Zagade

Adline Swetha Jesuthas

Cover Work

Shantanu Zagade

About the Author

Dave has been programming for as long as he can remember, and probably a bit longer than that. He began by playing a Star Trek game on a library computer, and quickly graduated to educating his grade school teachers about computers and the BASIC language. Receiving a TRS-80 Model 1 was pretty much the end of his social life, and he's never looked back.

A diverse background in both programming languages and problem spaces has provided him with a wide range of experience. Using a diverse set of languages, which includes Pascal, Forth, Fortran, Lisp, Smalltalk, assembly, C/C++, Java, and Ruby, brings an appreciation for many programming paradigms. Working on AI, embedded systems, device drivers, and both desktop and web application programming, has brought him an appreciation for the problems and solutions that each environment offers.

Even after thirty years of typing in his first infinite loop, he's still entertained by the process of programming. He never tires of looking for ways to do less work, and is convinced that he should never have to repeat himself to a computer. He still occasionally writes an infinite loop.

Acknowledgement

I'd like to thank Packt for providing me an opportunity to share what I hope is some useful information about my favorite Java web application framework, Struts 2, and along the way, throw in some techniques I've found my clients appreciate (and many of them mean I get to do less work, so it's a win-win!)

My parents, of course, deserve far more thanks than I could ever hope to express. From them, I received a robust sense of exploration and curiosity, which are traits that have served me well during my personal and professional career. They, and the rest of my family, have prodded me along by continually asking, "How's the book coming?", which was surprisingly motivating. They have also provided, along with my friends, much needed moral support during recent months.

I'd like to thank my co-workers, who have zero compunction about telling me when I'm completely wrong, and who provide me with a constant stream of ideas about programming, the associated processes, and how to make programming easier and more flexible.

The creators of the frameworks and libraries we use every day deserve more than they usually receive. Putting one's code out there for everyone to see and use is a brave step. They're under-appreciated when everything works, and unfairly punished when it doesn't. I hope this book pays homage to them in some small way, and contributes back to the various communities that have made my programming work easier.

Finally, the open source and Java communities deserve a hearty "Huzzah!" It includes places like the Struts 2 mailing lists, where all types of developers contribute by asking and answering questions, making suggestions, and politely reminding those involved with the framework that our documentation could be better. It also includes JavaRanch, where "No question is too simple", and sometimes the "simplest" questions turn out to be surprisingly interesting. Finally, the Apache Foundation and fellow Struts developers, who have made Struts possible in all its incarnations. All those people who write the code that we use, contribute to discussions, and try to help others out know who they are. I can't possibly begin to list all of them, but thanks.

About the Reviewers

Sandeep Jadav has been in the IT industry for three years and is currently working as a Software Engineer for an IT firm. Sandeep is an MCA qualified professional and is well-versed with Java technologies. He empowers people around him to work and play better, by helping them resolve complex issues with the simplest and most durable solutions.

In addition to reviewing, Sandeep has a history of using his technical skills for more practical purposes—providing technical leadership to past companies. He has an experience in developing on a large scale, n-tier and Web applications, for business and engineering uses.

Sandeep has a large network of friends and makes frequent contributions to a variety of content areas in many online IT communities.

I would first like to thank Packt Publishing, and the author Dave Newton, for spearheading this edition of Apache Struts 2 Web Application Development, and giving me an opportunity to revisit and improve upon the first efforts.

I am deeply grateful to my family for allowing me to encroach on many months of what should have been my family's quality time.

I extend my deepest appreciation to my friends, for all their support, encouragement, and guidance throughout my work.

I appreciate Packt Publishing for allowing me to gain a very new and delighting experience of reviewing the book.

While reviewing may seem a solitary pursuit, it is actually very much a collaborative effort, and as such, I extend my thanks and appreciation to my author, editor, and the staff at Packt Publishing for their support throughout this project.

Finally, I especially thank Payal for providing great support on each and every step of my life.

Dale Newfield is a computer scientist trained at Carnegie Mellon and the University of Virginia (ABD). Mr. Newfield has designed, built, and maintained a wide variety of systems in many languages. He has vertical knowledge in fields as disparate as graphics, user interfaces, virtual environments, networking, network technology design, network modeling, distributed and disconnected computation, bioinformatics, along with both web and POS systems requiring tight integration of hardware and software. Having built scalable web applications using both Struts1 and Struts2, his input was helpful in keeping this text focused on teaching best practices.

Michael T Minella has been working with, and teaching about, open source software and agile methodologies for over seven years. He holds degrees from Northern Illinois University and DePaul University in Computer Science and E-Commerce Technologies respectively.

Michael lives just outside Chicago, IL, and works at a major financial exchange there. In addition to his day job, Michael currently teaches at DeVry University, has authored a Refcard on JUnit and EasyMock (http://refcardz.dzone.com/refcardz/junit-and-easymock), and maintains the site http://www.michaelminella.com.

Michael would like to thank his wife Erica for her continued support in all the ways he expands his career.

Sharad Sharma is working as a Software Engineer with a reputed MNC. He completed his Bachelors in Technology (B.Tech) from Sikkim Manipal University, Sikkim, and has a passion to learn and teach new technologies. He has successfully completed many projects based on Java/J2EE technology. In spite of having less experience, due to his dedication and hard work, he was able to achieve the top position among all the developers of the organization. This is the first book he has worked upon and wishes to work on many more in future.

I would like to thank my family and friends for the support they have provided me in all the areas.

Preface

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.

What you need for this book

You'll need all the typical Java web application development tools. An IDE is very handy, but it doesn't matter which one you use. Almost any modern application server can be used to run the sample application.

Having an Internet connection while reading is extremely useful. The Struts 2 download includes the documentation wiki, along with the XWork and Struts 2 API Javadocs. However, we may also need to reference the Servlet API, various library APIs, and so on. Having access to the Struts 2 user mailing list can also be very beneficial, as sometimes searching the web for a question is the quickest way to get it answered.

The most important requirements aren't dependent on a particular Java version or specification. Curiosity, willingness to experiment, and patience will never be written up as a JSR, but they're critical qualities in a developer. It's perfectly fine to never learn the ins and outs of a framework. However, by digging into the documentation, and especially the source, we gain a much better understanding of why things happen the way they do. This increases our efficiency, our usefulness, and our value.

Who this book is for

This book is for Java developers who are interested in developing web applications using Struts. If you need a comprehensive introduction to Struts 2.1, along with the most important aspects of additional web application development technologies, agile programming practices, tool creation, and application life cycle management, this book is for you. You needn't know JavaScript and CSS to use this book, as the author will teach you the required basics.

If you are a Struts 1 or WebWork user, and wish to go ahead and migrate to Struts 2, this is a perfectly practical guide for you.

Conventions

In this book, you will find a number of styles of text that distinguish between different kinds of information. Here are some examples of these styles, and an explanation of their meaning.

Code words in text are shown as follows: "ActionSupport is an XWork class that provides validation and default implementations of several common interfaces needed for I18N."

A block of code will be set as follows:

package com.packt.s2wad.ch03.actions.i18n; public class TextExamplesAction extends ActionSupport implements TextInterface { private static Log log = LogFactory.getLog(TextExamplesAction.class); public String execute() throws Exception { log.debug(getText("from.class.props")); return SUCCESS; } }

When we wish to draw your attention to a particular part of a code block, the relevant lines or items will be shown in bold:

<!-- Incorrect "validation" interceptor configuration. --> <action name="brokenConfiguration"

Any command-line input or output is written as follows:

$ find . -name "*.java" | xargs grep -l "public interface" ./com/opensymphony/xwork2/Action.java

New terms and important words are shown in bold.

Note

Warnings or important notes appear in a box like this.

Tip

Tips and tricks appear like this.

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or may have disliked. Reader feedback is important for us to develop titles that you really get the most out of.

To send us general feedback, simply drop an email to <[email protected]>, and mention the book title in the subject of your message.

If there is a book that you need and would like to see us publish, please send us a note in the SUGGEST A TITLE form on www.packtpub.com or email <[email protected]>.

If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide on www.packtpub.com/authors.

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.

Downloading the example code for the book

Visit http://www.packtpub.com/files/code/3391_Code.zip to directly download the example code.

The downloadable files contain instructions on how to use them.

Errata

Although we have taken every care to ensure the accuracy of our contents, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in text or code—we would be grateful if you would report this to us. By doing so, you can save other readers from frustration, and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/support, selecting your book, clicking on the let us know link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata added to any list of existing errata. Any existing errata can be viewed by selecting your title from http://www.packtpub.com/support.

Piracy

Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or web site name immediately so that we can pursue a remedy.

Please contact us at <[email protected]>with a link to the suspected pirated material.

We appreciate your help in protecting our authors, and our ability to bring you valuable content.

Questions

You can contact us at <[email protected]>if you are having a problem with any aspect of the book, and we will do our best to address it.

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.

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:

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.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:

By copying the "blank" sample applicationBy manually using the libraries downloadBy 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.

Chapter 2. Basic Configuration

There are several ways we can configure our Struts 2 applications. These include using everybody's favorite, XML, annotations, and some agile convention-over -configuration methods.

In this chapter we'll cover the minimum necessary to get an application up and running, deferring more complex topics until they're necessary. We'll also begin our journey into lightweight application specification capture by introducing the "user story" concept. Along the way, we'll also begin coding our sample application.

Setting up our environment

Our first task is to get a minimal Struts 2 application running. We're not concerned with application functionality at this point. Our goal is to make sure our builds and deploys are working properly, and to sanity-check our Struts 2 configuration.

We won't cover any IDE-specific setup requirements, or discuss application-server -specific deployment issues. We'll assume an environment including Java 1.5, Servlet 2.4, and JSP 2+.0.

Note

Struts 2.0 is shipped with a set of JAR files usable under Java 1.4. Struts 2.1 no longer ships those libraries. The build process, however, still supports their creation. Struts 2 states a requirement of Servlet 2.4; however, full applications have been run under Servlet 2.3. Again, this capability may not always exist.

The sample applications are available in both a Maven-based distribution and a typical non-Maven directory layout. When we refer to source code, it will almost always be obvious where the directories and files belong (if you're not very familiar with Maven and wish to do things the "Maven way", there's an introduction to the Maven directory layout on the Maven website). The book text assumes that we're already able to get a Java web application compiled and deployed.

Note

Being dependent on an IDE's build process is, in general, a bad idea. Creating a build file allows our build process to be replicated across developers, IDEs, and tools. For example, a build file might be used by a Continuous Integration server to automate compilation, testing, and deployment. We won't delve deeply into the various build process options. Therefor, you may build the book source code in whatever manner you're most accustomed to, including relying on only an IDE.

A sanity-checking application

Our sanity-checking application will be as simple as possible. It will consist of only the minimum libraries necessary to get:

A Struts 2 application runningThe Struts 2 Configuration Browser Plug-inApache Log4J for logging

The Struts 2 Configuration Browser Plug-in lets us check out what Struts 2 thinks our configuration is. (Believe it or not, we do occasionally make mistakes. And ultimately it's the framework that decides what works, not us!)

Log4J is the ubiquitous logging framework. We'll discuss logging later in the book; however, we will use logging before then. Logging statements in the code can be safely ignored until then. The following is the table listing the minimum jar files to get a Struts 2 application running:

Required JAR file(s)

The Struts 2 application

struts2-core-2.1.6.jar

Struts 2 framework.

xwork-2.1.2.jar

XWork framework.

ognl-2.6.11.jar

OGNL, an expression language similar to JSP's EL, used by the Struts 2 tags.

freemarker-2.3.13.jar

FreeMarker, a templating library used to implement Struts 2's UI custom tags.

commons-fileupload-1.2.1.jar

commons-io-1.3.2.jar

commons-logging-1.1.1.jar

FileUpload and IO are used for Struts 2's file uploading capabilities. Logging is used as a logging library wrapper.

struts2-config-browser-Plug-in-2.1.6.jar

Struts 2 Config Browser Plug-in, used to examine application configuration.

log4j-1.2.14.jar

Ubiquitous logging library.

The dependency on the Commons FileUpload package and IO libraries is required, even if we're not uploading files in our application (not having them will cause the application to fail on startup). Note that we can decide to use other file upload libraries.

Note

Including a Struts 2 plug-in may introduce additional dependencies. For example, if we were using the Spring or JasperReports plug-ins, we would need to include their dependencies as well. Otherwise, our application may fail on startup. This is one area in which Maven is particularly handy. (There are dependency managers for Apache Ant as well. However, if we're gluttons for punishment, we can figure out the dependencies on our own.)

Configuring web.xml for Struts 2

Struts 2 dispatches requests with a filter (Struts 1 used a servlet). By default, Struts 2 expects to have a look at all requests. This allows Struts 2 to serve static content from the classpath. This includes JavaScript files for Dojo/Ajax support and FreeMarker templates for Struts 2's custom tags.

The default filter configuration defines the filter and its mapping.

<filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

Note that we map the Struts 2 filter to /*, and not to /*.action (the default Struts 2 extension). We can check whether our server and environment are correctly configured or not. If we visit any URL ending with .action, such as /sanity/foo.action, we should see an error message along the lines of: There is no Action mapped for namespace / and action name foo. This lets us know that Struts 2 at least attempted to process our request, but it couldn't.

If we don't see a similar error message, we have to troubleshoot our build and deploy environment. We can place a simple JSP file in our web context root to determine if we're able to process any request, and to determine whether we're processing JSP files correctly. (The URLs shown in the text won't include host or port information, and assume the root context.)

The specifics of troubleshooting are environment, IDE, and server-specific. These won't be covered here. The usual suspects include classpath and deployment issues.

Writing our first action

We'll start by writing one of the simplest actions possible:

package com.packt.s2wad.ch02.sanity; public class VerySimpleAction { public String execute() { return "success"; } }

As could be seen from above, the action doesn't extend or implement anything—it just has a method named execute() that returns a String. The execute() method is the method Struts 2 will call by default (we'll see how to call others a bit later on).

Configuring our first action with XML

Struts 2 configuration files are expected to be on the classpath (in Struts 1 they were typically located under /WEB-INF). By default, Struts 2 will look for a file named struts.xml in the root of the classpath. The top-level elements of our Struts 2 configuration file are shown here:

<struts> <constant name="struts.devMode" value="true"/> <package name="default" namespace="/" extends="struts-default"> <!-- Action configurations... --> </package> </struts>

The constant element defining struts.devMode puts Struts 2 into "developer mode", increasing the variety and quantity of error messages, reloading Struts 2 configuration files when they change, and so on.

Note

It's also possible to define constants in our web.xml file; this is useful when we don't need an XML-based configuration. Either is acceptable: which is used depends on our needs and preferences. We can also define constants in a file named struts.properties, also on the classpath, but this is not preferred.

The<package> element defines a unit of configuration that our actions will live in. We'll learn more about packages later on. For now, it's enough to know that Struts 2 packages are a way of dividing up an application's functionality and configuration. The namespace attribute defines the URL prefix used for all actions in the package, and should begin with a slash (/).

We configure our simple action by placing an action element inside our package and giving our action a result—a JSP in this case.

<action name="verysimple" class="com.packt.s2wad.ch02.sanity.VerySimpleAction"> <result>/WEB-INF/jsps/verysimple.jsp</result> </action>

For the most part, every action will have name and class attributes. The name attribute is used to map a URL to the action class, specified by the class attribute.

Visiting /verysimple.action should display the contents of our JSP file. If it doesn't, we need to troubleshoot our deployment.

Configuring our result

Results determine what gets returned to the browser after an action is executed. The string returned from the action should be the name of a result. Results are configured per-action as above, or as a "global" result, available to every action in a package.

Results have optional name and type attributes. The default name value is success. In the previous example, we didn't give our result a name. This is because we're returning success from the execute() method, so we don't need to provide the name explicitly.

We also did not define the type attribute of the result. However, we can surmise that as we provided the pathname of a JSP file and we end up seeing the JSP contents in the browser, it's some sort of dispatching process. In fact, the default result type is dispatcher, which dispatches to our JSP using the normal JEE mechanism.

We could have specified both the name and the type attributes as seen here:

<action name="verysimple" class="com.packt.s2wad.ch02.sanity.VerySimpleAction"> <result name="success" type="dispatcher"> /WEB-INF/jsps/verysimple.jsp </result> </action>

If we have a JSP that needs no additional processing, we can omit the action's class attribute. Struts 2 will forward to the JSP (similar to Struts 1's ForwardAction).

<action name="verysimple"> <result>/WEB-INF/jsps/verysimple.jsp</result> </action>

This keeps our JSP files hidden from direct access, and normalizes our application to use only action-based URLs. If we later modified the action to use an action class, the URL wouldn't need to be changed.

Choosing an action method

Our very simple action had a single method, execute(), which will be called by default. Consider an action with multiple action methods:

package com.packt.s2wad.ch02.sanity; public class MethodSelectionAction { public String method1() { return "success"; } public String method2() { return "success"; } }

We can define which method to call using the method attribute as seen here:

<action name="method1" method="method1" class="com.packt.s2wad.ch02.sanity.MethodSelectionAction"> <result>/WEB-INF/jsps/method1.jsp</result> </action> <action name="method2" method="method2" class="com.packt.s2wad.ch02.sanity.MethodSelectionAction"> <result>/WEB-INF/jsps/method2.jsp</result> </action>

Some people prefer creating separate classes for every action, rather than filling an action with several methods. Which route to take can depend on several factors, including personal preference. In some cases it makes perfect sense to keep related functionality in a single class, in other cases it may not.

This last example seems repetitive—the method and result names are the same and the JSPs have similar naming conventions. Struts 2 allows wildcard mapping in several ways, which we'll use now to help lay out our application flow.

Getting started with our application

The traditional model of application development generally starts with the gathering of requirements, followed by separate design, implementation, verification, and maintenance phases. This is called the waterfall method and has been around for many years.

In contrast, more agile models of development focus on the user experience, rapid turnaround of functionalities, and iterative development. This allows our clients to provide feedback in parallel with development, requesting changes in functionality, detecting usability and application flow issues, and so on, early in the process. In many circumstances, this lightweight development cycle can greatly speed up the development time, and deliver an application that more accurately meets the client's needs.

Gathering user stories—defining our application

Our client is building a recipe swapping website, which allows us to build a shopping list from a set of selected recipes. Even without any further requirements, we know we'll need at least five pages—home, recipe search, recipe list, recipe entry, and shopping list.

The first tool we'll explore for capturing application functionality are user stories. User stories are very short descriptions of functionalities (often captured on index cards) that represent a user experience.

User stories do not contain implementation or specification details. A simple example might be: "A user can search for recipes." This might even be expanded to read: "A user can search for recipes by name, ingredients, and so on." Anything significantly more detailed than that is (usually) better expressed as additional, equally short stories.

At this stage in our application requirements gathering, we have five user stories; a couple of them with some minor reminders of expected functionality:

Users see an informational homepageUsers can enter recipes to shareUsers can list recipes
Users can list either their own recipes or recipes from all usersUsers can mark recipes to create a shopping list
Users can search recipes
Users can search by the recipe's name, ethnicity, ingredients, and so on
Users can see a shopping list of ingredients needed for their selected recipes

Obviously, this isn't a complete application specification. However, it is enough to get started on coding the most basic website pages, organizing our development effort, and defining a tangible set of deliverables for the client. Even at this stage, the client might identify some missing functionalities, poor application flow, and so on.

We already know enough to define our action mappings to create skeletons of these pages, although they're a bit heavy considering our simple needs. Struts 2 provides handy wildcard configuration mechanisms making early prototyping really simple.

Building skeletal applications using wildcards

Wildcard action definitions are a quick way to create the skeleton of an application. The following configuration, along with the required JSP files, is enough:

<action name="*"> <result>/WEB-INF/jsps/{1}.jsp</result> </action>

The {1} refers to the first (in this case only) wildcard in the action's name attribute. In this case, visiting /foo.action would return the /WEB-INF/jsps/foo.jsp file.

Supplying a JSP page for each story creates an outline of the application. We might use the previously shown wildcard technique and create home.jsp, recipesearch.jsp, recipelist.jsp, recipenew.jsp, and shoppinglist.jsp. Visiting /home.action would give us /WEB-INF/jsps/home.jsp. We're not actually going to do it this way: the URLs are ugly, and we suspect there must be a better way.

Matching multiple wildcards

We have at least two different major divisions in our application—recipes and shopping lists. In the examples above we had pages such as /recipenew.action, rather than the more natural and hierarchical /recipe/new.action.

One solution would be to use multiple wildcards. Multiple wildcards allow us to map individual portions of the URL to action names, JSPs, directories, and so on. For example, see the following:

<action name="*/*"> <result>/WEB-INF/jsps/{1}/{2}.jsp</result> </action>

Here, we use the first wildcard as a directory (like /WEB-INF/jsps/recipe). The second defines the page (JSP) to be shown, such as list.jsp, new.jsp, and so on. Now the cleaner /recipe/list.action URL would return /WEB-INF/jsps/recipe/list.jsp.

Note

Using this method means that we have a slash (/) in our action name. To do this, we must set the struts.enable.SlashesInActionNames in our struts.xml file (shown next), our web.xml, or (not preferred) our struts.properties file.

<constant name="struts.enable.SlashesInActionNames" value="true"/>

More wildcard tricks