JavaSer ver Pages


The most common view technology in Java web applications nowadays is JavaServer Pages (JSPs). This is partly because JSP is part of the J2EE specification, which means it's guaranteed to ship with the application server or web container of your choice. JSP dates back to 1999, and the latest version is JSP 2.0. JavaServer Pages 2.0 is part of the J2EE 1.4 specification, and hence is already supported by many vendors at the time of this writing.

As did version 1.2, the JSP 2.0 specification improves a lot upon previous versions with respect to clean JavaServer Pages not requiring any Java code and simplifying the way web pages can be authored. JSP 2.0 enhancements include the incorporation of the Expression Language, which was previously part of the Java Standard Tag Library and JSP fragments that allow you to create reusable pieces of JSP code. More information about JavaServer Pages and the changes since 1.2 can be found in Pro JSP Third Edition by Simon Brown et al. (Apress, 2003) or in a series of articles by Hans Bergsten on ONJava (www.onjava.com/pub/a/onjava/2003/11/05/jsp.html).

Important 

JavaServer Pages allow you to incorporate Java code in your view files. This should, however, always be your last resort. Using Java code in your JSPs increases the risk of including non–view-specific functionality, preventing you from easily migrating to another view technology if needed. Furthermore, graphic designers and HTML programmers don't know Java code and won't know how to handle it. Use the Java Standard Tag Library and the expression language instead of Java scriplets as well as the other new features in JSP 2.0 where possible. Last but not least, there are always third-party tag libraries available that might already do what you have in mind.

Note that you can prevent the use of scriptlets by including a JSP property in your web.xml file. The following example disables scriptlets for all JavaServer Pages:

<jsp-property-group>   <url-pattern>*.jsp</url-pattern>   <scripting-invalid>true</scripting-invalid> </jsp-property-group>

Configuring Your Application to Use JSP

To use JSP in your web application, you will have to configure a ViewResolver, just as you would when using any other view technology. There are two view classes you can choose when using JSP. Both take care of preparing the model for the JSP to render. More specifically, this means they merge the model contained by the ModelAndView into the request context, providing the JSP access to it. The first view class provides basic support for old-fashioned JavaServer Pages, not using the Java Standard Tag Library (JSTL). It may or may not be a surprise to you, but for a Servlet container, a JSP is no different from any other request for a resource in the web application — hence the name InternalResourceView (in the package org.springframework.web.servlet.view). The second view class (org.springframework.web.servlet.view.JstlView) has more added value in that it does not merely merge the model in the request context as request attributes, but also prepares the localization context for the JSTL tags dealing with i18n. More specifically, this means you will be able to use the MessageSource(s) defined in your ApplicationContext.

Important 

In order to use the tags from the Java Standard Tag Library, you should use the JstlView. Remember that in Servlet containers implementing the JSP 2.0 specification,you’re not limited any longer to using the expression language only in tags — you can use expressions anywhere now. You can now, for example, write <input type="$ {person.name}"/> instead of having to encapsulate the ${person.name} fragment in a c:out tag. Where possible, try to use JSP 2.0 features — they increase maintainability and readability of your JSPs dramatically!

Creating Forms Using Custom Tags

In the previous chapter we reviewed some of the command controllers and form controllers with which you can create validating forms. Spring provides some custom tags that facilitate the creation of forms using those controllers. The primary goal of Spring's tags is to reduce duplication. Before we look at an example using all the tags, here's a list of those available:

  • spring:bind: Creates a BindStatus object and binds it in the request context making it available to JSTL and custom tags. The BindStatus object holds all relevant information about a specific property of the command object, indicated by the path attribute. Spring:bind is to be used when creating forms and displaying complex properties in a web page without knowing the format of the properties up front.

  • spring:transform: A tag supporting the transformation of properties from other sources than the command object, based on property editors exposed by the spring:bind tag. Spring:transform is especially suited for rendering reference data, such as options in a drop-down box.

  • spring:hasBindErrors: A tag exposing the org.springframework.validation.Errors object for a specific request.

  • spring:message: A Spring equivalent of the JSTL fmt:message tag. The JSTL fmt:message tag cannot be used in certain environments — Spring still allows you to internationalize your application using the spring:message tag.

  • spring:htmlEscape: A tag supporting the escaping of text in HTML. All Spring tags support

HTML escaping through the Boolean htmlEscape attribute.

The tags in the preceding list are best explained by example. Let's first review how to create a form:

