More comments inline.

Ted Husted wrote:
Comments inline.

On 5/11/06, Allen Gilliland <[EMAIL PROTECTED]> wrote:
I'm still doing some prototyping for both Spring and WebWork
implementations of what I want to do and I certainly wouldn't mind a
little guidance on the WebWork side if you have the time.  I think the
best thing would be for me to describe the problem a little bit and hear
how you might solve it in WebWork.

Right now Roller uses about 6 different Servlets to serve up all of the
user generated weblog content and currently we are using pure Velocity
via the VelocityServlet.  Basically the process is ...

1. request comes in
2. validate request and parse out some data we want
3. load up velocity context based on the needs of the request
4. lookup template used to render the view
5. render template output to response
6. return response

All of that happens in each of these servlets and is tailored towards
the specific type of content being served up for the request.

*The Problem*
I would like to do just enough work to get some view independence in the
process described above so that instead of assuming Velocity for
everything we can provide an option to use various view technologies.
In this case we are only concerned with templating technologies like
Velocity, FreeMarker, etc, so we would never use jsps for example.

The additional task is that our new url structure is very virtualized
and will require some kind of Filter that can inspect incoming requests,
figure out if they are a virtual url, and dispatch them if needed.  So
far, none of the canned url mapping tools from any framework appears to
provide enough flexibility to do what we need, so I am currently
assuming that part will have to be custom.

The entire WebWork/SAF2 architecture relies on the Filter pattern. We
call our implementation "Interceptors", but they can be used just like
Filters, but without acquiring a dependency on HTTP (unless you want
one!).

