EQUIP2 JSP Taglib

Chris Greenhalgh, 2006-07-18; last updated 2006-07-18

Contents:

Introduction

EQUIP2 is currently being used extensively for web applications, e.g. Day of the Figurines. While there are various ways to interface to EQUIP2 within a J2EE web application, the preferred (and probably simplest) option for rendering pages/views incorporating information from the EQUIP2 dataspace is to use the EQUIP2 custom taglib, documented here.

It is recommended that this taglib is only used for read access to the dataspace (although it is possible to modify the dataspace using it, this will typically bypass application logic and may result in an inconsistent application state).

It is also recommended (at least in more complex applications) to separete rendering pages separate from equip logic, so that logic can be migrated into (e.g.) Spring controllers later, while still being able to use the same views. This could be done in the interrim by the logic pages (with eq: tags) using jsp:include or jsp:forward to link to separate view pages which share data via request scoped variables.

Background

JSP options

Tomcat 5.5 supports Servlet 2.4 (JSR 154) & JSP 2.0 (JSR 152).
JSP 2.0 supports:
Actions available include:
As with normal Java servlets/JSPs the four scopes of objects available to pages are:

JSTL standard tags & JSP EL

JSTL standard tags and JSP expression language provide a good way to access information and do XSLT-like programming in JSPs. For example, the EQUIP controller might leaves a list of EQUIP2 data objects (Object[]) in the request parameter "matches"; a JSP view can then use EL and JSTL to print some information about these objects (below, assuming the matched object class has an ID and a name property):
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<c:out value="${fn:length(requestScope.matches)}"/> objects<br>

<c:forEach var="match" items="${requestScope.matches}">
ID = <c:out value="${match.ID}"/>,
name=<c:out value="${match.name}"/><br>
</c:forEach>
...
where ${requestScope.matches} is the parameter called "matches" in the request scope(!)

EQUIP2 custom taglib

The EQUIP2 custom taglib gives access to (most of) the normal equip2.core.ISession API, plus support for creating equip2.core.QueryTemplate objects. As noted above, this is only for read access, and normally EQUIP2 update operations should go in custom servlets/controllers and/or application logic objects.

The recommended taglib prefix for the EQUIP2 taglib is 'eq'. The URI of the taglib is 
'http://www.mrl.nott.ac.uk/jsp/equip2'. Use of the taglib is introduced within a JSP in the usual way:

...
<%@ taglib uri="http://www.mrl.nott.ac.uk/jsp/equip2" prefix="eq" %>
...

Creating a session

Any EQUIP2 operation must be performed within the context of a session. The tag eq:session creates a dataspace session within the JSP page context, which is available (only) within the body of the session tag:
<%@ taglib uri="http://www.mrl.nott.ac.uk/jsp/equip2" prefix="eq" %>
<eq:session> <!-- begins session -->
<!-- equip operation tags valid here... -->
</eq:session> <!-- ends session -->
The session tag has the following (optional) attributes:
Attribute name
Required/ optional
Type
Default
Meaning
read_write
optional
boolean
false
Make the session type READ_WRITE, rather than READ_ONLY, i.e. allow update operations.
dataspacename
optional
String
java:/app/env/provider/IDataspace
Name to use to look up the dataspace to use in the EQUIP2 naming Initial Context.
dataspace
optional
equip2.core.IDataspace
use dataspacename to locate dataspace
Direct reference to the dataspace to use.
As already noted it is recommended that read_write session are NOT used.

Performing a match

The main dataspace read operation is match, which is made available by the eq:match tag. This tag can only be used within the body of an eq:session tag, from which it determines the dataspace session that it should use. Like the core API operation it takes a single argument which is the template object (or equip2.core.TemplateQuery) that it should match. It returns a (possible 0 length) array of the objects in the dataspace which match the template. If and only if the session is read_write and the match operation is also read_write then the returned objects are 'managed' and changes to them will be returned to the dataspace at the end of the session. For example:
  ... <!-- in a session... -->
<eq:match var="matches" template="${somevariable}"/>
...
The eq:match tag has the following attributes (it must have an empty body):
Name
Required/ optional
type
default
Meaing
var
required
String (not EL)
-
Name of variable to which results should be bound. Results are of type Object[].
template
required
Object
-
Template object value (or equip2.core.QueryTemplate) to be matched.
scope
optional
one of page, request, session or application
request
Scope of declared variable, var.

Creating simple templates

The template value in a match is either a Query Template (see below) or an instance of a class managed by EQUIP2. This may come from any source that is accessible within the JSP page, e.g. parameters, page, request, session or application scoped variables. Simple template instances can also be directly constructed using the standard JSP JavaBean support tags, such as the example below which creates a template instance of class mypackage.MyClass, and sets the property name to the string 'Bob'.
...
<jsp:useBean id="mytemplate" class="mypackage.MyClass"/>
<jsp:setProperty name="mytemplate" property="name" value="Bob"/>
...
<eq:match var="matches" template="${mytemplate}"/>
...
Note that simple templates are always matched exactly; more complex queries (e.g. inequalities) can only be expressed using Query Templates, below.

