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]>