struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig McClanahan <craig...@apache.org>
Subject Re: [shale] Overall requirements for "remoting" feature
Date Wed, 28 Dec 2005 04:33:37 GMT
On 12/27/05, Martin Cooper <martinc@apache.org> wrote:
>
> On 12/27/05, Craig McClanahan <craigmcc@apache.org> wrote:
> >
> > A recent RFE[1] in our issue tracking system, plus discussions with
> > several
> > folks at the recently completed ApacheCon US conference in San Diego,
> has
> > motivated me to attempt a distillation of where I think Shale's support
> > for
> > "remoting" should go.  For comparision (since there isn't any
> > feature-related documentation to speak of), I'll start with a brief
> > description of the current functionality, and then talk about what seems
> > like a good idea for the future.
> >
> >
> > CURRENT REMOTING FUNCTIONALITY:
> >
> > Shale's application level functionality is supplied by a Servlet filter
> (
> > org.apache.shale.faces.ShaleApplicationFilter).  One of the features of
> > this
> > filter is that it executes a standard Commons Chain[2] chain of commands
> > for
> > each request.  In turn, the default chain that is executed includes a
> > command (org.apache.shale.remote.RemoteCommand) that is invoked if the
> > request URL matches an extension mapping (default is "*.remote").  In
> > turn,
> > this command performs the following tasks:
> >
> > * Creates a ShaleWebContext instance (extension of Commons Chain
> > ServletWebContext implementation)
> >   to represent the "context" passed to each command.
> >
> > * Extracts the context relative path such as "/foo/bar.remote" from the
> > servlet request path properties.
> >
> > * Looks for a corresponding Commons Chain command in a catalog named
> > "remote".  If there is such a
> >   command, invoke it (passing in the constructed ShaleWebContext).  This
> > command is responsible for
> >   constructing a response, which can be done by the usual
> > RequestDispatcher.forward() call -- normally
> >   to a JSP page that might use JSTL and EL expressions -- or
> programmatic
> > construction via an
> >   instance of org.apache.shale.remote.ResponseWrapper that acts much
> like
> > a
> > standard JSF ResponseWriter.
> >
> > * Several default command implementations are provided, including one
> that
> > invokes an arbitrary JSF
> >   value binding expression and stores the result as a ShaleWebContext
> > attribute.
> >
> > While this functionality does support achieving the original goal of
> this
> > portion of Shale (providing back-end support for AJAX enabled JSF
> > components), it has several issues, including:
> >
> > * Bound to Servlet API objects, so not directly portable to a portlet
> > environment.
> >
> > * As described in [1], requires quite a lot of work (plus an
> understanding
> > of
> >   Commons Chain itself) simply to map an incoming URL to a piece of
> > business
> >   logic that produces the response.
> >
> > * Does not directly support serving of static resources (images,
> > JavaScript
> > files,
> >   stylesheets) without mapping each individual resource as an individual
> > command.
> >
> >
> > PROPOSED REMOTING FUNCTIONALITY - GOALS:
> >
> > The remoting support in Shale should be focused on providing
> > client-technology-agnostic mapping of incoming HTTP requests to server
> > side
> > dynamic logic for AJAX-enabled widgets (including AJAX-enabled
> JavaServer
> > Faces components), plus an easy way to serve static resources (from
> either
> > the web application itself or from class loader resources) that the
> client
> > side widgets might require.  This support must operate in either a
> servlet
> > or portlet environment, and require minimal (ideally none in the
> simplest
> > case) configuration at the application level.
> >
> >
> > PROPOSED REMOTING FUNCTIONALITY - IMPLEMENTATION STRATEGY:
> >
> > Shale will provide a PhaseListener implementation that receives
> > notification
> > after the Restore View phase of the request processing lifecycle has
> been
> > completed.  At this point, a "view identifier" (a context-relative path
> to
> > the resource to be processed) will have been identified.  This view
> > identiifer will be compared to one or more preregistered mapping
> patterns
> > --
> > if the view identifier matches, this request will be processed by a
> > corresponding processing logic module, instead of following the usual
> JSF
> > request processing lifecycle.
> >
> > Registering processing logic modules will be easy and extensible.  To
> > minimize the effort required to assemble an application, however, the
> > following standard processing logic modules will be provided:
> >
> > * Serve a static resource corresponding to this view identifier, from
> the
> > web application's
> >   static resources (i.e. starting from the document root).  To be
> > consistent
> > with a servlet
> >   container's standard behavior, no such resources will be served
> directly
> > from the "/WEB-INF"
> >   or "/META-INF" paths.
>
>
> I'm not sure I understand why I would want to use this. Requests for
> static
> content such as this would be processed more efficiently by letting the
> container treat them as static content - or, even better for a high load
> app, moving these files off the web container completely, and into a
> fronting HTTP server.


There are multiple perspectives on why this might actually be a good idea.
Consider that, as an application deveoper, want to use some "widgets" in my
application that require external JavaScript and/or stylesheet resources.
Note that these widgets don't have to be JSF component libraries ... the
issues are more generic than that.

* From the widget developer's point of view, there is no standard mechanism
  to publish static resources required by my widgets, such that they can be
  served up as needed, without either reserving portions of the context
relative
  namespace and/or defining a special processing servlet for those resources
  that can be mapped to some appropriate patterns.  Either technique is
tedious
  and error-prone.