Creating Query Templates

The most flexibly way of expressing a match template is as an instance of class equip2.core.QueryTemplate. A number of tags support this.

The eq:query tag creates a Query Template and binds it to a scoped variable:

<eq:query var="qt" classname="mypackage.MyClass">
<!-- constraints and order specified here... -->
</eq:query>
The eq:query tag has the following attributes:
Name
required/ optional
type
default
Meaning
var
required
String (not EL)
-
Name of variable to bind resulting query template to.
scope
optional
one of page, request, session or application request
Scope of declared variable, var.
classname
required
String
-
Name of java class to match
maxResults
optonal
int
0 (unlimited)
Maximum numbers of matching objects to return.
firstResult
optional
int
0
Index (counting from 0) of first object to return, i.e. discard this many results first.

The body of the eq:query tag can include eq:constraint and eq:order tags to further specify the query.

Each eq:constraint tag specifies a value constraint on a single property of the query's class. For example, the equivalent of the simple template before (fixed name 'Bob') would be:

<eq:query var="qt" class="mypackage.MyClass">
<eq:constraint property="name" constraint="eq" value="Bob"/>
</eq:query>

Note that it is normally clearer to use one of the specialised constraint tags (in this case eq:constraint-eq) described below, rather than the generic constraint tag.

The eq:constraint tag has the following attributes:

Name
required/ optional
type
default
Meaing
property
required
String
-
Name of the property to be constrained
constraint
required
one of eq, ne, lt, gt, le, ge, isnull, notnull, like, in, notin
-
Kind of constraint (equal, not equal, less than, greater than, less than or equal, greater than or equal, is null, not null, like (SQL pattern match))
value
optional
Object
null
Value for comparison with property (for all constraints except isnull/notnull).

The following specialised constraint tags are also specified, each for one particular constraint type:

Tag name
eq:constraint constraint
Value required?
Property constraint
constraint-eq
eq
yes
equals value
constraint-ne
ne
yes
not equal to value
constraint-gt
gt
yes
greater than value
constraint-lt lt
yes less than value
constraint-ge ge
yes greater than or equal to value
constraint-le le
yes less than or equal to value
constraint-isnull isnull
no
is null
constraint-notnull notnull
no
is not null
constraint-like like
yes matches value, using SQL 'like' syntax, i.e. '%' matches any 0 or more characters; '_' matches any one character.
constraint-in
in
yes
in, i.e. equals one of the array of values provided (array type castable to Object[])
constraint-notin
in
yes
not in, i.e. not equal to any of the array of values provided (array type castable to Object[])

It is important for matching that the Java type of the value corresponds to the Java type of the property being tested against. This can be hard to achieve using JSP Expression Language, and JSP expressions or scriptlets may be required instead. For example, a default EL number ("${0}") is actually a Long. Some examples of particular primitive type values are given below:

The eq:order tag has the following attributes:

Name
required/ optional
type
default
Meaing
property
required
String
-
Name of the property for results to be sorted by
descending
optional
boolean
false
sort in descending rather than ascending order

Other read operations

The API matchUnique operation is provided by the eq:matchUnique tag. This is identical to the eq:match tag except that the return type is Object (not Object[]), and it is an error to use this operation if more than one matching value is expected (or possible!). For example:
<eq:matchUnique var="VARNAME"  [scope="page|request|session|application"] 
template="TEMPLATEVALUE"/> <%-- result type Object --%>

The API get operation is provided by the eq:get tag. This retrieves a single Object (if it is present, else null) by matching its class and identity. Identity, if defined for that class, is typically one of its properties. For example:

  <eq:get var="VARNAME"  [scope="page|request|session|application"]
classname="CLASSNAME" identity="IDENTITYVALUE"/> <%-- result type CLASSNAME --%>

The API count operation is provided by the eq:count tag. This returns the count of the number of objects satisfying a match with the given template. For example:

<eq:count var="VARNAME"  [scope="page|request|session|application"] 
template="TEMPLATEVALUE"/> <%-- result type Integer --%>

Other dataspace operations

The remaing datatype operations (add, update, remove, addOrUpdate) are only valid in a read_write session, and change the dataspace (note that changing a value retrieved in a read_write session by a read_write match, matchUnique or get also changes the dataspace, e.g. with jsp:setProperty). Typical usage is as follows:
  <eq:add object="VALUE"/>
<eq:remove object="VALUE"/>
<eq:update object="VALUE"/>
<eq:addOrUpdate object="VALUE"/>

Refer to the EQUIP2 API documentation for more information on these operations and modifying the dataspace.

Building

The built taglib is the jar dist/equip2taglib.jar, and is built by the ant target 'taglib'. Building requires the servlet and jsp API jars; the current build assumes you have a local Tomcat install in which they can be found.
 
The source is under src/equip2/taglib/j2se. The taglib desriptor file is etc/eq.tld.

Known issues

Change log

2006-09-25
2006-07-18