Return-Path: Delivered-To: apmail-struts-dev-archive@www.apache.org Received: (qmail 69714 invoked from network); 28 Dec 2005 05:27:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 28 Dec 2005 05:27:02 -0000 Received: (qmail 48463 invoked by uid 500); 28 Dec 2005 05:27:01 -0000 Delivered-To: apmail-struts-dev-archive@struts.apache.org Received: (qmail 47757 invoked by uid 500); 28 Dec 2005 05:26:58 -0000 Mailing-List: contact dev-help@struts.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Struts Developers List" Reply-To: "Struts Developers List" Delivered-To: mailing list dev@struts.apache.org Received: (qmail 47746 invoked by uid 99); 28 Dec 2005 05:26:58 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Dec 2005 21:26:58 -0800 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests=HTML_MESSAGE,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: domain of mfncooper@gmail.com designates 64.233.162.204 as permitted sender) Received: from [64.233.162.204] (HELO zproxy.gmail.com) (64.233.162.204) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Dec 2005 21:26:57 -0800 Received: by zproxy.gmail.com with SMTP id s18so1741075nze for ; Tue, 27 Dec 2005 21:26:36 -0800 (PST) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:sender:to:subject:in-reply-to:mime-version:content-type:references; b=F65y5rSmiGRl4IFjwE9F9+NHqueOzOALJL3Ljv7t0qjgaobTlg4Vd07Xho/vg15v6xoH8W77ksGx9QKejiy6rJZvlAPVbRticVEnZ7PsJaflQph+v4GUj60IMjotaA2Ux/qhs+fn3lYUDXjhg043AMxh+p29xpasc4XrEI8ikJo= Received: by 10.65.204.4 with SMTP id g4mr1030354qbq; Tue, 27 Dec 2005 21:26:35 -0800 (PST) Received: by 10.65.97.6 with HTTP; Tue, 27 Dec 2005 21:26:35 -0800 (PST) Message-ID: <16d6c6200512272126k109b6a3dk403f2c38b34546dd@mail.gmail.com> Date: Tue, 27 Dec 2005 21:26:35 -0800 From: Martin Cooper Sender: mfncooper@gmail.com To: Struts Developers List Subject: Re: [shale] Overall requirements for "remoting" feature In-Reply-To: MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_61394_1503247.1135747595785" References: <16d6c6200512272000t6287ba01uba3fba50afa46db@mail.gmail.com> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N ------=_Part_61394_1503247.1135747595785 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On 12/27/05, Craig McClanahan wrote: > > On 12/27/05, Martin Cooper wrote: > > > > On 12/27/05, Craig McClanahan 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 th= e > > > 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 serve= r > > > 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 loa= d > > 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 i= f > the > widget libraries have a way to programmatically determine the resource > paths > for their dependent resources. I understand what you're saying in the above two points. I'll just point ou= t that in the last several years of developing highly dynamic (i.e. boatloads of JavaScript) web apps, I haven't encountered _any_ of the issues you mention. We've simply reserved a subtree off the context, and configured each widget library to point to the relevant location. It has been neither tedious nor error-prone. Furthermore, if a widget library has been hard-coded to a particular location, it's clearly poorly designed, and you're likely to have much bigger issues with it than just putting things in the right place... ;-) * Even without name clashes, requiring the application developer to manuall= y > 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 configur= e > a > special > servlet for serving such resources (to get around the hard coded names > problem). This is a one-off addition to your Ant or Maven build file, is usually at the beginning of the project, and is typically a single copy command. If you're changing the set of widget libraries along the way, then you may hav= e more work to do, but that wouldn't be such a great idea anyway, for a variety of reasons. I'm not arguing against embedding static resources inside of jar files, since that is clearly a good way of providing a consolidated widget library= . In my experience, though, I've found that deploying as much of the application as possible as a single compressed file (e.g. foo.js.gz) provides the best performing app from a client perspective, and it is *very= * worthwhile doing some work up front in the build process to make that happen. (If you want to see an example of the opposite of this, just take a look at the Rialto demo. It's a nightmare.) * 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. If an app has a lot of static resources, as well as a lot of stuff that needs to run in the web container, it can make a big difference to front th= e web container with an HTTP server running on a separate box, so that requests for static content never even reach the web container, leaving tha= t box to deal with only what it has to. That's what I was referring to. -- Martin Cooper * 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, b= y > > > 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 XWor= k > > > 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) wil= l > > > 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=3D38050 > > > [2] http://jakarta.apache.org/commons/chain/ > > > > > > > > > > > > ------=_Part_61394_1503247.1135747595785--