As some of you might remember, I started a little project a while ago to build
a tag library which implements the Struts tag libraries, but uses the JSTL
EL-engine to evaluate attributes, as opposed to using rtexprvalues.  I've
talked to Craig about most of this already (although I've changed it a little
bit since he last saw it), but I wanted to give this information to the rest of
the community.

I'm still working on this project.  I've found that once I decided on a basic
strategy, writing the code for the tags was very simple, as they are all
subclasses of the Struts tags.  I did find some annoyances when I found that I
had to override a base class method, so I ended up making pure copies of some
base class methods and making my own edits.  This was particularly annoying
when I had to copy methods from base-base-classes, where I had to copy the
identical method into more than one of my subclasses.  If I continue with this
strategy, I'll probably refactor this into some "mixin" classes, with methods
that take a bunch of arguments and return a string.  It's also possible that
the Struts tags could be refactored slightly to make it easier to "plug in"
this functionality (Craig offered this idea, not me :) ).

A slightly more difficult task (to figure out, initially), was writing
reasonably complete Cactus-based unit tests for these tags.  My strategy here
was to set HTTP request headers on the "server" side, before calling the tag
methods, which specify required values for tag attributes.  Then, on the
"client" side, I use HttpUnit, JTidy, and Xalan to parse the response (which
actually took very little code on my part), and then read the request headers
and compare the values.  In many cases, when I considered how I could write
code in the test to determine what the expected values should be, I realized
that the only practical strategy was to copy a method from the real tag class
into my test class, and use the output of that method.  If the test fails at
some future date, that means the algorithm in the Struts tag changed, either
intentionally or unintentionally.  If intentionally, then we just change the
unit test again.  Craig mentioned the Tomcat unit tests go a little bit in this
direction, and apparently the "latka" commons library facilitates this kind of
thing.  I'll look at those two pieces at some point.

I've yet to get through all the unit tests.  The vast majority of this unit
test code doesn't even use the EL library.  That is, they're just testing
ordinary Struts tag functionality.  It's likely that these tests could be
back-ported to the Struts unit tests when I'm ready to release this work.

The most difficult task is simply to decide on a reasonable strategy for
attribute naming and "how it works".  I believe that what I have right now will
need some basic changes, but I think I'll describe what I have at this point.

The strategy I settled on (remember: I'm going to change this again) was to
remove the notion of a "name, property" pair for accessing bean values, and
replace it with a basic scheme using two properties, one a "currentValue"
attribute, being an EL expression for the value of the element, and a "name"
attribute for the HTML "name" attribute.

I'm not happy with this for several reasons.

First, with this arrangement, you would likely have duplication of the property
name in both the "currentValue" and "name" attributes, which just demonstrates
why the existing "name, property" pair is good.

Second, related to the first, most elements would have to explicitly specify
the formbean name in the expression, losing the former implicit specification.

Third, although mapping from JSP "name" to HTML "name" is good in some sense,
it's actually inconsistent with existing JSP usage.

So, I'm considering other alternatives.

One idea that Craig pointed out to me is that the JSTL implements the
"prefixes" in JSTL expressions like "pageScope", "param", etc. by setting up a
variable context, so that properties referenced from the variable context can
be done in the EL engine.  It is straightforward to set up a variable context
for an arbitrary variable.  Thus, we could still have the "name, property"
pair, where the "name" attribute has the usual meaning, but the "property"
attribute could be an EL expression, but it would be evaluated in the context
of the explicit or implicit bean (and not wrapped with "${" and "}").  It's
likely that I'll be using this strategy in some form.  Hopefully Shawn can give
me an example of how to do this :) .

The problem that I can see with this strategy, however, is that EL expressions
can be arbitrarily complex, and I'm not sure we can easily guarantee that the
"property" EL expression can always be used as a request parameter name.  In
addition, there might be some confusion with specifying that an attribute will
be evaluated with the EL engine, but that it would NOT be wrapped with "${" and
"}".

I've been wondering whether it would make sense to have an additional attribute
called "elproperty", which the user would wrap with "${" and "}", and would be
used as the element value, in the context of the explicit or implicit bean.
The "property" attribute would still be used as the HTML "name" attribute.  If
the "elproperty" attribute was not present, the behavior would be as it was
before.

Along with these ideas, I did realize another completely different strategy for
building this library.  Instead of trying to change "how it works" under the
covers, I could simply implement a tag library that exactly matches the Struts
tag libraries, but all of whose attributes are evaluated with the EL engine.
The internal behavior of the "name, property" pairs would be unchanged, but
attribute values could be specified as EL expressions in addition to, or
instead of, rtexprvalues.  This would clean up the nasty code I've seen people
write to assemble an "on..." attribute value from pieces.  I believe this only
becomes a slight implementation difficulty for attributes whose type is not
String or boolean, like the "collection" attribute of some tags.  Since from
the point of view of JSP, an EL expression is just a string, that wouldn't map
directly to a javabeans set method that takes a Collection.  In these cases, I
believe I'd have to implement a BeanInfo class that specifies a method in my
subclass, like "setCollectionExpr()" or something like that, which I can map
into the base class "setCollection()" method.

I'd appreciate any useful comments or suggestions.

-- 
===================================================================
David M. Karr          ; Java/J2EE/XML/Unix/C++
[EMAIL PROTECTED]


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to