Hi carbon-ga,
The reason your custom tag can't interpret the expression is probably
due to the fact that you are using JSP 1.2 container, which doesn't
know anything about EL expressions, so they are evaluated by code in
the JSTL tag handlers. JSTL 1.0 doesn't define a public API for this
evaluation code (JSP 2.0 will however), so there's no way to let
custom tag handlers do the same in a way that works with all JSTL
implementations.
You can, however, pick one JSTL implementation and code to its API.
For instance, if you're willing to be dependent on the JSTL Reference
Implementation (RI) developed in the Apache Taglibs project, you can
use this org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager
method in your tag handler:
public static Object evaluate(String attributeName,
String expression,
Class expectedType,
Tag tag,
PageContext pageContext);
This method takes an EL expression and evaluates it in the specified
PageContext and converts (coerces) the result to the specified
expected type, according to the rules defined by the JSTL 1.0
specification. The other parameters are used to include details in a
possible error message, such as the name of the custom action and the
attribute where the invalid expression is used.
You must call this method in one of the main methods in the tag
handler (e.g. doEndTag()), never in the attribute setter method. The
reason for this is that the setter method may not be called every time
the tag handler is used.
In this case your tag could look like this:
package mypackage;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import org.apache.taglibs.standard.lang.support.*;
public class FormInputText
extends TagSupport {
private String error;
public void setError(String error) {
this.error = error;
}
public int doEndTag() throws JspException {
boolean boolError = ((Boolean) ExpressionEvaluatorManager.evaluate(
"error",error,Boolean.class,this,pageContext)).booleanValue();
if (boolError) {
// ...
} else {
// ...
}
// do stuff and return status ...
}
// other methods...
}
Note that to compile and use this tag handler, you must have the JSTL
RI ExpressionEvaluatorManager in the classpath; it's available in the
standard.jar file that's part of the RI download (see reference
section below).
If you can hold your horses a bit and wait for JSP 2.0, you don't have
to do anything in your tag handlers to accept EL expression attribute
values. JSP 2.0 (currently at the Proposed Final Draft stage, expected
to be released Q1 2003) will include a somewhat extended version of
the EL and will evaluate EL expressions before calling tag handler
attribute setter methods. Hence, EL expressions can be used with any
tag handler that is declared in the TLD to accept a runtime value. JSP
2.0 will also accept EL expressions anywhere in the template text.
On a side-note: the "form.isNameValid" expression in your example
might need to be "form.nameValid", since bean properties should be
called directly and not through there method name.
If you run into any trouble, don't hesitate to ask for a clarification.
Sincerely,
rhansenne-ga.
Search terms used: jsp jstl "custom tag" "expression language"
References:
Jakarta standard tag library:
http://jakarta.apache.org/taglibs/doc/standard-1.0-doc/intro.html
JSTL 1.0: What JSP Applications Need
http://www.onjava.com/pub/a/onjava/2002/10/30/jstl3.html |
Request for Answer Clarification by
carbon-ga
on
13 Jul 2004 09:12 PDT
Hi, thanks for the answer. I think I understand your answer, but I'm
still not sure why what I'm doing doesn't work, since I'm using Tomcat
5.0.18, which seems to support JSP 2.0. My TLD specifies
<jspversion>2.0</jspversion>, and the error attribute for the custom
form tag looks like
<attribute>
<name>error</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<type>boolean</type>
</attribute>
According to the article, "JSP 2.0 ... will evaluate EL expressions
before calling tag handler attribute setter methods. Hence, EL
expressions can be used with any tag handler that is declared in the
TLD to accept a runtime value."
Isn't that exactly what I'm doing? I'm specifying, as one parameter to
my custom tag, error="${param.validating && !form.nameValid}". This
expression doesn't seem to get evaluated -- it just gets passed to
error unmodified.
|
Clarification of Answer by
rhansenne-ga
on
13 Jul 2004 11:21 PDT
Hi carbon-ga,
Tomcat 5 does indeed support JSP 2.0
I presume the "validating" parameter always contains the value "true" or "false"?
If you use the c:out tag with this expression, does it correctly print
out the result? E.g.:
<c:out value="${param.validating && !form.nameValid}" />
Sincerely,
rhansenne-ga.
|
Clarification of Answer by
rhansenne-ga
on
13 Jul 2004 11:58 PDT
Hi carbon-ga,
It took me a while to reproduce the same behavior on Tomcat 5.0, but I
managed to get the same problems you're describing, when using a
servlet 2.3 definition in web.xml. Everything works fine when using
2.4.
So if your web.xml (in /WEB-INF) look something like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<webapp>
...
Change it to this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
And with a little luck, EL evaluation will now be enabled. Keep me informed.
Sincerely,
rhansenne-ga.
Sincerely,
rhansenne-ga.
|
Request for Answer Clarification by
carbon-ga
on
13 Jul 2004 15:18 PDT
Thanks for your answer.
My application's web.xml did specify 2.3 stuff, so I made the changes
you suggested. With this new web.xml, when I do a <c:out
value="${param.validating && !form.nameValid}" />, I get an error from
Tomcat: "According to TLD or attribute directive in tag file,
attribute value does not accept any expressions".
To make sure that it was the web.xml that was making the difference, I
restored the old web.xml (the 2.3 one) and restarted Tomcat. Then the
result is "false".
|
Request for Answer Clarification by
carbon-ga
on
13 Jul 2004 15:44 PDT
Please give me a while to make certain my TLDs and libs and taglib
directives and stuff are as they should be. Thanks again for your
answers.
|
Clarification of Answer by
rhansenne-ga
on
14 Jul 2004 02:27 PDT
Ah, yes - forgot to mention something:
When using 2.4, change the directive:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
to
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
That should get the "c" tags working again under servlet 2.4. Does
your custom tag correctly parse the attribute expression now?
Kind regards,
rhansenne-ga
|
Request for Answer Clarification by
carbon-ga
on
14 Jul 2004 12:56 PDT
My custom tag's working just like I needed it to now. I guess
everything makes sense now except for the TLD situation.
On http://jakarta.apache.org/taglibs/binarydist.html there is a
section "Using a Custom Tag Library in Your Application" whose advice
I followed. They said I should add taglib directives to my
application's web.xml and to use kind of strange-looking taglib uris
in my JSPs (http://jakarta.apache.org/taglibs/{library}).
In the taglibs 1.1 archive, there are numerous TLDs. I chose to copy
c.tld to my application's WEB-INF. c.tld's uri is the more
familiar-looking http://java.sun.com/jsp/jstl/core, so I'm not sure
how my setup is working.
Thanks again.
|
Clarification of Answer by
rhansenne-ga
on
15 Jul 2004 00:22 PDT
excellent :)
Best regards,
rhansenne-ga
|