public class Reservation {       public void setShow(Show show) { ... }   public Show getShow() { ... }       public void setDate(Date d) { ... }   public Date getDate() { ... }       public void setNumberOfPersons(int p) { ... }   public int getNumberOfPersons() { ... } } 

We will be using the bean shown in the preceding code in our form, having getters and setters for both the date and the show properties. Next, we'll review our form controller.

public class ReservationFormController {       // non-relevant methods left out       protected void initBinder(HttpServletRequest request,        ServletRequestDataBinder binder)    throws Exception {     binder.registerCustomEditor(Show.class, new ShowEditor(...));     binder.registerCustomerEditor(Date.class,          new CustomDateEditor("yyyy-MM-dd", true);   }       protected Map referenceData(HttpServletRequest request)    throws Exception {     Map refData = new HashMap();     List shows; // lookup shows     refData.put("shows", shows);   }       public ModelAndView onSubmit(Object command) {     Reservation r = (Reservation)command;     // do something with the reservation     return new ModelAndView(getSuccessView());   } }

The ShowEditor in this example can transform a Show object to a String representing the name of the show, as well as the reverse (looking up Show objects by name). After we've configured the form controller with an appropriate form view, success view, and command class, we're ready to implement the JSP.

Let's review a fragment of a JSP in which we create a form to allow the user to select a show as part of the reservation. (This view is rendered after a controller has added the list of shows to the model using the referenceData() method.)

<form method="post">     <select name="show">     <c:forEach items="${shows}" var="show">       <option value="${show.name}">${show.name}</option>     </c:forEach>   </select>   <input type="text" name="date"      value="<fmt:formatDate value="${reservation.date}" pattern="yyyy-MM-dd"/>"/>   <input type="text" name="numberOfPersons"     value="${reservation.numberOfPersons}"/> </form>

As you can see, in this example we need to format the date using a pattern also specified when creating the property editor in our controller. Also, we need to pass the name of the show as the value of the options we're creating. Again it's kind of tightly coupled to the property editor we've created in our controller. You can see how this duplication will result in a lot of hassle when you need to change things in your web application (for instance change the property editor to use an identifier instead of a name to resolve shows). Fortunately, Spring provides custom tags so that we don't need to implement JSPs like that in the previous example.

BindStatus and spring:bind

Each and every command controller (that means also the SimpleFormController and the Wizard FormController) has built-in support for the creation of a binding object that facilitates command validation. We've reviewed the functionality of this binding object (org.springframework.validation.Errors) in Chapter 12. In the view layer, you can reuse this object implicitly to retrieve property values from the command object your controller deals with. You can do this through using the <spring:bind> tag. Let's start off with a small example:

 <spring:bind path="command.numberOfPersons">   <input type="text" name="${status.expression}" value="${status.value}"/> </spring:bind> 

Important 

Note that by default, Spring binds the command object (in this case the reservation) in the model (resulting in the object being bound as an attribute to the HttpServletRequest when using JSP) using the identifier command. You can change this behavior by setting the commandName property in your WebApplicationContext. We generally encourage people to do so and to change it to something more sensible. It increases the readability of your JSPs. If we had modified the command name to show, the preceding example would have to be changed to <spring:bind path="show.numberOfPersons">. More information on the command controllers and ways to modify the command name can be found in Chapter 12.

As you can see, we've surrounded the input element by a spring:bind tag. By doing so, we're telling Spring to create a BindStatus object and make it available under the name status. This object contains information about the property mentioned in the path attribute (in this case numberOfPersons), such as the actual value of the property but also error messages. The most important properties (getters) the BindStatus object provides are as follows:

  • status.expression: Returns the expression identifying the property. While submitting the form, Spring will use this expression (after all, it will be communicating back to our controller using HTTP request parameters) to bind the value of the input field to our command object. Use this attribute to set the name property of your HTML input field.

  • status.value: Returns the value of the property (not transformed by any property editor registered for the property). Ideally suited for comparing the property with other objects (to compare a selection and see which object is selected, for example).

  • status.displayValue: Returns the value of the original property, already transformed by the property editor registered for this property. This accessor returns a String, usable in input fields and so on.

