> -----Original Message-----
> From: A mailing list about Java Server Pages specification and reference
> [mailto:[EMAIL PROTECTED]]On Behalf Of Drew Cox
> Sent: Sunday, January 16, 2000 4:10 AM
> To: [EMAIL PROTECTED]
> Subject: Providing application resources to action classes in
> single-servl et delegation model
>
>

...

> <background-info>
>
> As discussed previously on this list, the app implements the
> single-servlet
> event delegation model (is there a recognised name for this?) for
> partitioning the application functionality.  In this scenario the request
> URI (eg. /controller/login) specifies a particular "web action"
> (eg. login),
> which is mapped to a named action class
> (barrack.action.LoginAction) using a
> properties file loaded at application startup.
>
> All the action classes implement a WebAction interface which defines a
> perform(req, resp) method.  This method does the actual work of processing
> the action, populates the required display beans, stores them in
> the Request
> scope and finally forwards to a JSP to render the display.  The single
> controlling servlet simply manages the process of dispatching the
> request to
> the appropriate action class.
>
> This infrastructure is working now and appears to be very worthwhile.  We
> can add functionality to the app (or build completely new apps) without
> touching any of this infrastructure.  I can let the less experience
> developers loose on a web action class stub and a spec and they don't have
> to touch (ie. break) any of the "already-working" bits.  Viva development
> partitioning!
>
> </background-info>

Design reviews, how awesome!

This is almost to a tee how my servlet architecture has evolved over the
last year or so as well. The only additions/differences:

- the controller servlet is a Controller interface (if you were wondering,
that's what the MVC literature calls it), because I had some grand
aspirations to use the same architecture and the same exact business classes
in a non-servlet setting. Also Controllers have Dispatchers which actually
do the work of accessing WebActions and forwarding action messages. Again an
item of flexibility which may be overkill.

- the WebActions can be grouped into WebActivities (which of course could
themselves be grouped) to form a hierarchy (signified by extending the
virtual filesystem, e.g., in your example, /controller/login/newuser and
/controller/login/forgottenpwd, etc). This is mainly to centralize commonly
used services into common code. So for example, the LoginActivity class
actually has a reference to the user/password database or provides a way to
access the actual data, while its WebActions simply use this service to do
their individual process (eg, check, change, etc). This avoids repeating
similar code in all the WebActions related to login.

> The action class perform( ) method actually needs access to additional
> resources beyond the HttpServletRequest and HttpServletResponse
> shown in the
> simplified example above.  In our case most need acces to the custom
> application logging service, security manager and database
> connection pool,
> all of which are stored in the application scope.  This sort of
> requirement
> must be common for others out there implementing this model?
>
> Currently I am just having the controlling servlet extract references to
> these beans from the application scope and passing them as
> parameters to the
> action class perform( ) method.
>
> However, in the Sep 99 JavaWorld acticle on the above model, they
> recommended bundling these sorts of additional parameters into a
> "services"
> array of Objects, to pass them as a single parameter to the perform( )
> method.  I can see some benefits to this, for example, you can readily add
> new services to this array without changing the WebAction interface and
> breaking all your existing implementing classes.  However, I
> don't like the
> idea of hiding the identity of these service classes as positions in an
> array of Objects, then getting run-time ClassCastExceptions when
> I (or more
> likely one of the other developers ;-) get the positions wrong.
>
> I have also seen a slight derivation where the services are bundled into a
> Hashtable and passed to the perform( ) method.  As I see it, you might as
> well just pass a reference to the ServletContext and let the action class
> extract the services themselves.

It strikes me as odd that when needing to bundle data, the most obvious
object-oriented technique didn't come out - make a new type!

An array of Objects seems arcane. As you point out: referencing the Object
fields with numbers has all sorts of difficulties (including needing to
write a manual :-)).

A Hashtable is pretty good since it does make the code readable (at the
small cost of proliferating internal Strings), but there's still no type
safety (what if you mis-spell a String? what if the object is not what you
think it is?).

While if you make a new type (specifically an interface), you get the double
advantages of type safety and extensibility. Say something like a
ServicesManager object which is really a singleton (of some well-defined
scope) whose reference is passed to the WebActions.

Type safety:
        Since your dealing with a specific type, your WebActions classes don't need
to check for the correct type nor to cast objects nor to handle type
incompatibilities. That is, "servicesManager.getLogger()" is safer than
"servicesHash.get("Logger")" because the compiler will check for compliance
and a lot simpler to code ("simple" and "good" are not always opposites
:-)).
        You still have a problem with null objects (what if
servicesManager.getLogger() is null and not only useless but dangerous to
dereference because of NullPointerExceptions?). My suggestion is to use the
NullObject pattern (NullObject by Bobby Woolf, see Pattern Languages of
Program Design, vol 3) - servicesManager.getLogger() must return a valid
(not null) Logger object, even if that object is useless (does nothing), it
can't be dangerous to use. Using Null Objects gets rid of so many
null-checks, that it too has increased the clarity and simplicity of my
code.

Extensibility:
        Since we're dealing with types, you can extend the services of
ServicesManager by subclassing the interface or adding additional
interfaces. Old WebAction code which only knows about certain services, can
still work. New WebAction code which can take advantage of new services will
check to make sure the ServicesManager object provides the needed services
(for example, if you add a security manager service, you can check to see
whether the ServicesManager object is of interface "SecurityManagable"). You
do need to change the ServicesManager maker function (that which actually
makes the ServicesManager object in the first place, thus specified which
class will be used), but all the other solutions would require changing the
core code anyway.

        This is for compile-level extensibility. If you want extensibility without
changing your core code, either at startup (services initiated in
configuration file) or even more dramatically: dynamically during operation,
you will need to add a bit more machinery.

-s

===========================================================================
To unsubscribe: mailto [EMAIL PROTECTED] with body: "signoff JSP-INTEREST".
FAQs on JSP can be found at:
 http://java.sun.com/products/jsp/faq.html
 http://www.esperanto.org.nz/jsp/jspfaq.html

Reply via email to