On Thursday, January 9, 2003, at 12:05  PM, Drew Davidson wrote:
The basic premise still holds though: Struts makes you jump through hoops to do even the most trivial of things. You ALWAYS have to have Java code (Struts 1.1 makes this a bit better with DynamicForm) to support your views. In my opinion this is a barrier to clarity for very simple cases (like the counter increment).
DynaForm's suck!  :)

The current value of the count is <%= count %>.
Click <ognl:hyperlink action="[:[ incrementCount() ]]">here</ognl:hyperlink> to increment the count.
The thing that stands out to me about what I see here is that I need some bizarre syntax "[:[....]]" mumbo jumbo. How is that simpler than this?

<html:link forward="count">here</html:link>

I realize you've embedded the actual "action" right there in your template, and that is sort of cool, but I wouldn't think that is "designer friendly". This is what I see as Tapestry's biggest perk - the HTML is literally _HTML_ and the separation is clean and elegant - like WebObjects, except perhaps even slicker. Does WebOGNL support that type of separation too, and your examples are just showing one way of doing it?

I don't think that Struts' way of forcing a single way of doing things is making things clearer or better.
Just my perspective - in doing Struts I don't feel very "forced" to do anything a particular way. There are many ways to mix and match ways of doing things with it. And please trust that I'm not a Struts evangelist here. I'm just searching for the Holy Grail of web presentation tier frameworks and we use Struts because its commonplace (so developers you can hire know it - thats a good reason, right?) and its got a lot of books on it.

WebOGNL supports several types of actions out of the box, mainly to give flexibility on how you organize your application. The "component actions" you see above are very easy to use and are based on the premise that you want to perform some small bit of code and redisplay the same page. These actions do not have to be changed if the component is embedded deep within other components - they just work regardless of nesting (Struts requires that you forward to a page at the end of the action - no way to signal "redisplay the same page again" unless you explicitly have a "forward" for it).
Not entirely true. Action mappings in Struts have an 'input' attribute. For any decent form, you'd set that attribute and it tells Struts where to go back to if there are validation errors. In a Struts action if you wanted to go back to the same page you'd just do this:

return mapping.getInputForward();

Yes, this is perhaps an explicit forward, but its a forward that would be defined regardless in order to handle validation errors that do not even make it to the action execute() method.

My point with the rant on the site is that Struts is a Procrustean bed - it forces you into a certain mold of doing things and will not tolerate deviation.
I don't feel Struts is like that. But perhaps I just haven't seen how much better things could be with WebOGNL yet. I look forward to it being released, open-sourced, and well documented so I can try it out and take it for a serious test drive.

This is Velocity code I assume (I haven't used it). I would argue that $count vs <%= session.count %> is somewhat trivial. It makes it more unclear because the "count' variable could be in request, page, session or context. The "search path" thing is (IMNSHO) unnecessary and dangerous because it relies on implicit communication. If I were to write this page and you modified some code that called it you have to know in advance that the count is a request, page, session or context variable and program accordingly.
In Struts, using <bean:write name="count"/> grabs "count" by searching the scopes from inner to outer to find it, so it wouldn't matter which scope it is in. You can add scope="session" if you want to pin it down though.

Having done Struts and JSP for a while I am always concerned with the amount of stuff you have to keep in your head at any given time. The Struts config file entries are completely out of hand.
Thank goodness for XDoclet! :)

No argument there. But so are J2EE deployment descriptors - and we can't fight those, now can we? But we can use better tools to generate them.

In order to have an action (no matter how trivial) I have to write a host of configuration tags that wire up the Form, Action and ActionMapping; then I have to write Java classes to implement these. By the time all of this infrastructure is completed THEN I can start on the meat of the code that implements the action; with WebOGNL I would have moved on and gotten more work done.
Excellent! I look forward to such higher productive days. Honestly I really do.


Form handling has always been a pet peeve of mine. Struts requires you to plan, IN ADVANCE, all of the things that will appear on the form. This sounds reasonable but you are then locked out of doing something as simple as a variable-row table where each cell is editable. Oh, I know you can do it by clever naming of the values and using DynamicForms (or no forms at all, just processing request parameters). But Struts basically throws you to the wolves on this one. This is a problem mostly because it (a) forces you to name every element uniquely in the form and (b) implement an ActionForm subclass that has bindings for these.
No question that doing advanced forms is tricky in Struts. I fight with it, admittedly. But, in general, the applications I've built do not have that many of them and so its the exception rather than the norm.

Here's a more real-life example: If I just want to read an n x m matrix of integers in Struts I would probably get a whiteboard and two Tylenol. In WebOGNL I write this off the top of my head:

<!-- matrix.osp -->
<!-- component that presents an n (rowCount) x m (colCount) matrix of integers in a table and allows editing -->
<ognl:parameter name="matrix"/>
<ognl:parameter name="colCount"/>
<ognl:parameter name="rowCount"/>

<table>
<ognl:form>
<ognl:for init="[row = 0]" condition="[row < rowCount]" inc="[row = row + 1]">
<tr>
<ognl:for init="[col = 0]" condition="[col < colCount]" inc="[col = col + 1]">
<td><ognl:textfield valueType="int" value="[ matrix[row][col] ]" html:size="6"/></td>
</ognl:for>
</tr>
</ognl:for>
<tr><td colspan="<%= colCount %>"><ognl:submit/></td></tr>
</ognl:form>
</table>

It is called thusly:

<ognl:variable name="matrix" initialValue="[ { new int[3], new int[3], new int[3], new int[3] } ]"/>
<ognl:component component="matrix" matrix="[matrix]" colCount="[matrix[0].length]" rowCount="[matrix.size]"/>

I double-dog dare you to write this in Struts and make it clearer or easier to use. Remember it works with a variable number of rows and columns and what you see above is EVERYTHING - there is not, nor does there need to be, any Java code to support this. It handles it's submit by itself (there is nothing to do - only converting string parameters to ints which ognl:textfield does automatically given the "valueType" attribute, and storing the values somewhere, which the matrix[row][col] expression does quite succinctly).
Very cool example!

Thanks for that Drew. And no, there would be no such better, comparable, or even closely reasonable solution in Struts for this case.

I've removed the rant since it seems to be offensive to some.
I love the rant... I just wanted to be sure that you were using best practices Struts so that its a more reasonable comparison that a self-respecting Struts developer could dig rather than rolling their eyes at the scriptlet junk.

Erik


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

Reply via email to