  • status.error: Determines whether or not the currently bound property has an error message attached to it (returns a Boolean, so it's easily usable in JSP expressions).

  • status.errorMessages: Retrieves an array of error messages. The error messages are the ones you created in your controller or that were created by any validators associated with your controller.

  • status.errorMessage: Gives you the first error message available.

  • status.errorCode and status.errorCodes: Give you the first available error code and all error codes as an array, respectively. Note that these are the not-localized codes. The other properties such as status.errorMessage return already localized codes.

Because the status.displayValue method not only looks up the value of the property but transforms it to a String using the property editor bound in the controller, you can use this method to remove formatting issues from your form elements:

 <spring:bind path="command.date">   <input type="text" name="${status.expression}"        value="${status.displayValue}">   <c:if test="${status.error}">     <font color="red"><c:out value="${status.errorMessage}"/></font>   </c:if> </spring:bind> 

As you can see, it's easy to incorporate error messages created during the validation stage (in your controller) and also to remove the patterns needed to format dates. They have to be mentioned only in one place, alongside your property editor.

Important 

Be careful when outputting properties using embedded EL expressions, such as <c:out value="${status.errorMessage}"/>. Often they include user input, which might result in problems when not escaping. Use <c:out value="${status.errorMessage}"/> instead, which by default does character escaping.

Furthermore we could have rewritten the above code fragment to include a conditional operator and make it look something like this:

${status.error ? status.errorMessage : ''} 

We've encountered numerous cases where less experienced developers didn't understand how a conditional operator works. Try to imagine what an HTML programmer thinks when she sees such an expression! Use the conditional operator cautiously because often it doesn't increase readability of your JSP code.

spring:nestedPath

Sometimes you might have forms including lots of data as well as data spread across a more complex object model. The spring:nestedPath tag helps limit the amount of JSP code you need to type. The nestedPath tag simply tells any nested bind tags to use the nested path mentioned with the parent tag. We can rewrite the preceding example as follows:

 <spring:nestedPath path="command">   <spring:bind path="date">     <input type="text" name="date" value="${status.displayValue}"/>     ...        </spring:bind> </spring:nestedPath>  

Important 

This tag is especially useful when writing JSP fragments and reusing those across multiple form JSPs.

Also, if you're using a complex domain model with lots of nesting, you will greatly benefit from the nestedPath tag.

spring:transform

In the example where we allowed the user to select a show from a list, we created the following piece of JSP:

<select name="show">   <c:forEach items="${shows}" var="show">         <option value="${show.name}">${show.name}</option>   </c:forEach> </select> 

Of course, we can rewrite this to a JSP code using the spring:bind tag as well, but we will still have to specify what value our property editor will use when transforming the input text back to a show object:

<spring:bind path="command.show">   <select name="${status.expression}">     <c:forEach items="${shows}" var="show"             <option          <c:if test="${status.value == show}">selected</c:if>         value="<c:out value="${show.name}"/>">           <c:out value="${show.name}"/></option>     </c:forEach>   </select> </spring:bind>

The spring:transform tag provides you with support for transforming properties not contained by a command using property editors associated with the command. The shows rendered in the preceding example need to be transformed in the same way the spring:bind tag does the transformation. The spring:transform tag provides this support, internally using the same property editor as the spring:bind tag.

Note that the spring:transform tag can be used only inside a spring:bind tag:

... <c:forEach>   <option value="<spring:transform value="${show}"/>">     <c:out value="${show.name}">   </option> </c:forEach> ...

The spring:transform tag also supports the storing of the transformation result in a variable, using the var attribute.

Important 

All Spring tags extend HtmlEscapingAwareTag by the way, offering the htmlEscape Boolean property, allowing you to switch HTML escaping on or off for all output generated by the corresponding tag. By default, HTML escaping will always occur. You can set defaults by using the HtmlEscapeTag or by specifying a defaultHtmlEscape property in your web.xml.

HTML 4.0 is compliant with several character sets, such as ISO Latin-1. You can use whatever characters are available in the character sets supported by HTML 4.0. Parts of Unicode are also supported by HTML 4.0. Special characters, such as the German ü character and the symbol for the European currency, € , can be expressed only in Unicode. Transforming those characters from ASCII to Unicode is what the HTML escaping functionality does. You can find a full list of what characters are supported at www.w3.org/TR/REC-html40/sgml/entities.html.

spring:message

The spring:message tag is the Spring equivalent of the fmt:message tag from the Java Standard Tag Library. We felt the need to implement our own tag supporting internationalization because not everyone has the opportunity to use the JSTL. The spring:message tag has three properties (plus the standard

htmlEscape all tags offer): one for specifying the message code, one for a default message that will be used if the code can’t be resolved to a message, and one for storing the message in a page scoped variable.

 <spring:message   code="reservation.show.select.label"   text="Select your show">

While the preceding code snippet will directly output the result (after the tag has looked up the actual message using the MessageSource registered), you can also store the result in a variable for future use:

<spring:message   code="reservation.show.select.label"   text="Select your show">   var="messageVariable"/> 

Using ${messageVariable} in you HTML now will result in the resolved message being output. If the message cannot be resolved, the spring:message tag will output the string specified by the text attribute.

Important 

Note that most of Spring's tags support scoping, through the scope attribute. Variables can be stored in one of four scopes: page (exposed to the current JSP only), request(exposed for all pages rendered in the current request), session (stored in the session), and application (stored in the application's memory, hence visible to all consecutive requests, for all users). Keep in mind that storing a variable in a user's session will cause the variable to be left hanging there for the entire lifetime of his or her session(unless you remove it). In applications with a large number of concurrent users, this can result in a dramatic increase in the amount of memory used by the application.

Spring's message tag relies on the ApplicationContext for its messages. The ApplicationContext itself is an org.springframework.context.MessageSource, and will be able to resolve messages if you specify a message source with it (refer to Chapter 4 for information on MessageSources).

A Final Note on Spring Tags

Since JSP 2.0, all tags are EL-enabled, which means that you can use the expression language everywhere to pass objects to tags (for example by doing <pref:tag value="${date}"/>) . This wasn't the case in JSP 1.2, where tag developers had to provide EL-enabled versions of their tags themselves. As a result, lots of tag libraries provided both versions of their libraries for the old-school request-time expressions(rtexprvalue) using scriptlets (for example <pref:tag value="<% show.getDate() %"/>) as well as EL versions supporting the expression language. With the latter you could rewrite the preceding example to <pref:tag value="${show.date}"/>.

All Spring tags support the expression language. We strongly recommend you not use the runtime expressions anymore because they severely impact the readability and maintainability of your JSP code.

Because the tags support EL, you are allowed to do something like this:

<c:set var="bindPath" value="firstName"/>     <c:if test="${showLastName}">   <c:set var="bindPath" value="lastName"/> </c:if>     <spring:bind path="${bindPath}"/>   <input type="text" name="${status.expression}" value="${status.value}"/> </spring:bind>

Using Tag Files to Create Reusable Elements

In the previous sections we've been reviewing the Spring tags facilitating data binding, error messages, and i18n. You may have noticed that each time we introduced a tag, the level of coupling and duplication got reduced, but at the same time, we had to write more and more JSP code. We can prevent writing lots of JSP code with spring:bind tags littered all over the place in a couple of ways. First of all, we can write our own custom tags generating HTML input fields. This is the approach Struts has been taking with its html:XXX tags. Except for the normal HTML attributes such as style, id, and name, these include Struts- specific attributes that will facilitate data binding. By including <html:text style="width: 150px;" property="name"/> we could, for example, let Struts generate a text field with a preset width, which will be bound to the name property of the associated ActionForm.

With Spring, we explicitly decided not to include a tag library for generating markup as the preceding example shows. It limits the ways the developer can create markup, and in addition, HTML programmers need to learn an additional (and rather large) tag library. Last but not least, with the newly added features in JSP 2.0, we don't even have to create those tags anymore.

We'll show you how to code a form with a simple text field where the user has to enter his name — all this using JSP tag files. Note that JSP 2.0 (of which tag files is one of the new features) isn't implemented yet by all major Servlet container vendors. At the time of this writing, Jetty and Tomcat both support the latest JSP specification.

Tag files are ordinary pieces of JSP, placed in a directory and mentioned in the JSP using normal tag library declarations. Once set up, you can use them just as you would use any other tag. First, we'll have to create a new directory beneath WEB-INF, called tags. This is where the JSP fragments will be placed. Second, we'll mention the tags directory in our JSP creating the form:

 <%@ taglib prefix="form" tagdir="/WEB-INF/tags" %> <html>   <body>     <h1>Please enter your name</h1>     Name:      <form:text path="command.name"/>   </body> </html>

The form:select tag file will render an HTML select element for us and the form:text tag will render an HTML input field. Let's review these tag files:

<%-- partial text.tag, located in /WEB-INF/tags --%> <spring:bind path="${path}">   <input type="text"      name="${status.expression}"      value="${status.value}"/>   <c:if test="${status.error}"><font color="red">${status.errorMessage}</c:if> </spring:bind> 

As you can see, we've again decreased the level of duplication in our JSP; we don't have to mention the spring:bind tags in numerous places and we've refactored the code for the input field to a separate tag file. More resources on Spring and how to use tag files can be found online at the Spring Wiki site (http://opensource.atlassian.com/confluence/spring/display/ DISC/Minimize+Typing+with+nestedPath+Tag).



Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net