Struts: MVC meets JSP

James Turner, Kevin Bedell
Adapted from: Struts Kick Start
2003-09 1

Agenda
What is Struts? A Brief Review of MVC A Look at a Simple Struts Example The Struts Tag Library Advanced Features of Struts

2003-09

2

Who Are We? - James
Director of Software Development, Benefit Systems Inc. 23 years of development experience. Author of JSP & MySQL Web Applications, Struts Kick Start, JSF Kick Start (Forthcoming, Fall 2003) Committer status on Apache Commons and Apache Struts.
2003-09

3

Who Are We? - Kevin
E-Business Architect, Sun Life Financial. BS Engineering, MBA. Microsoft MCSE Sun Certified Java Programmer Co-Author, "Struts Kick Start", SAMS Publishing Co-Author, "Axis: The Definitive Guide", O'Reilly Contributing Editor, Linux Business & Technology
4

2003-09

What is Struts?
Struts implements the Model-ViewController design pattern for JSP. Pioneered by Craig McClanahan of Sun. Maintained as part of the Apache Jakarta project. Currently in final betas for a 1.1 release.

2003-09

5

The Components of Struts
Struts consists of two main components:
1.

2.

The servlet processing portion, which is responsible for maintaining control of user sessions and data, and managing workflow. The tag libraries, which are meant to reduce or eliminate the use of Java scriptlets on the JSP page.

2003-09

6

The Power of Struts
Of the two, the tag libraries are the most visible part, but also the least important part of Struts (at least in the long run.) Many of the tag libraries are already obsolete if you can take advantage of JSTL (i.e., you have a Servlet 2.3 container) Most of the rest will be obsoleted by JSF.
2003-09

7

The Power of Struts (MVC)
The real power of Struts comes from the MVC design pattern that is implemented by the request processor. To understand why this is such a powerful tool, you first need to be familiar with MVC

2003-09

8

The MVC Pattern
The MVC (or model 2) design pattern is intended to separate out the everchanging presentation layer (the JSP page) from the web application control flow (what page leads to what) and the underlying business logic.

2003-09

9

The Three Pieces of MVC
The Model – The actual business data and logic, such as an class representing users in the database and routines to read and write those users. The View – A separate class which represents data as submitted or presented to the user on the JSP page. The Controller – The ringmaster who decides what the next place to take the user is, based on the results of processing the current request.
10

2003-09

MVC and Struts
The best way to learn both MVC and Struts is to see it in operation in a simple application. Let’s look at a basic user registration form implemented using Struts. This walk-through skips all the basic configuration steps and focuses on features.
See Struts Kick Start for all the gory details of setting up Struts. http://www.strutskickstart.com

2003-09

11

The Model
The model isn’t part of Struts per se, it’s the actual back-end business objects and logic that Struts exposes to the user. In this case, we’ll write a very simple bean that implements a User object. Note: All example code omits imports for brevity.
2003-09

12