* Requiring the application developer to "reserve" parts of the context
relative
  namespace is unfriendly.  What happens if I want to include two different
  widgets that have been hard coded to the same subdirectories?  Better if
the
  widget libraries have a way to programmatically determine the resource
paths
  for their dependent resources.

* Even without name clashes, requiring the application developer to manually
  copy resources into the output web application structure increases the
compexity
  of the Ant or Maven build script being used, versus simply dropping the
widget
  JAR into WEB-INF/lib that he or she will have to do anyway.  The same
argument
  applies to approaches that require the application deveoper to configure a
special
  servlet for serving such resources (to get around the hard coded names
problem).

* Performance differences, compared to what you suggest (letting the
container serve
  static resources "in the usual way") will only occur if (a) you're not
using a pure Java
  servlet container -- the code that will implement this technique is doing
essentially
  what Tomcat's DefaultServlet does, for exampe, to serve static resource
files, and
  (b) the native implementation of serving static file resources is actually
faster enough
  to matter.  Historically, this has been a no brainer, but recent
improvements the performance
  of pure-Java containers, plus an increased emphasis on ease of development
versus an
  absolute focus on performance, makes this much more of a values-based
decision versus
  one that should be dictated primarily, or solely, by performance
considerations.

* Serve a static resource corresponding to this view identifer, from the
> > class loader resources
> >   of this web application.  For example, this facilitates component
> > libraries that wish to make
> >   JavaScript files available to the client pages that utilize those
> > components, without requiring
> >   *any* specific configuration in web.xml, or manual assembly of
> resources
> > into a reserved
> >   directory of the web application.
>
>
> While I do understand how this would simplify the deployment of
> components,
> again performance will suffer if this is used extensively.


That is a historically accurate assumption.  However, in *many* current
scenarios it is either no longer true (due to improvements in the
performance of pure Java servlet containers) or not relevant in the overall
performance picture (because bottlenecks are dominated by the typical
constraints on database performance and network traffic, not on CPU overhead
on the container).

That's not to say there are *no* circumstances in which the serving of
static resource has critical impact on the overall performance of an
application.  It's just to say that, IMHO, the 80% scenario says "it just
doesn't matter".

Perhaps there
> could be some way to have components extract their static resources at
> startup time, so that they could subsequently be treated as static by the
> web container? Such resources would be harder to deploy to a fronting HTTP
> server, but not impossible if a suitable extraction method can be defined.
> But perhaps that would have to be dealt with in the JSF spec.


It would indeed be nice to have a portable mechanism like that.  But it
doesn't exist in current specs, and (in practical terms) could not exist
until some Servlet spec after the Java EE 5 round (this is too generic a
problem to restrict to only solving it in the JSF spec).

And, if such a mechanism did come into being in some future spec, there's
nothing that stops the remoting implementation support here from taking
advantage of it, without impacting the APIs used by widgets to reference
those resources :-).

--
> Martin Cooper


Craig McClanahan


* Map the view identifier (such as "/foo/bar.remote") to a method binding
> > expression (such as
> >   "#{foo.bar}"), identifying a public method that will be invoked to
> > create
> > the response for this
> >   HTTP request.  The bean containing this method can be a managed bean,
> > and
> > thus created
> >   on demand if needed.  The method itself can call
> > FacesContext.getCurrentInstance() to retrieve
> >   the per-request state information for this request (since we are, by
> > defnition, performing a JSF
> >   request at this point), and can use any desired JSF facilities
> > (including
> > the standard ResponseWriter)
> >   to prepare the actual response.
> >
> > * (Optional) alternative dynamic execution mapping to execute a Commons
> > Chain command
> >   (essentially equivalent to the current functionality, and/or a tie-in
> to
> > Struts Action Framework 1.3.x
> >   type processing logic).
> >
> > * (Optional) alternative dynamic execution mapping to execute an XWork
> > action (essentially
> >   equivalent to what WebWork currently does for mapping incoming URLs to
> > business logic).
> >
> > In addition, the configuration information mapping incoming URL patterns
> > to
> > corresponding processing logic modules will be made available in a
> simple
> > JavaBean stored in application scope, so that dynamic code (such as the
> > renderer for a JSF component wanting to utilize these facilities) will
> > know
> > what kind of context relative URL is required).
> >
> > Given these capabilities, and assuming some default mappings, one could
> > have
> > all of the following facilities with *zero* application level
> > configuration,
> > other than including the appropriate Shale library into /WEB-INF/lib:
> >
> > * For a context relative URL of the form "/web/foo/bar.js", serve the
> > static
> > resource at "/foo/bar.js"
> >   with appropriate content type settings.
> >
> > * For a context relative URL of the form "/classpath/foo/bar.css", serve
> > the
> > resource "/foo/bar.css"
> >   from the webapp classpath (typically, a resource file embedded in the
> > JAR
> > file containing the
> >   component whose renderer requested this resource), with appropriate
> > content type settings.
> >
> > * For a context relative URL of the form "/execute/foo/bar", execute the
> > bar() method on the managed
> >   bean named "foo".  This method will take total responsibility for
> > producing the output, so it can do
> >   whatever it needs.
> >
> >
> > SUMMARY:
> >
> > Thoughts?
> >
> > Craig
> >
> > [1] http://issues.apache.org/bugzilla/show_bug.cgi?id=38050
> > [2] http://jakarta.apache.org/commons/chain/
> >
> >
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message