Excellent! Michael Oliver AppsAsPeers LLC 7391 S. Bullrider Ave. Tucson, AZ 85747 Phone:(520)574-1150 Fax:(520)844-1036
-----Original Message----- From: Erik Hatcher [mailto:[EMAIL PROTECTED]] Sent: Thursday, January 09, 2003 11:32 AM To: [EMAIL PROTECTED] Subject: [jug-discussion] Web frameworks (was: Re: [jug-discussion] January Presentation) On Thursday, January 9, 2003, at 01:03 PM, Drew Davidson wrote: > Erik Hatcher wrote: > >> On Thursday, January 9, 2003, at 02:01 AM, Tim Colson wrote: >> >>> Plus... I don't use JSP anymore, just Velocity templates + Struts. >>> >>> So the view in my webapp wouldn't be this: >>> <%= request.getSession().getAttribute("count") %> >> >> >> And (and I think I e-mailed Drew this a while back too), a seasoned >> Struts developer wouldn't use scriptlets anyway. I would do this: >> >> <bean:write name="count"/> >> >> instead. > > Yes, this is true. What you have done demonstrates a couple of other > bad things about JSP and Struts. Where is "count"? It is in the > search path of { request, page, session, context} of course! It's up > to you to guess, of course, if you are reading someone else's code. > Or you can grovel all the source code that may have forwarded to this > page and see where it sticks it, or you could rely on your > organization's "conventions" about where this should be placed...well > I hope you get the point. We use conventions. Just to be petty, the order is {page, request, session, application} (page and request were reversed in Drew's comment). But yup, right. >> And my hyperlink would be: >> >> <html:link page="/count.do">increment</html:link> >> >> Or it could be even cleaner expressed as: >> >> <html:link forward="count">increment</html:link> > > So you have had to > > (1) come up with a name for an action AND a forward, uniquely across > ALL applications running in this context : All applications? Well, the Struts Way would be to only have a single application within a WAR, at least that is how I do it. Struts 1.1 now had the concept of "modules" where you can have multiple configuration files and paths in there are relative to the module and aren't "global" per se. Ugly, yes. I don't use modules - use multiple WAR's for different applications - that separates J2EE security too, and allows deployment to different application servers. > (3) figure out the ONE location that this count will be allowed to > forward to - whatever the mapping is of the "success" forward. You > cannot just allow it to redisplay the same page (does returning null > do this? I don't know) Returning null indicates the Action has completely handled the response (i.e. it could server up an image or binary file). So returning null generally would return a blank page if you haven't written anything in that action. An Action can forward to any number of forwards, and they could be defined dynamically. You have to return an ActionForward instance, but that could point to any URL (if its a redirect) or any context URL if its a server-side forward. > (4) Write the struts-config.xml entries for your "count.do" action and > the action mapping, plus figure out where the forwards go. Again, XDoclet to the rescue. XDoclet generates my JSP pages from a form bean definition. So I write a form bean, generate the starter JSP, and then XDoclet generates my form bean definitions. We currently code the action mappings by hand, but thats because I think putting them in @tags is lame. > By this time, in WebOGNL, I have written: > > <ognl:hyperlink action="[:[ session.count = session.count + 1 > ]]">click me</ognl:hyperlink> > > ...and moved on to more stimulating things than writing what amounts > to (conservatively) 30 lines of code to INCREMENT A COUNTER, when 1 > expression would do. Excellent example Drew. I really appreciate you taking the time to carefully explain this with code. This is very helpful in my understanding. How would you do it without putting <ognl:*> tags in the template, and put the code in Java? >> Of course WebOGNL is much more like WebObjects, which I *love*! So >> WebOGNL has a big architectural jump on the hacked thing we call >> Struts (I'm allowed to say its a "hack" because I'm intimate with it, >> but I use it exclusively at my day job). > > I'm allowed to say it's a "hack" because IT IS A HACK :-) No argument from me here, not at all. > I'll put WebOGNL up against any other framework. Name the problem and > I guarantee I can do it in WO (a) faster, (b) clearer and (c) with > less code. I love it! Throwing down the gauntlet! I want to know in what ways WebOGNL is better than Tapestry. Thats the main information I'm after. > + WO component templates can be loaded from anywhere, including the > filesystem, across the web or from a database. This is where its at. Big +1 here. > - Struts/JSP "component" communication is through ad-hoc methods: > either use <jsp:include> with nested <jsp:param> and live with String > parameters only or use request/session/page/context attributes to > communicate - God help you sort out the "conventions" you will have to > invent to keep all of this manageable and straight in your head, not > to mention maintainable by anyone. Request scoped stuff is no big deal... no conventions needed here since they are short-lived and the action/JSP can be kept in tight synchronization. Session variables we have a WebConstants interface where we define them as global statics, and use a package-name prefix construct to keep them separate. Its not too tough, and its maintainable. Sure, someone could go nuts and go around the conventions, but we get CVS commit messages via e-mail, and I beat the snot out of developers that do not adhere to conventions :)) > - Validating a form happens in the ActionForm. You get to return > ActionErrors which are normally displayed above the form in a list. > What happens when I want to know WHY a particular field failed or if I > want to draw all erroneous fields with a red triangle pointing at > them? Roll your own, that's what. I suggest, if you want to be as Struts knowledgeable as possible for sales pitches, that you check out the ValidatorFramework and the XDoclet work I've done. If I want a field in a form bean to be required, I simple do this (my forms extend from ValidatorForm, not ActionForm directly): /** * @struts.validator type="required" */ public void setField(String field) { ... } voila... that field is now a required field. Likewise with any of the builtin Validator validations (date, credit card, etc). There are tags for all features of the Struts Validator pieces. If you could see the hideous XML that this generated, you'd cry. But a lot of Struts developers are writing that crap by hand. As for flagging fields in error, I wrote LabelTag: <custom:label key="FormName.formField"/> That generates the field label, turns it red if there was an error on the field (Validator names the ActionErrors keys by the field name, thankfully) and puts an asterisk by it if it is a required field (the Validator information is accessible and easily checked for whether a field has the required validation set on it, as shown above with the @tags. To see this in action, check out my project: http://www.ehatchersolutions.com/JavaDevWithAnt Its got minimal Struts in it, but all the XDoclet and LabelTag magic is hidden within it. So, while this is not an application that has much of a web interface, the build and XDoclet stuff is really what's being showcased. > As for Tapestry, I think that Howard is doing a great job. He's got > the right idea architecturally and the upcoming Tapestry > implementation (2.4) will go a long way toward making it greater still > (with more accessible templating). Tapestry uses OGNL for bindings, > also :-) So why is WebOGNL better? Why not combine efforts? Do you expect (or care if) WebOGNL gains popularity? Is that the goal, or is it just a fun project for you to use on your own projects? I'm just trying to get a feel for where you are going with WebOGNL... are you trying to usurp Tapestry/Struts? Erik --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]