package strutsdemo; public class User { private String username = null; private String password = null; public String getUsername () { return username; } public void setUsername(String name) { username = name; } public String getPassword () { return password; } public void setPassword(String pw) { password = pw; } public static User findUser(String username) { User u = new User(); u.setUsername(username); u.setPassword(“test”); // dummy implementation return u; } }
2003-09

13

The Model (cont)
No rocket science so far, the Model (in this case) is a simple bean with a dummied-up load method that just creates a test user. The key point of MVC is that the model doesn’t get directly exposed to the view (the JSP page in Struts.) So how is data passed back and forth to the user?
2003-09

14

Enter the View
The view is an placeholder object used in association with the JSP pages, and which holds a temporary copy of the model. Why do this? Well, suppose you are editing a model object, and the form submission fails during validation. If the model = the view, the model is now in an inconsistent state and the original values are lost.
2003-09

15

Defining the View
With Struts 1.1, there are now two different ways to define a view object (known as an ActionForm)
You can create a bean manually, with manual form validation. Or you can use DynaBeans in combination with the Validator Framework.

2003-09

16

A Manual ActionForm
package strutsdemo.struts.forms; public class UserForm extends ActionForm { private String username = null; private String password = null; public String getUsername () { return username; } public void setUsername(String name) { username = name; } public String getPassword () { return password; } public void setPassword(String pw) { password = pw; }

2003-09

17

A Manual ActionForm (cont)
public ActionErrors validate(ActionMapping map, HttpServletRequest req) { ActionErrors errors = new ActionErrors(); if ((username == null) || (username.size() == 0)) { errors.add(“username”, new ActionError(“login.user.required”)); } if ((password == null) || (password.size() == 0)) { errors.add(“password”, new ActionError(“login.passwd.required”)); } return errors; } }

2003-09

18

Key Points for ActionForms
In general, all fields should be Strings. This preserves the contents of the field if it doesn’t match against the required type
so if you type in “1OO” (rather than 100) for a field that needs to be a number, the field contents will be preserved when it returns to the input form.

2003-09

19

More on ActionForms
If an ActionForm doesn’t implement validate, the default validate (which does nothing) is run. If an ActionForm overrides validate, it controls whether a form passes validation or not. If the ActionErrors object returned has size > 0, control is returned to the input page.
2003-09

20

A Common ActionForm Gotcha
Let’s say you have a boolean property called isJavaGeek tied to a checkbox on a page. You submit the form with the checkbox checked. Then you hit the back button (or it returns to the page because of a validation error), and you uncheck the box.
2003-09

21

A Common ActionForm Gotcha
The problem: Because by the HTML standard, unchecked checkboxes don’t get placed on the request, the form object will not get the new value because the reflection will never occur to change the value of isJavaGeek The solution: Implement the reset() method on the ActionForm.
2003-09

22

Using Struts on the JSP Page
Let’s take a look at the input form that supplies our newly created ActionForm with values Struts uses the struts-html taglib to make interacting with the view easy.

2003-09

23

login.jsp
<%@ page language=“java” %> <%@ taglib uri=“/WEB-INF/struts-html.tld” prefix=“html” %> <head><title>Log in Please</title></head> <h1>Log In Please</h1> <html:form action=“/login”> <html:errors property=“username”/><BR> Username: <html:text property=“username”/><BR> <html:errors property=“password”/><BR> Username: <html:password property=“password”/> <html:submit/> </html:form>

2003-09

24

Controlling Flow with Actions
The actual processing of forms occurs in Actions. The action is the link between the view and the backend business logic in the model. The Action is also responsible for determining the next step in the pageflow.
2003-09

25

A Simple Action Class
package strutsdemo.struts.actions; public class LoginUserAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse resp) { UserForm uf = (UserForm) form; User u = User.findUser(uf.getUsername()); ActionErrors errors = new ActionErrors(); if (u == null) { errors.add(“username”, new ActionError(“login.username.notfound”)); } else if (!uf.getPassword().equals(u.getPassword()) { errors.add(“password”, new ActionError(“login.password.invalid”)); }
2003-09

26

A Simple Action Class (cont)
if (errors.size() > 0) { saveErrors(request, errors); return mapping.getInputForward(); } request.getSession().setAttribute(“currentUser”, u); return mapping.findForward(“success”); } }

2003-09

27

Fun Things to do with Actions
If the Action returns null, no further processing occurs afterwards. This means you can use an Action to implement pure servlet technology, like generating a CSV file or a JPG. You can chain together Actions using the configuration file, useful for instantiating multiple ActionForms.
2003-09

28

A Note About Validation
Because the ActionForm shouldn’t contain business logic, the Action may need to do some validations (such as username/password checking) Since the Action isn’t called until the ActionForm validates correctly, you can end up getting new errors at the end of the process.
2003-09

29

Tying it All Together
So far, you’ve seen all the components that come together to form a Struts request cycle, except… The piece that ties all the disparate pieces together. In Struts, this is the struts-config.xml file.

2003-09

30

A Simple Example of the Config
<struts-config> <form-beans> <form-bean name=“userForm” type=“strutsdemo.struts.forms.UserForm”/> </form-beans> <action-mappings> <action path=“/login” name=“userForm” scope=“request” validate=“true” type=“strutsdemo.struts.actions.LoginUserAction” input=“/login.jsp”> <forward name=“success” path=“/mainMenu.jsp”/> </action> </action-mappings> </struts-config>

2003-09

31

Things to Notice in the Config
For space reasons, the XML header was ommitted. Form-beans define a name that Struts uses to access an ActionForm. Actions define:
What URL path the action is associated with. What JSP page provides the input. What JSP pages can serve as targets to the Action. What Action is used to process the request. Whether the form should be validated.
32

2003-09

Built-in Security
Because all JSP pages are reached via calls to Actions, they end up with URLs like “/login.do” The end-user never sees the actual URL of the underlying JSP page. You can place access control in your Actions, avoiding having to put checks on all your JSP pages. You can also use container-based security to control access via roles directly in the config.
2003-09

33

The Struts Tag Libraries
With the exception of the HTML and TILES libraries, they have all been superceded by JSTL. However, if you can’t move to a Servlet 2.3 container, they offer a lot of the power of JSTL.

2003-09

34

Examples of Struts Tags vs JSTL
Struts:
<logic:iterate id=“person” name=“people”> <logic:empty name=“person” property=“height”> <bean:write name=“person” property=“name”/> has no height<BR> </logic:empty> </logic:iterate>

JSTL:
<c:forEach var=“person” items=“${people}”> <c:if test=“${empty person.height}”> <c:out value=“${person.name}”/> has no height<BR> </c:if> </c:forEach>

2003-09

35

The Struts Tag Libraries
Logic – Conditional Display, Iteration Bean – Data Instantiation and Access Html – Forms and Links Nested – Access to Properties of Beans Tiles – Structured Layout of Pages

2003-09

36

Advanced Tricks with Struts

DynaForms allow you to avoid writing ActionForms alltogther.

2003-09

37

<form-bean name=“userForm” type=“org.apache.struts.actions.DynaAction Form”> <form-property name=“username” type=“java.lang.String”/> <form-property name=“password” type=“java.lang.String”/> </form-bean> -------------------------------DynaActionForm uf = (DynaActionForm) form; String userName = (String)uf.get(“username”);

2003-09

38

How to Validate DynaForms
Since you don’t define DynaForms as explicit classes, how do you do validation? Answer 1: Extend the DynaActionForm class and write validate() methods. Answer 2: Using the Struts Validator Framework.
Based on the Commons Validator package. Uses an XML file to describe validations to be applied to form fields.

2003-09

39

The Validator Framework
Predefined validations include:
Valid number: float, int Is a Credit Card number Length Checks Blank/NotBlank Regular Expression Matches Plus the all-purpose cross-field dependency: requiredif
2003-09

40

<form name=“medicalHistoryForm"> <field property=“lastCheckup" depends=“required"> <arg0 key=" medicalHistoryForm.checkup.label"/> </field> <field property=“weight" depends=“required,float"> <arg0 key=" medicalHistoryForm.weight.label"/> </field> </form>

2003-09

41

Validwhen appears in Struts 1.2
<form name=“medicalHistoryForm"> <field property=“lastMamogram" depends="validwhen"> <arg0 key="dependentlistForm.firstName.label"/> <var> <var-name>test</var-name> <var-value>((gender=“M”) OR (*this* != null)) </var-value> </var> </field> </form>

2003-09

42

Summary
Struts 1.1 is about to be released. Supported by all major IDEs (Eclipse, IdeaJ, Jbuilder, etc) Widely accepted and integrated into most J2EE platforms. Want to learn more?
“We’ve seen no better resource for learning Struts than Struts Kick Start. “ -- barnesandnoble.com

2003-09

43

Master your semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master your semester with Scribd & The New York Times

Cancel anytime.