Thanks a zillion. Will take time to think it through though. The weekend must be a good time for this! :)
Hail Erik :O -----Original Message----- From: Erik Weber [mailto:[EMAIL PROTECTED] Sent: Friday, July 23, 2004 12:13 AM To: Struts Users Mailing List Subject: Re: Tag question (JSP organization) Sure, Raghuram. Caution: long post! It seems every project I've ever seen has an actor called "vendor", so I'll use that as an example. ;) Typically these use cases are required: Add a new vendor account to the system Remove an existing vendor account from the system Edit an existing vendor's account details Find a vendor account using a unique ID Find a vendor account using some combination of criteria other than unique ID Retrieve all account details for a vendor In other words, for each actor, you have the typical 'CRUD' use cases, where 'R' might be complex enough to require several of its own sub-use cases (different ways of viewing, searching). So, translated to URI tokens that make some sense to an end user: add delete edit search view Now let's make them specific to the actor at hand, and make them into full-fledged "action" or "command" URIs (Note: I use path mapping, not extension mapping. Extension mapping changes this whole discussion.) /vendor/add /vendor/delete /vendor/edit /vendor/search /vendor/view But wait, if you've done this before, you know there (typically) are actually two "commands" associated with each use case. If someone wants to add a new vendor to the system, first he must visit some "add" screen, which might contain not much more than a blank form. Then after he submits the form, the application must process his input, and he must visit some "result" screen, that lets him know whether his data made it into the system as a permanent record (this result screen might actually be the equivalent of another "view" action with the data processing and feedback sort of "piggybacking" on the navigation; for example, /viewadd --> submit, process, /viewdetails -- but any way you look at it, it's normally two HTTP requests to get it all done). You can refer to these as "setup" and "execute" actions, respectively. So now we have: /vendor/viewadd (show the blank form) /vendor/executeadd (process the completed form) /vendor/viewsearch /vendor/executesearch . . . You might think at this point that the perfect pattern is not going to hold up. For example, to "view" details of a vendor account, you only need one action, not two. But it depends on how you look at it. If you have a "search" screen, or even a simple list of all vendors, you sort of have your "/viewview", if you will. Once a single vendor is selected, you have your "/executeview". Also, you might not think of separate /viewdelete and /executedelete actions. Rather, you might think only of /executedelete. But, if you have a "confirm" screen (even if it's just a JavaScript popup that says, "Are you sure you want to delete?"), you could think of that as /viewdelete -- so the pattern can hold up if you squint a little. Also you should remember, to hell with the pattern if it doesn't suit you. So you can literally organize your JSPs this way, according to actor: web/vendor/add_or_update.jsp web/vendor/view_details.jsp web/someOtherActor/add_or_update.jsp . . . and so on. Notice the shared page for add and edit (aka "update"). Typically the form is the same, or close to the same, for each of the two usecases. So why not parameterize that form and reuse it, if you can? Rick Reumann's site ( www.*reumann*.net/do/struts/main ) might be of some help on this topic. I know that some of his posts to this list will. In your controller configuration, both /vendor/viewadd and /vendor/viewedit would map to the same JSP (add_or_update.jsp). So now we have the trailing end of our action URIs, but we still need the leading end. That part consists of the application context path (if any), and the controller Servlet path (if any). I say "if any" because the default context and default Servlet mapping (both the equivalent of "/") might suffice. But I like to use an explicit controller Servlet path, such as "/services", because it allows me to delegate other Servlets to "controlling" other things besides the services proper -- such as the dispensing of images (again, if you use extension mapping, you might never have had to consider this). So if your controller is mapped to "/services*" or "/services/*", then action URIs that you want to route through the controller Servlet look like this: <app context>/services/vendor/viewadd And other URIs (that won't be routed to the controller, might be routed to another Servlet or might just be served directly) might look like this: <app context>/images/vendor/rainy_day.gif. I always liked that song by Oscar the Grouch, "Let a Frown Be Your Umbrella (on a rainy, rainy day . . . )". Remember how, on the old Mac OS, Oscar lived in the desktop garbage can? Finally, restricting access to *.jsp in your web-resource-collection element of web.xml can force your users to use the controller Servlet-relative action URIs and prevent them from accessing JSPs directly. Also, I solved the problem that led to this post by putting an init-param in web.xml called "controllerPath". I set its value as an application scope attribute in a plug-in class. Now I can create controller-relative hyperlinks like this, using the JSTL-like tags: <html:link page="${controllerPath}/vendor/home">home</html:link> If someone wants to use extension mapping, I just set controllerPath to be the empty String. Now, what I want to know is, what flies out the window when I decide to learn JSF? I'm afraid to look. ;) By the time I learn JSF, someone will have developed a "CRUD IDE" that builds your entire app in five minutes, based on actor names and a CSS stylesheet. In a few years, we will have highly-paid "stack trace" experts. The average "corporate developer" will see a stack trace and run for the hills, having always thought they were a myth. The manager will have to call in a stack trace expert, who will, at the rate of $700 per hour, begin to explain to all the remaining developers what a "stack" is . . . But seriously, hope this helps a newbie or two. Criticism is always welcome! Erik Raghuram Kanadam wrote: >If you had the time Erik would you explain your method of arranging JSPs by the >actor, seemed a beautiful approach. > >-----Original Message----- >From: Erik Weber [mailto:[EMAIL PROTECTED] >Sent: Thursday, July 22, 2004 1:16 AM >To: Struts Users Mailing List >Subject: Re: Tag question > > >Sorry if this post repeats -- I find that occasionally they are not >making it . . . > > > >Jim, "actor" is precisely what I meant! > >It goes /context/controller/actor/usecase (in my case) > >Sorry I didn't say that correctly. > >But as you point out, I think it doesn't change the point of >the post, that I need to manually make sure the name of the controller >servlet gets into the hyperlinks. > >I wonder if a mapping of "/services" work better than "/services/*". >Haven't tried that . . . > >Thanks, >Erik > > > >Jim Barrows wrote: > > > >> >> >> >> >>>-----Original Message----- >>>From: Erik Weber [mailto:[EMAIL PROTECTED] >>>Sent: Wednesday, July 21, 2004 11:32 AM >>>To: Struts Users Mailing List >>>Subject: Re: Tag question >>> >>> >>>Sorry, I should have explained better what I am doing. >>> >>>My controller Servlet is mapped to /services/* >>> >>>All requests for JSP pages go through the controller, via action >>>mappings. The actions have paths like: >>> >>>/usecase/view_edit_page >>>/usecase/save_existing_record >>>/usecase/view_add_page >>>/usecase/add_new_record >>> >>>So the full links look like: >>> >>><context>/services/usecase/view_edit_page >>> >>>meanhwhile other resources have paths like: >>> >>><context>/images/some_image.gif >>> >>>This keeps other resources out of the scope of the controller (and >>>perhaps into the scope of some other servlet). Also, direct >>>JSP access >>>is prohibited. >>> >>>So in places where I am building hyperlinks (within JSPs), I >>>need to get >>>"/services" into each link, in front of the action URI, but >>>behind the >>>context. And I want to do this in a portable way (in case the Servlet >>>mapping changes). >>> >>> >>> >>> >>If you use html:link and forwards then you can do whatever you want, and won't have >>to change the links themselves. This would be pretty portable as well. >> >> >> >> >> >>>So the idea is to put something like <html:rewrite >>>page="${controller_path}<action_URI_here>"> which literally would be >>>"/services" + "/usecase/action" or >>>"/services/usecase/action". Using the >>>"page" attribute to the tag makes it come out right >>>("/context/services/usecase/action"). >>> >>>(When I say "usecase" here I really should say "collection of >>>usecases" >>>or "function group" to be more accurate). >>> >>>I would be interested in hearing other mapping strategies. >>> >>> >>> >>> >>I map jsp and directories by actor rather then use case, or use case package. Makes >>everything easier (especially declaritive security, then again I've kept the *.do >>mapping, rather then what you're doing. >>That would make your url something like services/actor/useCase, which doesn't get >>around your problem. >> >> >> >> >> >>>For now I'm >>>making sure the JSP can call a method or access a variable >>>that returns >>>"/services". >>> >>>Erik >>> >>> >>> >>>Christian D Hahn wrote: >>> >>> >>> >>> >>> >>>>Are you mapping the jsp to /services in the web.xml? if you do, >>>>getServletPath should return the path you are looking for. >>>> >>>><servlet> >>>><servlet-name>jsp</servlet-name> >>>><jsp-file>/usecase/page.jsp</jsp-file> >>>></servlet> >>>> >>>><servlet-mapping> >>>><servlet-name>jsp</servlet-name> >>>><url-pattern>/services</url-pattern> >>>></servlet-mapping> >>>> >>>>-Chris >>>> >>>>Erik Weber wrote: >>>> >>>> >>>> >>>> >>>> >>>>>Hmm I must be doing something wrong. That's giving me the >>>>> >>>>> >>>>> >>>>> >>>same value >>> >>> >>> >>> >>>>>as Erez's example. Strange, I would have expected it to give me >>>>>"/services". I wonder how I am causing it to give me >>>>>"/usecase/page.jsp". >>>>> >>>>>atta-ur rehman wrote: >>>>> >>>>> >>>>> >>>>> >>>>> >>>>>>Hi Erik, >>>>>> >>>>>>This one worked for me: >>>>>> >>>>>><c:set var="v"> >>>>>><%= request.getServletPath() %> >>>>>></c:set> >>>>>> >>>>>><c:out value="${v}"/> >>>>>><bean:write name="v"/> >>>>>> >>>>>>HTH, >>>>>> >>>>>>ATTA >>>>>> >>>>>>On Tue, 20 Jul 2004 16:20:30 -0400, Erik Weber >>>>>><[EMAIL PROTECTED]> wrote: >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>>>How can I set a variable (I assume with c:set) that will >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>hold the >>> >>> >>> >>> >>>>>>>value >>>>>>>of request.getServletPath, so that I can use it in el tags? >>>>>>> >>>>>>>Thanks, >>>>>>>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] >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>>> >>>>> >>>--------------------------------------------------------------------- >>> >>> >>> >>> >>>>>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] >>>> >>>> >>>> >>>> >>>> >>>> >>>--------------------------------------------------------------------- >>>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] >> >> >> >> >> >> > > >--------------------------------------------------------------------- >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] > > > > --------------------------------------------------------------------- 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]