Google Answers Logo
View Question
 
Q: Processing forms with JSP ( Answered 5 out of 5 stars,   1 Comment )
Question  
Subject: Processing forms with JSP
Category: Computers > Programming
Asked by: carbon-ga
List Price: $15.00
Posted: 12 Jul 2004 22:41 PDT
Expires: 11 Aug 2004 22:41 PDT
Question ID: 373340
I design my forms to submit to themselves. In addition to the form
fields, they submit a variable 'validate' so that they can tell they
should be validating the fields. If validation is on and all of the
fields are ok, send a redirect to the next page. Otherwise, display
the form again with the erroneous fields in red.

I've set up my JSP to do that. The form is set to submit to itself,
and the form contains a hidden value 'validate'. If the JSP sees that
it's in validation mode, it uses a bean and sets that bean's
properties (we basically get all the variables that were passed in).
The bean sets some booleans so that I can tell which fields are
properly formed.

The problem is with a custom tag of mine that creates the 'input' tag
source. It looks about like

<x:formInputText field="name" label="Name:" error="${param.validate &&
!form.isNameValid}" />

I want the tag's 'error' parameter to be set to the boolean result of
the expression 'we are validating and the field is not valid'. If
that's done, the tag handler class will know to print the field's
label in red. HOWEVER, I CANNOT SEEM TO SET ERROR TO THE RESULT OF
THAT EXPRESSION LIKE I HAVE TO. That is, the expression in my error=""
doesn't work like I think it should.

If I can't make something like that work, I think I'll have to do
something dumb like a c:if where the two blocks are exactly the same
except that one has error="true" and the other has error="false".

If you have some other recipe similar to this I'd very much like to hear it. Thanks.
Answer  
Subject: Re: Processing forms with JSP
Answered By: rhansenne-ga on 13 Jul 2004 04:52 PDT
Rated:5 out of 5 stars
 
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
carbon-ga rated this answer:5 out of 5 stars
Very helpful information, great attitude when I needed clarification.

Comments  
Subject: Re: Processing forms with JSP
From: cristi_nada-ga on 26 Aug 2004 16:45 PDT
 
> 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.

According to the JSP 2.0 spec, section 7.3.2
>> The following order of precedence applies (from highest to lowest) when
>> building the taglib map (see the following sections for details):
>> 1. Taglib Map in web.xml
>> 2. Implicit Map Entries from TLDs
>>  TLDs in JAR files in WEB-INF/lib
>>  TLDs under WEB-INF
>> 3. Implicit Map Entries from the Container

So i guess tomcat 5 is looking in the c.tld (as instructed in
web.xml), it doesn't find http://java.sun.com/jsp/jstl/core_rt, then
looks in WEB-INF/lib, where the JSTL standard.jar contains
META-INF/c-1_0-rt.tld which does specify core_rt as URI. Note that by
this mechanism Tomcat will find the TLD even if it's not declared in
web.xml

I found this post interesting
http://www.mail-archive.com/tomcat-user@jakarta.apache.org/msg123308.html

What bothers me is: c-1_0-rt is a JSP 1.2 taglib and most probably
implements JSTL 1.0, not 1.1. doesn't that lose some features of JSTL
1.1?

Also, isn't there a cleaner way to use expression language in JSTL tag
attributes with Tomcat 5/JSP 2.0? Will the core_rt form always be
supported?

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy