On Thu, 27 Dec 2001, Jesse Alexander (KABS 11) wrote:

> Date: Thu, 27 Dec 2001 10:57:44 +0100
> From: "Jesse Alexander (KABS 11)" <[EMAIL PROTECTED]>
> Reply-To: Struts Developers List <[EMAIL PROTECTED]>
> To: 'Struts Developers List' <[EMAIL PROTECTED]>
> Subject: RE: [Design Discussion] Multiple Controllers Per Web App
>
> Hi,
>
> how about proposing to use only the "prefix"-noptation for the
> servlet-mappings (/do/... instead of /*.do).
>
> Then it might be possible to specify the mappings like:
>
> /(application_1)/*    -->    application-1 action-servlet
> /(application_2)/*    -->    application-2 action-servlet
>
> Wouldn't that make it easier. For bakward compatibility *.do
> still could be used and would drop back to old-style-struts.
>

There are two different types of "mappings" going on, and the choice of
what to do for each are independent:

* Mapping to the controller servlet (typically "*.do" or "/do/*" today),
  that must conform to the rules of the servlet specification.  Note that
  this mapping does *not* apply to JSP pages.

* Associating the context-relative portion of the path to a request URI to
  the particular sub-application it is part of.  This includes *both*
  requests to the controller (for that sub-app), as well as the JSP pages
  that belong to it, in order to make all of the lookups work correctly
  (for example, <bean:message> has to know what sub-application it is
  part of in order to access the right message resources, and an Action
  has to look up it's mappings in the table for this sub-app).

Let's look at a concrete example, and assume we were packaging all of the
existing Struts example web-apps as a sub-application inside a "/portal"
webapp.  Assume the standard "*.do" mapping for the controller.  Now, we'd
have request URIs like this:

  /portal/index.jsp                          Portal home page

  /portal/struts-example/index.jsp           Example home page
  /portal/struts-example/logon.do            Example logon action
  /portal/struts-example/registration.jsp    Example app page
  /portal/struts-example/saveRegistration.do Example app action

  /portal/struts-upload/display.jsp          Upload app JSP page
  /portal/struts-upload/upload.jsp           Upload app JSP page
  /portal/struts-upload/upload.do            Upload app action

If you wanted to use path-based matching for the actions, you'd need to
establish multiple servlet mappings to get it to work right:

  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>/struts-example/do/*</url-pattern>
  </servlet-maping>

  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>/struts-upload/do/*</url-pattern>
  </servlet-mapping>

and the action URIs quoted above would become:

  /portal/struts-example/do/logon
  /portal/struts-example/do/saveRegistration
  /portal/struts-upload/do/upload

without changing any of the JSP page mappings (from the servlet
container's perspective).

Bottom line -- you can still use either kind of mapping for the controller
with no difficulties.  For associating requests with sub-apps, using a
path prefix seems like the only feasible strategy (and it's the strategy
employed in a couple of other frameworks that formally support the notion
of a sub-app).

> Just my 2cents...
>
> Alexander Jesse
>

Craig


> -----Original Message-----
> From: Ted Husted [mailto:[EMAIL PROTECTED]]
> Sent: Thursday, December 27, 2001 5:26 AM
> To: Struts Developers List
> Subject: Re: [Design Discussion] Multiple Controllers Per Web App
>
>
> +1 overall.
>
> Very much one of those brilliant ideas that only seem obvious after
> someone *else* brings it up.
>
> Though I wonder if we need to have a single servlet is catch all the
> requests and then do the mapping. What if the standard servlet-mapping
> for a sub-app matched their prefix, and we let the request be routed by
> the container? The specification says the longest one wins, so
> /this-prefix/*.do should be matched before *.do.
>
> A way to look at this is that given a WAR named
>
> {application-name}.war
>
> our URI breaks down to
>
>     /(application-name}/{servlet-name}/{action-path}
>
> so we might have a configuration like
>
>   <servlet>
>     <servlet-name>default</servlet-name>
>
> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
>     <init-param>
>       <param-name>config</param-name>
>       <param-value>/WEB-INF/conf/default.xml</param-value>
>     </init-param>
>   < ... >
>  </servlet>
>  <servlet>
>     <servlet-name>logon</servlet-name>
>
> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
>     <init-param>
>       <param-name>servlet-context</param-name>
>       <param-value>logon</param-value>
>     </init-param>
>     <init-param>
>       <param-name>config</param-name>
>       <param-value>/WEB-INF/conf/logon.xml</param-value>
>     </init-param>
>     <init-param>
>       <param-name>default</param-name>
>       <param-value>false</param-value>
>     </init-param>
>   < ... >
>  </servlet>
>
>   <servlet-mapping>
>     <servlet-name>default</servlet-name>
>     <url-pattern>*.do</url-pattern>
>   </servlet-mapping>
>
>   <servlet-mapping>
>     <servlet-name>logon</servlet-name>
>     <url-pattern>/logon/*.do</url-pattern>
>   </servlet-mapping>
>
> I believe a "default" servlet with a *.do or /do/* servlet would then
> receive any requests not sent to a longer matching URI (e.g one with a
> servlet-name prefix).
>
> So, with the links being expanded to include the servlet-context (when
> non-blank), and the RequestURI being expanded to return the right
> configuration based on the expanded URI, we might be able to let the
> container do the matching in the normal course.
>
> I'd also suggest that we call multiple-servlet applications "sub-apps"
> or "apps", and reserve "application" to refer to that which could be
> placed into a single Web Application Resource file. Otherwise, it starts
> to get confusing.
>
> This is a *very* exciting idea. It neatly solves several problems, and
> open several new doors. Besides supporting team development, where each
> group can be working on parallel sub-apps, it also makes Struts
> "portlets" much simplier to do. We could start assembling applications
> out of components apps, and resuse code in bulk.
>
> We should give some thought early-on to what other API mechanisms Struts
> "portlets" might need. For example a customization resource to provide a
> common look and feel across sub-applications. This might mean a way to
> specify a global directory (or sub-app) for resources like stylesheets
> and images.
>
> Going the other way, teams working together on parallel sub-apps might
> also want to share message resources, so that if a key is not found in
> the sub-app message resource, it could check the "default" or some other
> global sub-app. The sub-app would then only have to define messages not
> carried in the global app.
>
> Ditto for forwards. If a forward is not found in the local app, should
> it try the global app?
>
> -Ted.
>
>
>
> "Craig R. McClanahan" wrote:
> >
> > One of the highly requested features for Struts has been the concept of
> > wanting to define multiple "applications" (or multiple "controllers")
> > within a single Struts-based web application.  Implementing this feature
> > in the current controller servlet is pretty complicated, due to its
> > assumpations all over the code that there is only one controller.
> >
> > Recent discussions on the STRUTS-DEV list, some thought that Ted Husted
> > put in on the "ContextHelper" class recently checked in, and a little bit
> > of time (Sun is shut down this week, so I've got a little quality time to
> > put in on Struts) leads me to propose a way to accomplish the goals of
> > multiple applications, using a single controller servlet, in a way that
> > should remain backwards-compatible for current users (which is *always* a
> > very important consideration IMHO).
> >
> > The basic design would include the following elements:
> >
> > * Running multiple "applications" within a single web app will be
> >   accomplished by defining each "application" to have a particular
> >   prefix on the context relative path.  Thus, a complete request
> >   URI gets divided into:
> >
> >     /{context-path}/{application-prefix}/{action-select-path}
> >
> > * When the controller processes an incoming request, it will parse
> >   the request URI and try to match it to a particular "application
> >   configuration" by matching against the application prefixes it
> >   knows about, in a manner similar to how a servlet container figures
> >   out which web app to run by matching against the context paths
> >   that it knows about.
> >
> > * In addition to the defined application prefixes, there will be a
> >   "default" application that processes all requests that cannot be
> >   assigned to any other application.  This default application will
> >   be configured *exactly* as the current one-and-only application is
> >   defined, thus maximizing backwards compatibility.
> >
> > * Each application that is defined will have its own struts-config.xml
> >   file.  The initialization parameters of the controller servlet will
> >   define an application prefix, and corresponding path to the config file,
> >   for each supported application.
> >
> > * Internally, all of the static configuration information from a
> >   particular struts-config.xml file will be organized into a single
> >   "application configuration" object.  I've checked in a new package
> >   of classes (org.apache.struts.config) to represent this data.  Each
> >   ApplicationConfig object will be exposed as a servlet context attribute,
> >   rather than all of the individual objects (ActionMappings,
> >   ActionForwards, and so on).  LIKELY EXCEPTION:  The actual
> >   javax.sql.DataSource objects for connection pools.
> >
> > * All cases of "context-relative" paths in the current Struts environment
> >   will be modified to be "application-relative" instead.  This allows you
> >   to configure an application's XML file completely independent of the
> >   application prefix that will be assigned -- exactly the way a web app is
> >   independent of the context path to which it is assigned.  (Note also
> >   that this still works for the "default" application -- think of this as
> >   having a zero-length String as the prefix, so that all application
> >   relative paths are actually context relative.
> >
> > * All logic in the existing classes (and custom tag implementations) that
> >   currently looks up the configuration information in servlet context
> >   attributes, or via method calls on ActionServlet, will need to be
> >   modified to look up the info for the current application instead.  To
> >   facilitate this, we'll add a utility method to RequestUtils that looks
> >   up the appropriate ApplicationConfig object for a given request URI.
> >
> > * Existing classes in org.apache.struts.action that represent the config
> >   information will be deprecated in favor of the new classes in
> >   org.apache.struts.config.  The exception will be ActionMapping (because
> >   it is passed as an argument to the perform() method of action classes),
> >   but ActionMapping will be modified to subclass
> >   org.apache.struts.config.ActionConfig instead of being its own class.
> >   This maximizes backwards compatibility, but *will* require applications
> >   to be compiled against the version of Struts that they are going to
> >   be run against (not a big restriction, IMHO).
> >
> > What do you think?  Does this sound like a strategy that can accomplish
> > the "multiple controllers" feature request without messing up existing
> > Struts based applications?
> >
> > Craig McClanahan
> >
> > --
> > To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
>
> -- Ted Husted, Husted dot Com, Fairport NY USA.
> -- Custom Software ~ Technical Services.
> -- Tel +1 716 737-3463
> -- http://www.husted.com/struts/
>
> --
> To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
>
> --
> To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
>
>


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

Reply via email to