The main theme for the Java Platform, Enterprise Edition (Java EE) 5 is ease of development. The platform's web tier contributes significantly to ease of development in two ways. First, the platform now includes the Java Standard Tag Library (JSTL) and JavaServer Faces technology. Second, all the web-tier technologies offer a set of features that make development of web applications on Java EE much easier. Some of these features are the following:
- A new expression language (EL) syntax that allows deferred evaluation of expressions, enables using expressions to both get and set data and to invoke methods, and facilitates customizing the resolution of a variable or property referenced by an expression
- Support for resource injection through annotations to simplify configuring access to resources and environment data
- Complete alignment of JavaServer Faces technology tags and JavaServer Pages (JSP) software code
In this series of articles, web-tier proponents at Sun introduce the new concepts that every web-application developer should be familiar with to get the most out of the Java EE 5 web-tier technologies. This first article in the series gives an overview of the new features introduced in version 2.1 of JSP technology.
Under the auspices of JSR 245 at the Java Community Process (JCP), the main focus of JSP 2.1 technology has been to provide a better alignment with the next release of JavaServer Faces technology, version 1.2.
The misalignment between the two technologies originated with the fact that version 1.0 of JavaServer Faces technology depended on JSP 1.2 technology. The reason is that the JSP 1.2 software was already widely available at the time, and the intention was to make the JavaServer Faces 1.0 interface more accessible to a broader audience. A consequence of this requirement was that JavaServer Faces technology could not take advantage of the EL introduced in the subsequent version of JSP technology, version 2.0. In addition, JSP 2.0 technology could not be modified to accommodate the needs of JavaServer Faces technology. And JSP 1.2 technology does not support an EL. Therefore, JavaServer Faces technology introduced an EL that was suited to its needs as a user interface (UI) component framework. As a result, page authors using JavaServer Faces technology tags with JSP technology code encountered some incompatibilities between the two technologies.
The expert groups have worked together on the upcoming releases of JSP 2.1 and JavaServer Faces 1.2 technologies in Java EE 5 to fix these integration issues and make sure that the two technologies work together seamlessly. One result is that all of the web-tier technologies now share a unified EL, allowing you to mix code from all of these technologies freely and without worry. This article provides an overview of the work that was done to improve the alignment of these technologies. It also explains the other minor improvements that made it into JSP 2.1 technology.
The simple EL included in JSP 2.0 technology offers many advantages to the page author. Using simple expressions, page authors can easily access external data objects from their pages. The JSP technology container evaluates and resolves these expressions as it encounters them. It then immediately returns a response because the JSP request-processing model has only one phase, the render
phase. However, because the request-processing model does not support a postback
, all JSP expressions are read-only.
Unlike JSP technology, JavaServer Faces technology supports a multiphase life cycle. When a user enters values into the JavaServer Faces UI components and submits the page, those values are converted, validated, and propagated to server-side data objects, after which component events are processed. In order to perform all these tasks in an orderly fashion, the JavaServer Faces life cycle is split into separate phases. Therefore, JavaServer Faces technology evaluates expressions at different phases of the life cycle rather than immediately, as JSP technology would do. Additionally, the expressions can be used to set as well as get data, so that the values a user enters into the UI components are propagated to server-side objects during a postback
. Finally, some JavaServer Faces technology expressions can invoke methods on server-side objects during various stages of the life cycle in order to validate data and handle component events.
Each EL suited the needs of its respective technology very well. When using both JSP technology tags or template text and JavaServer Faces technology tags, however, page authors would expose incompatibilities between the ELs. One example involves using JavaServer Faces components inside the c:forEach
tag, as in the following example:
<c:forEach var="location" items="${handler.locations}"> |
The problem with this code stems from the fact that the iteration variable location
is visible only within the boundaries of its iteration tag. This means that on a postback
, the JavaServer Faces request life cycle has no way to access the value associated with the variable location
.
To solve problems such as these, the expert groups for JavaServer Faces and JSP technologies decided to unify the two ELs. They created a more powerful EL, the unified EL, that supports the following features:
- Deferred expressions, which can be evaluated at different stages of the page life cycle
- Expressions that can set data of external objects as well as get that data
- Method expressions, which can invoke methods that perform event handling, validation, and other functions for the JavaServer Faces technology UI components
- A flexible mechanism to enable customization of variable and property resolution for EL expression evaluation
With the addition of these features into a unified EL, the incompatibility problems such as that illustrated by the preceding c:forEach
code example can be solved. Now, the iteration variable can be a deferred expression that refers to the proper object within the collection being iterated over -- for example, locations[0]
. This way, the deferred expression can be evaluated later on during the JavaServer Faces request life cycle, as shown in the following code:
<c:forEach var="location" items="#{locations}"> |
For more details on changes made to the c:forEach
tag and other JSTL tags, please see the upcoming article of this series, which will describe new features in JSTL. If you are a page author, make sure to read another upcoming article in the series, which describes the differences between the two EL syntaxes now supported in JSP technology. The article "Unified Expression Language (EL)" provides a much more detailed description. It also explains how to create a custom resolver, which is one of the new features of the unified EL.
It is also important to note that the EL is useful beyond all of the web technology specifications. This is why the EL is agnostic of the technology hosting it and is currently defined through its own independent document within the JSP specification. This makes it clear that the EL is not dependent on the JSP specification and might therefore have its own JSR in the future.
Prior to the Java EE 5 platform, accessing data sources, web services, environment entries, and Enterprise JavaBeans (EJB) bean references required the use of the Java Naming and Directory Interface (JNDI) API along with the declaration of entries into a deployment descriptor. Thanks to injection annotations, it is now possible to inject container-managed objects without having to write the traditional boilerplate code and deal with the deployment descriptor.
For example, a tag handler could access a database through the following code:
@Resource(name="jdbc/myDB") |
The field myDB
of type javax.sql.DataSource
is annotated with @Resource
and is injected by the container prior to the tag handler being made available to the application. The data source JNDI mapping is inferred from the field name catalogDS
and type javax.sql.DataSource
. Moreover, the myDB
resource no longer needs to be defined in the deployment descriptor. An upcoming article in this series will provide more detail on how to perform injection with web-tier applications.
TrimWhiteSpace
A frequent complaint in user forums concerns the large number of blank lines, or white spaces, that often clutter the output of a JSP technology page. For example, consider this page:
<%@page contentType="text/html"%> |
Prior to JSP 2.1 technology, this page would produce the following output in the response (where ¬
represents the end of a blank line):
¬ |
Although these extra blank lines do not change the way a browser displays the output page, they do add extra payload to the response and make the HTML source code less legible. To solve this issue, JSP 2.1 technology now offers the configuration parameter trimDirectiveWhitespaces
, which can be specified as a page directive or as a property-group configuration parameter that applies to a group of pages.
With trimDirectiveWhitespaces
enabled, template text containing only blank lines, or white space, is removed from the response output. In the code example above, the lines containing only blank lines would be removed, yielding the following output:
<html> |
Maintaining compatibility with earlier versions is critical for any Java EE platform release. For JSP 2.1 technology, the only backward compatibility issue involves the EL's new support of the #{
syntax that refers to deferred expressions. The #{
character sequence can create backward compatibility problems in two situations: when the sequence is included in template text or in attribute values.
In JSP 2.1 technology, a deferred expression does not make sense in the context of template text because evaluation of an expression is always done immediately by the JSP container. Because no entity other than the JSP container processes template text, a deferred expression would always be left unevaluated if it were included in template text. Therefore, any page authors who have included the #{
character sequence in template text probably meant to use the ${}
syntax instead. Acknowledging this fact, the JSP specification authors have mandated that the inclusion of #{
in template text triggers a translation error in JSP 2.1 technology.
With respect to tag attribute values, it is important to note that tag libraries based on JSP versions prior to 2.1 (such as the 1.1 version of the JavaServer Faces component tag library) made extensive use of the #{
syntax to specify deferred expressions. Because these tag libraries must be responsible for the parsing of these deferred expressions, they must execute in an environment in which the #{
character sequence is processed as a string literal.
To determine whether or not to treat the #{
character sequence as a string literal, the web container relies on the JSP version indicated by the tag library descriptor (TLD) associated with the tag library. The JSP version specified in the TLD tells the web container which version of the JSP specification the tag library is written for. JSP versions previous to 2.1 processed #{
as a string literal, as did applications based on those earlier versions. With version 2.1 or later, the character sequence #{
represents a deferred expression, assuming the attribute has been declared to support deferred expressions in the TLD. If the attribute does not support deferred expressions, then the presence of the #{
character sequence results in a translation error.
Web-application developers who have developed applications for a version prior to JSP 2.1 technology and want to deploy and run them on a JSP 2.1 container must take the following actions to ensure that the container handles any instances of the #{
character sequence correctly:
- Escape each instance of the
#{
characters using a backslash:\#{
.
- Globally allow usage of the
#{
character sequence as a string literal by setting the JSP property groups elementdeferred-syntax-allowed-as-literal
totrue
or by setting thepage/tag-file
directive attributedeferredSyntaxAllowedAsStringLiteral
totrue
.
Aside from the incompatibilities relating to the #{
character sequence, all JSP 2.0 technology applications will run as is on JSP 2.1 containers. However, if a web application uses third-party tag libraries that are based on JavaServer Faces 1.1 technology or earlier, some new features provided by JSP 2.1 and JavaServer Faces 1.2 technologies will not be available with these libraries. For example, although EL functions may now be used in the JavaServer Faces 1.2 core and HTML tag libraries, they cannot be used with third-party tag libraries that are based on JavaServer Faces 1.1 technology and earlier, because these libraries run on a version of the JavaServer Faces EL that did not support EL functions.
Taglib
Order of Precedence
Now that JavaServer Faces technology and JSTL are part of the Java EE 5 platform, they take precedence over any other version of these libraries that could be bundled with a web application. Some people may ask: "But what if I want to replace the container's implementation of these technologies with another implementation?" This is no longer possible. This would be like replacing the implementation of the java.util package
in the Java Platform, Standard Edition (Java SE, formerly referred to as J2SE), a fruitless task. The same applies from now on with platform tag libraries.
Essentially, applications should not replace the APIs that the Java EE 5 platform requires. If the platform architects really wanted to make this possible, they would have designed the APIs with service-provider interfaces to allow applications to easily swap in their own implementations. However, this was not their intention, and applications will always have to rely on the platform tag libraries bundled with a container.
Let's look at a few other minor additions and clarifications to the JSP 2.1 specification. For a detailed list of all changes between JSP 2.0 and JSP 2.1, please consult Appendix E of the specification. Most notable are the following:
- The JSP spec now supports Byte Order Marks (BOM) as authoritative page-encoding declarations for JSP technology pages and tag files in standard syntax.
- Because JSP 2.1 technology requires J2SE 5.0, some APIs that can take advantage of generics have been modified.
- And many more, as Appendix E points out.