Return to index

logo

 

JSP - Part 3
Expression Language,
Attribute Scope
and Standard Tags



The Expression Language adds no new functionality as such, but does make life easier when developing JSP - by allowing expressions to be written in a simpler format.

The JSP Standard Tag Library (JSTL) provides a set of tags to perform common generic functions, such as 'if then else'. TJI provides the main tags of the JSTL 'core' in source code format (thereby providing a resource for studying how tag handlers can be written).

This document also looks at how attributes can be stored with various scopes - as with Java Beans in JSP.

Five new example projects demonstrate the new functionality very well and can be found on the 'Resources' page of our web site. These include a JSP version of 'Duke's Book Store' to parallel the servlet based version.

 

The Expression Language

Consider the following snippet of JSP :

<tags:someTag value="<%= myBean.getCurrentValue() %>">

It's a bit hard to read. Now look at this alternative :

<tags:someTag value="${ myBean.currentValue }">

Much cleaner looking! Welcome to the 'Expression Language' - or 'EL' for short.

The EL version (above) is easier to read because it avoids having angle brackets inside angle brackets. Furthermore it employs a short hand for referring to:

  • java bean properties
  • attributes

 

Retrieving attributes

You may remember attributes from working with Servlets. You can use EL to retrieve a page scope attribute (the default scope) with, for example:

<tags:someTag value="${ count }">

This is equivalent to :

<tags:someTag value="<%= pageContext.findAttribute("count") %>">

The JSP enabled server will look for an attribute called 'count' in the page, request, session and application scopes (in this order) and return its value. If 'count' is not found, null is returned.


EL can be used to specify attributes for tag handlers, as in the examples above. When used within static HTML parts of a JSP page, the value is automatically sent to the output. For example:

<b>The current number of users is: ${ count } people.</b>

 

Retrieving Bean Properties

If count is a bean property accessed by method getCount(), it can be accessed by the following Expression Language:

<b>The current number of users is: ${ mybean.number } people.</b>

See also <c:out value="xxx"> below.


You can download and try examples
JSP Example 2 and JSP Example 3 from our website - these illustrate the features briefly detailed here. Each comes as two projects - one for the JSP files and Java Beans, and one for the tag handlers. JSP Example 2 includes a prototype standard tag - a generic 'if' tag that processes the body if a passed-in attribute ('test') is true. For example:

<b>The current number of users is: ${ mybean.number } people.</b>
<tags:if test="${ mybean.number>10 }">
     <i>
          Wow, so many!
     </i>
</tags:if> 

 

A comparison of Scriptlets, Expressions and the use of the Expression Language

Consider a Web application that maintains information about usage statistics in a bean of class ServerStats. Class ServerStats has a method getUserCount(), which returns the number of users currently logged on. The application maintains a single instance of ServerStats in a ServletContext (i.e. application scope) attribute called 'stats'. Here's a comparison of how you could create usage statistics output using a scriptlet, a JSP expression, and by using the Expression Language.

  • Creating output with a scriptlet (embedded Java code) : Any output the scriptlet produces has to be explicitly written to the output stream. A JSP page could report the number of users with the following scriptlet and template text:
      There are currently 
      <%
           ServerStats ss = (ServerStats)application.getAttribute("stats");
           out.print(ss.getUserCount());
      %> 
      users logged on. 

    The result would look like this :

    There are currently 15 users logged on.

  • Creating output with a JSP expression: You can simplify things a bit by using an expression. The expression is evaluated, and the result is coerced to a String for output. The result of the expression replaces the expression tag in the JSP page output. Writing the resulting text to the JSP page output is implicit.
         There are currently
      <%= 
           (ServerStats)(application.getAttribute("stats")).getUserCount() 
      %> 
      users logged on. 

    This is somewhat easier to write, but is still a bit difficult to read and maintain.

  • By using the Expression Language. This provides a way to access server-side state with less effort than the approaches shown above. The way to print the "number of users" message would look like this:
           There are currently ${stats.userCount} users logged in.

 

Of course, an alternative is to use a custom tag. Custom tags produce a cleaner JSP page and enable code reuse. However, this approach is probably 'over the top' in this case. Remembering that the implementation code is in the handler class, the JSP code for the example message would look like this:

There are currently <myTags:userCount/> users logged in.

 

Predefined Implicit Objects

 There are some predefined implicit objects that one can use in EL. These include 'request', 'response', 'session', 'application' and 'pageContext'.

${ session.attribute("count") }

can also be written as :

${ pageContext.sesion.attribute("count") }

or simply :

${ sessionScope.count }

which as a standard expression would be written as :

<%= pageContext.getSession().getAttribute("count") %>

 

 param

There is also 'param'. For example,

${ param.count }

which is equivalent to:

<%= request.getParameter("count") %>

 

 paramValues

This is used when request parameters may have multiple values with the same key. For example, a form may send the following request:

processForm.jsp?name=fred&like=tea&like=pizza&like=pineapple

The following snippet shows how paramValues can be used to get at the multiple values one by one - by using the standard tag c:forEach (see below)

<c:forEach items="${paramValues.food}" var="currentItem">
      <c:out value="${currentItem}"/> 
      <br>
</c:forEach>

 

 Other useful predefined objects

  • pageScope
  • requestScope
  • sessionScope
  • applicationScope

So, for example,

${ sessionScope.count }

will return the attribute named "count" defined in scope 'session' - or null if it does not exist. See the 'Attribute Scope' section of this document for information on scope.

 

Notes on the support for Expression Language in TJI

The Expression Language supported by TJI is not a complete support of its functionality. Nevertheless, quite complex expressions are possible. For example:

<c:if test="${ myBean.food!=null && !myBean.food.length()==0}">