Interceptors are very easy to write and plug into the framework. In
fact, almost *all* of the framework's funcationality is plugged in
through Interceptors. Each application can decide for itself exactly
which Interceptors it needs (or doesn't need).

I know that both Spring and WebWork offer easy configuration for interceptors and they sound like a great feature which indeed functions basically the same way as a servlet filter. However, my understanding is that in both Spring and WebWork the request is supposed to get to a dispatch servlet, then it may pass through a series of interceptors during it's handling.

This actually doesn't work for us because we need to filter entries *before* they get to an actual servlet endpoint. That's why we need a true servlet filter.

The url space is going to be so virtual that we need to inspect all requests (/*) and we only want to take special action on a subset of those requests. If I map /* to the Spring or WebWork dispatcher servlet then I can't let my servlet container handle things like static files (/foo.png).




It's also important to note that our real goal here is simplicity,
control, and speed.  The content we are rendering is entirely dynamic,
so we need to be flexible.  We aren't doing anything fancy here either,
no form processing, chaining, etc, basically just lookup the data,
render it, return it.  This part of Roller represents about 95% of the
applications usage, so we want it to be as simple and streamlined as
possible yet allow us enough control to hack it however is needed for
optimization.

As mentioned, it's very easy to optimize the WebWork/SAF2 "pipeline"
by being selective about which Interceptors are included. The set of
Interceptors can be adjusted on an action-by-action basis, making the
architecture as flexible as it gets.

In truth, I don't think that interceptors are something we would make extensive use of in this particular component of the UI. In the publishing interface definitely, but in the content delivery component I don't think we would really need them much if at all.




*The Spring Approach*
I call Spring "lightweight" because 1) it has minimal dependencies in
the form of jars, configs, etc and 2) because the code it uses is not
very intrusive.  By intrusive I mean it doesn't try and do things for
you or ask you to tailor much of your code in the Spring pattern, and it
doesn't make many assumptions about how you should (or want to) use the
framework.

Ditto for WebWork/SAF. Almost *nothing* is hardwired, and almost
*everything* is optional. We have a default configuration that most
applications use "out of the box", but it's just as easy for an
application to pick and choose exactly which features are needed.

Hmm, I didn't get that same impression from my initial look. I want to make clear that I am not saying that WW is not flexible enough to let the user configure things however they want, but what I am saying is that the defaults in WW seem more elaborate than Spring.





So, in Spring our VelocityServlets would become Spring Controllers and
those controllers can function exactly as they do now, except that they
would use a generic Map instead of a VelocityContext object for loading
the model.  Then instead of doing steps 4 & 5 in the Controller they
will dispatch to a View object instead.

This requires fairly minimal effort because we simply rename a few
things to turn the servlets into Controllers, and the effort to use a
Map instead of a VelocityContext is a good thing no matter what
framework we choose.  We also have simple and flexible view independence
because we can simply have the controllers return any variation of View
that we want.

I don't know the full details of how the url mapping will get flushed
out.  So far it still looks like we'll need some kind of custom filter
to at least to the first part of the mapping and get requests forwarded
to the appropriate servlet destination.

The WebWork/SAF2 approach might be to use "Results" to accomidate
different types of output. There is already a VelocityResult that does
what you describe.

I have looked at that VelocityResult and it won't work for us for a couple reasons.

1. we don't have an easy way to map result codes to this result. explained more below.

2. the way our decorating stuff works means we would have to make customizations to the Velocity rendering process, so it's very doubtful we could just use this canned Result.



The Results are plugged in, like everything else. The output of the
servlets would be represented as different Result Types. I expect that
either an Interceptor or an Action would determine which Result is
need to service a request, and then the framework would select the
appropriate Result.

 From what you've described so far, I suspect that we might be able to
use a single Action to service the requests, which would then select
the appropriate Result Type. The six servlets would map to six Result
Types, and more could be plugged in as needed.

But wouldn't the more standard way be to use 6 actions and have each Result represent a different view technology. i.e. your example of VelocityResult?

It also seems like the action is meant to be View agnostic, so the real logic of view handling is done by a Result. So perhaps what we would need is a RollerResult class which takes the result code from the Action and determines how best to render it?



In brief, the typical request lifecycle runs something like this:

* The URI requested is mapped to an action. The action includes a Java
handler that can be used to access a database and so forth.

This is always done via a dispatcher servlet correct? so you map /foo/* to dispatcher servlet in the web.xml and the dispatcher will analyze the url again and map to an action?



* The handler's execution is wrapped in a set of "Interceptors" that
fire before and after the handler, like a filter. The Interceptors
provide cross-cutting features that actions might want to share, like
validation, property population, and security. Interceptors can also
use "dependency injection" to set properties on the Action handler
before it executes. All Interceptors are optional. Each action can
have it's own set of Interceptors.

* After the Action executes, it returns a String indicating which
Result should be used.  There are several predefined result types,
including Velocity or FreeMaker templates, JavaServer Pages,
JasperReports, and so forth. Other Result Types can be plugged in as
needed.

I think the one nice thing that Spring does here that WebWork doesn't is that it provides a pluggable ViewResolver. The ViewResolver is just the logic that maps a result code to a Result and can be unaware of how the actual Result is implemented.

AFAIK you can't do that in WW so we would have to define a custom Result which inspects result codes and then somehow passes on to another set of classes to do the actual rendering.

This is important because the result codes we are probably going to return are going to be custom and very dynamic. like ... "velocity:basic:weblog" or "velocity:0112f2dd0ad732dc010ad733f9be0001"



* The selected Result is responsible for returning the response to the
client's request, or transfering control to another resource.

what kind of other resources would a Result transfer to? does WW define a standard or is that something custom?

-- Allen



* The framework also provides for declarative exception handling. If
the Action handler throws an Exception, it can be automatically mapped
to another Result, which can log and display the error. Different
types of Exceptions can be mapped to different Results.

For more on the WebWork/SAF2 architecture, see

* http://confluence.twdata.org/display/WW/Architecture

As an aside, the framework already depends on the technologies you've
mentioned. We use Velocity or FreeMarker under-the-hood to create our
custom UI tags, and many WebWork developers are loyal template users.

We also use Spring as the framework's internal object fractory, and we
also expose Spring to the application. The Spring support in
WebWork/SAF is as seamless as the Spring support in Spring MVC!

It's possible that other popular framework add-ins, like SiteMesh,
might help simplify other Roller features like themes.

-Ted.

Reply via email to