The point is, don't try to put too much business logic into an expression - try to put it into a bean or custom tag instead. For example:

<c:if test="${myBean.valid}">
     ... 
</c:if>

or

<myTags:foodValid>
     ... 
</myTags:foodValid>

In the above case, the matter is borderline. Certainly any complex logic should be 'off-page'.

Note that TJI supports the standard Java symbols for expressions rather than the EL equivalents - '==' rather than 'eq'', '!' rather than 'not', etc.

 

The JSP Standard Tag Library

TJI supports the core part of the JSP Standard Tag Library (JSTL) by providing as a project the core tag handlers, in source code format. This is available on our web site within the 'Resources' page. Simply download the zip file, import it into TJI and build it. You can then use the standard tag handlers in your JSP projects.

JSP examples 1, 4 and 5 on our web site provide simple examples that use the standard tag library functionality.

There is also a JSP version of 'Duke's Book Store' available.

The core tag handlers have a prefix of 'c'. Here are some examples of how they can be used.

 

 <c:if test="xxx">

The test attribute is mandatory and should return a boolean value. If true, the body is 'run'.

A jsp snippet

Hello
<c:if test="${ sb.count>1 }">
      (again)
</c:if> 


 <c:choose> <c:when
test="xxx"> [<c:otherwise>]

c:when is almost identical to c:if

c:choose groups the c:when tags and runs c:otherise if no c:when has run. Take a look at the source code to see how it works. Basically, c:choose maintains a flag which is set if any c:when child runs; if none has then when it is the turn of c:otherwise, c:otherwise runs.

The whole structure is similar to switch in Java.

A jsp snippet

This page has been accessed
<c:choose>
     <c:when test='${ sb.count==1 }'>
          Once
     </c:when>
     <c:when test='${ sb.count==2 }'>
          Twice
     </c:when>
     <c:otherwise>
          A lot !!
     </c:otherwise>
</c:choose> 


 <c:forEach
items="xxx" [var="yyy"]>

items can be any Collection type.

var is optional - it is used as a reference to the current object in the Collection and can be referred to with Expression Language, as in the example below.

The jsp file

<html> 
     <body>
          <jsp:useBean id='bean' class='SimpleBean3'/>
          <c:forEach items="${ bean.data }" var="it">
               Item: ${ it }
               <br>
          </c:forEach>
     </body>
</html> 

The Java Bean

import java.util.*;
public class SimpleBean3 {
      Vector v;

 

      public SimpleBean3() {
            v=new Vector();
            v.addElement("fish");
            v.addElement("veggies");
            v.addElement("spices");
      }

 

      public Vector getData() {
            return v;
      }
} 


 <c:out
value="xxx" [default="yyy"]>

<p>
      The current number of people logged in is ${ count }
</p>

is equivalent to :

<p>
      The current number of people logged in is <c:out value="${ count }"/>
</p>

One reason for using c:out is to take advantage of the default attribute; this will be used if the value is null. For example:

<p>
      The current number of people logged in is <c:out value="${ count }" default="unknown" />
</p>

 

 <c:set [var="xxx"] [value="yyy"] [scope="session"] [target="beanName"] [property="beanPropertyName"] />

This tag can be used to set :

  • an attribute, or
  • a bean property.

scope is optional; if omitted, the default scope is used - 'page' scope.
scope can be one of : 'session', 'page', 'request' or 'application'.

If no target is specified, an attribute is set, and created first if it does not already exist.
var is used for setting attribute values - it should be the attribute name.

If target is specified, this should be the name (identifier, not class name) of a bean.
property
the name of a bean property.

value can be any Java object type (not a primitive).

So the two forms of use for c:set are :

  • For attributes :
    <c:set var="attributeName" value="val" />
  • For beans :
    <c:set target="beanName" property="beanProperty" value="val" />

 

 <c:remove var="xxx" [scope="session"]/>
This tag can be used to remove an attribute. Scope is optional; if omitted, the default scope is used - 'page' scope.
Has the same effect as c:set with a value of null.
Scope can be one of : 'session', 'page', 'request' or 'application'.

 

Attribute Scope

Attributes provide a way to store and retrieve information. There are four levels of storage, each with its own scope. The level of scope determines for what duration the attribute is stored. The four scopes are, from shortest to longest duration :

  • PageContext.PAGE_SCOPE
  • PageContext.REQUEST_SCOPE
  • PageContext.SESSION_SCOPE
  • PageContext.APPLICATION_SCOPE

These PageContext constants can be used in the following PageContext methods :

  • setAttribute(String name, Object value, int scope)
  • Object getAttribute(String name, int scope)
  • removeAttribute(String name, int scope)

* Page scope is the briefest scope - the attribute exists only as long as the declaring page is active.

* Request scope allows the attribute to exist as long as the request, so it will exist in a page forwarded to, or after return from an include.

* Session scope ties the attribute to a particular user for a certain amount of time - typically 2 hours - as defined by cookie life or server setting.

* Application scope is 'forever' - well, until the server is rebooted.


In the case of :

  • setAttribute(String name)
  • Object getAttribute(String name)
  • removeAttribute(String name)

the default scope is used - page scope.


The following PageContext methods are also available :

  • Object findAttribute(String name)
    searches for the attribute in all scopes, in this order: page, request, session, application
  • int getAttributesScope(String name)
    the returned value will be one of the constants defined in class PageContext, such as PageContext.PAGE_SCOPE


As an example, a tag handler could include the following in its doTag() method :

PageContext page=(PageContext)getJspContext();
page.setAttribute("Count", count, PageContext.SESSION_SCOPE);


Note that
the tag c:set can also be used to set an attribute with a defined scope. For example:

<c:set var="x" value="y" scope="session"/> 

Scope is optional; if omitted, the default scope is used - 'page' scope.

 

Return to index