You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by David Chisholm <Da...@i2.com> on 2000/06/21 07:39:32 UTC

FW: Does struts provide hooks for app-specific initialization?

Sorry if you get this twice...

-----Original Message-----
From: David Chisholm [mailto:David_Chisholm@i2.com]
Sent: Tuesday, June 20, 2000 11:40 PM
To: struts-user@jakarta.apache.org
Subject: Does struts provide hooks for app-specific initialization?


I've developed my own action framework, and I'm considering switching to
struts given all of the benefits of an open source jakarta project, etc,
etc.

But I've come across a few issues that struts doesn't appear to have the
flexibility (yet) to address.

1.  App-specific initialization

Is there anyplace in struts where I can add a hook to perform application
specific initialization when the struts action servlet is loaded?  If not,
is there some other recommended method of doing this?

In the framework I'm working on, I defined an initialization interface for
applications to implement.  An application's concrete class is specified in
a property file, and when loaded, the action servlet instantiated and
executes the concrete class.  Typical dynamic class loading stuff.

2.  Request pre-processing

Is there a central point in struts where I can examine and modify all
requests before they are delegated to an Action?

I use request pre-processing to perform common actions such as validating
sessions and parsing out cross site scripting special characters from
requests.  The request pre-processor class is configurable by the
application just as the app-specific initialization class is.

3.  Page parameterization

Is there any way to declare output page parameters?

In the applications that I'm working with, many of the pages are
inter-changeable between different workflows, and we make each page
independent of other pages and actions.

A typical action that a page invokes is 'next', and it's up to the 'next'
action to figure out what exactly to do.  The 'next' action is actually a
composite Action that searches for the next Action in the workflow, executes
it, and returns that Action's jsp page.

To make this work, pages have to declare what their output is, and this
allows the 'next' action to forward that output to the next page.

Ideally, pages would also declare what beans that they require and actions
would declare what parameters they require and what beans they output.  Then
we could perform static analysis of the configuration files to find
mis-matches between actions and pages, but that's another to-do item on my
list.

So does anyone have some information/ideas about how to handle these issues
with struts?

David




Re: FW: Does struts provide hooks for app-specific initialization?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
David Chisholm wrote:

>
> Sounds like the Tomcat interceptor idea (haven't followed Tomcat for a
> while - are interceptors still a part of it?)
>

I'm not at liberty to go into the details (until the spec goes public), but
request interception is part of it.

>
> I understand your reservations, and if it were me, I wouldn't implement this
> in struts either.  In the meantime if we switch to struts, I'll just
> subclass ActionServlet.
>

Cool.  Thanks for the interesting discussion.

>
> Thanks,
> David

Craig



RE: FW: Does struts provide hooks for app-specific initialization?

Posted by David Chisholm <Da...@i2.com>.

> -----Original Message-----
> From: Craig R. McClanahan [mailto:Craig.McClanahan@eng.sun.com]
> Sent: Wednesday, June 21, 2000 4:35 PM
> To: struts-dev@jakarta.apache.org
> Subject: Re: FW: Does struts provide hooks for app-specific
> initialization?
>
>

<snip>


>
> One difficulty you are going to have with this approach is a
> restriction in the
> servlet API spec -- when you finally call RequestDispatcher.forward(), the
> request and response objects you pass as parameters have to be
> the original ones
> -- you cannot wrap them at this point.
>


I've noticed.  Funny how your servlet container throws exceptions when it
tries to call it's own methods on your class :)

The action servlet will use the original request/response objects for
forwarding and redirecting.


> An alternative to consider would be to copy all the request
> parameters you want
> into request attributes, doing whatever filtering and replacement that you
> need.  Then you can go ahead and call the action classes with the original
> request and response arguments, with no difficulties.
>

I thought about this but I can't change the semantics of the request object
due to legacy code.


> Another alternative if you're using struts - if you are using an
> ActionForm bean
> associated with your actions, the controller will have copied the matching
> parameters into corresponding properties for you.  You can easily
> modify the
> form bean properties, since you have both getters and setters available.
>


The problem here is that our most critical forms have dynamically generated
field names and a dynamic number of fields.  I would need a special kind of
ActionForm (along with special support for it) that doesn't rely on matching
field names to bean properties to populate the ActionForm.


> > Finally, pre-processors can be chained together using inheritance and
> > calling super.process(request).
> >
> > Are these the kinds of ideas your interested in?
> >
>
> This is an interesting idea, but I'm a little hesitant about
> implementing it
> within Struts.
>
> The reason for this is that the entire topic of "request
> filtering" is currently
> being discussed for the Servlet API version 2.3 spec (should be
> out for public
> review before too much longer :-).  The idea will be that you can
> define some
> sort of chain for pre-processing and post-processing requests
> around the servlet
> itself, and it will be portable across servlet containers
> (because it will be
> part of the spec).
>

Sounds like the Tomcat interceptor idea (haven't followed Tomcat for a
while - are interceptors still a part of it?)

I understand your reservations, and if it were me, I wouldn't implement this
in struts either.  In the meantime if we switch to struts, I'll just
subclass ActionServlet.

Thanks,
David


Re: FW: Does struts provide hooks for app-specific initialization?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
David Chisholm wrote:

> [snip]
> > > 2.  Request pre-processing
> > >
> > > Is there a central point in struts where I can examine and modify all
> > > requests before they are delegated to an Action?
> > >
> > > I use request pre-processing to perform common actions such as
> > validating
> > > sessions and parsing out cross site scripting special characters from
> > > requests.  The request pre-processor class is configurable by the
> > > application just as the app-specific initialization class is.
> > >
> >
> > The processing logic to handle a request is performed in the
> > process() method of
> > ActionServlet, which is mostly a bunch of calls to other methods
> > that do the
> > more detailed processing.  You can again subclass ActionServlet,
> > and override
> > whichever particular processing method makes sense for what you
> > are trying to
> > do.  In this scenario, since you're actually modifying the behavior of
> > ActionServlet, you would take the "override init()" approach to
> > configuring it
> > as well, in order to add the dynamic class loading of your
> > pre-processor class.
> >
> > I'd be interested in your thoughts about some more general purpose
> > "preprocessing" hook that could get called ahead of the remaining
> > methods in the
> > processing chain.
> >
>
> Well, what I had done was to create an interface with one primary method:
>
>   public Boolean process(HttpServletRequest request) throws
> RequestPreprocessorException;
>
> If, for whatever reason, the preprocessor throws a
> RequestPreprocessorException, then the exception contains the WebPage
> (equivalent of ActionForward) to which the request will be forwarded or
> redirected.
>
> The Boolean return value indicates whether the request should be forwarded
> or redirected.  This applies to the WebPage in the
> RequestPreprocessorException as well as the WebPage returned by an Action.
> The WebPage class contains a redirect property too, but the value returned
> above will override it.  (I know this is a little confusing, and I plan to
> make it simpler.)
>

If you were using Struts as the basis, you might just return an ActionForward
from the preprocessor instead of a boolean.  Then you could implement something
like this, for example:

    protected void processActionInstance(...) ... {

        RequestPreprocessor preprocessor = ... find the right one ...
        ActionForward forward = preprossor.process(...);
        if (forward == null)
            super.processActionInstance();
        else
            ... do the forward or redirect trick ...

    }

so that your preprocessor would return null if everything is fine (go on and
call the action), or a non-null ActionForward that says where to go and how to
get there.

>
> Another feature that I need to add to the request pre-processor is the
> ability to change the request and response objects.  Our application can
> manage it's own clustered environment, but to do that, it needs to wrap the
> servlet container's request and response objects with our own versions
> before the request and response objects are passed to any Actions.  This
> will also allow us to filter out special characters in the request before
> sending the request to an Action.
>

One difficulty you are going to have with this approach is a restriction in the
servlet API spec -- when you finally call RequestDispatcher.forward(), the
request and response objects you pass as parameters have to be the original ones
-- you cannot wrap them at this point.

An alternative to consider would be to copy all the request parameters you want
into request attributes, doing whatever filtering and replacement that you
need.  Then you can go ahead and call the action classes with the original
request and response arguments, with no difficulties.

Another alternative if you're using struts - if you are using an ActionForm bean
associated with your actions, the controller will have copied the matching
parameters into corresponding properties for you.  You can easily modify the
form bean properties, since you have both getters and setters available.

> Finally, pre-processors can be chained together using inheritance and
> calling super.process(request).
>
> Are these the kinds of ideas your interested in?
>

This is an interesting idea, but I'm a little hesitant about implementing it
within Struts.

The reason for this is that the entire topic of "request filtering" is currently
being discussed for the Servlet API version 2.3 spec (should be out for public
review before too much longer :-).  The idea will be that you can define some
sort of chain for pre-processing and post-processing requests around the servlet
itself, and it will be portable across servlet containers (because it will be
part of the spec).

I know it doesn't help your immediate need very much, but this particular
problem is one I'd like to wait and let the standards process deal with, instead
of trying to do something application specific, and limited to what a servlet
itself can do.

>
> > >
> > > 3.  Page parameterization
> > >
> > > Is there any way to declare output page parameters?
> > >
> > > In the applications that I'm working with, many of the pages are
> > > inter-changeable between different workflows, and we make each page
> > > independent of other pages and actions.
> > >
> > > A typical action that a page invokes is 'next', and it's up to
> > the 'next'
> > > action to figure out what exactly to do.  The 'next' action is
> > actually a
> > > composite Action that searches for the next Action in the
> > workflow, executes
> > > it, and returns that Action's jsp page.
> > >
> > > To make this work, pages have to declare what their output is, and this
> > > allows the 'next' action to forward that output to the next page.
> > >
> > > Ideally, pages would also declare what beans that they require
> > and actions
> > > would declare what parameters they require and what beans they
> > output.  Then
> > > we could perform static analysis of the configuration files to find
> > > mis-matches between actions and pages, but that's another to-do
> > item on my
> > > list.
> > >
> > > So does anyone have some information/ideas about how to handle
> > these issues
> > > with struts?
> > >
> >
> > Actions do declare what ActionForm bean they use (if any), and support was
> > recently added for ValidatingActionForm beans -- the controller
> > servlet will
> > call the validate() method and return to the original entry form
> > if it detects
> > any errors.
> >
>
> This is a nice feature.
>
> > For the action classes themselves, the concept of looking up the
> > next" page to
> > be displayed (i.e. the next action in a workflow) by a logical
> > name was added.
> > The default Struts implementation lets you preconfigure lookup
> > tables of either
> > global logical names, or local names that are specific to this action (or
> > both).  The example app's LogonAction uses this technique to
> > forward to a page
> > with logical name "success", for example, after an authenticated
> > logon.  The
> > fact that this page is named "/mainMenu.jsp" is a configuration parameter.
> >
>
> Understood.  This is what I do except that an action only has a single
> logical page.
>
> > Within a page, it is sometimes useful to be able to reference other pages
> > directly (because you're only manipulating the view, not changing
> > the state of
> > the system -- for the latter, you should still go through an
> > action that uses
> > the logical mapping described in the previous paragraph).  An
> > example would be
> > the "Next" and "Previous" buttons of a multi-page report, like
> > the results of a
> > search engine lookup.
> >
>
> This is where the struts framework and mine differ.  I don't allow pages to
> be accessed directly.  The requests have to be funneled through the action
> servlet.  This is so that every request passes through the request
> preprocessor first.
>
> So the flow is always request -> action -> page.
>
> Ideally the page doesn't know anything about any other pages, so I needed an
> action that could choose other actions to execute.  The actions that this
> workflow action use are configurable, and the choice is made based on
> information in the request.
>
> Besides choosing which actions to execute, the workflow action also forwards
> any output from one page, i.e. request parameters, to the next action in the
> workflow.
>
> To do this, I separately configure pages and actions.  Actions specify a
> logical name for a page (just like struts), but the logical page is defined
> separately from the action and it can have more than just a path attribute.
>
> In this case, a page definition includes the names of the request parameters
> that it produces.  From this attribute a workflow action can tell what
> request parameters from the current request should be forwarded to the
> WebPage (ActionForward).  The forwarded parameters are stored in a class
> called WebContext (though ActionContext would be a better name); the
> WebContext is added to the request with setAttribute; and I have static
> helper methods (soon to be custom tags) than can automatically add this
> context data to a hyperlink.
>
> (sorry for the long explanation)
>
> > There was a proposal to extend the recent ActionForward mapping
> > values (that let
> > action classes refer to pages by logical names) into a global
> > resource that can
> > be accessed from a custom tag.  Then, in your page, you could generate a
> > hyperlink or button (for example) based on the logical name of
> > the next action
> > in the view.  Does that sound like it would be useful in your scenario?
> >
>
> I'm kinda doing this now, but without exposing the logical page inside the
> page since I want the pages to only refer to actions.  If I could extend the
> attributes of a logical 'PageMapping' just like an ActionMapping, then I
> think this would be a great feature.
>
> David
>
> > >
> > > David
> >
> > Craig
> >
> >


Re: FW: Does struts provide hooks for app-specific initialization?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
[pushed "Send" a little too fast..."]

David Chisholm wrote:

> > >
> > > 3.  Page parameterization
> > >
> > > Is there any way to declare output page parameters?
> > >
> > > In the applications that I'm working with, many of the pages are
> > > inter-changeable between different workflows, and we make each page
> > > independent of other pages and actions.
> > >
> > > A typical action that a page invokes is 'next', and it's up to
> > the 'next'
> > > action to figure out what exactly to do.  The 'next' action is
> > actually a
> > > composite Action that searches for the next Action in the
> > workflow, executes
> > > it, and returns that Action's jsp page.
> > >
> > > To make this work, pages have to declare what their output is, and this
> > > allows the 'next' action to forward that output to the next page.
> > >

OK, that part is pretty easy.  If you've declared a <forward> for each action
with the logical name "next", you can identify and return the way to get to the
next page from the action's perform() method:

    return (mapping.findForward("next"));

See next paragraphs regarding parameters.

>
> > > Ideally, pages would also declare what beans that they require
> > and actions
> > > would declare what parameters they require and what beans they
> > output.  Then
> > > we could perform static analysis of the configuration files to find
> > > mis-matches between actions and pages, but that's another to-do
> > item on my
> > > list.
> > >
> > > So does anyone have some information/ideas about how to handle
> > these issues
> > > with struts?
> > >
> >
> > Actions do declare what ActionForm bean they use (if any), and support was
> > recently added for ValidatingActionForm beans -- the controller
> > servlet will
> > call the validate() method and return to the original entry form
> > if it detects
> > any errors.
> >
>
> This is a nice feature.
>
> > For the action classes themselves, the concept of looking up the
> > next" page to
> > be displayed (i.e. the next action in a workflow) by a logical
> > name was added.
> > The default Struts implementation lets you preconfigure lookup
> > tables of either
> > global logical names, or local names that are specific to this action (or
> > both).  The example app's LogonAction uses this technique to
> > forward to a page
> > with logical name "success", for example, after an authenticated
> > logon.  The
> > fact that this page is named "/mainMenu.jsp" is a configuration parameter.
> >
>
> Understood.  This is what I do except that an action only has a single
> logical page.
>
> > Within a page, it is sometimes useful to be able to reference other pages
> > directly (because you're only manipulating the view, not changing
> > the state of
> > the system -- for the latter, you should still go through an
> > action that uses
> > the logical mapping described in the previous paragraph).  An
> > example would be
> > the "Next" and "Previous" buttons of a multi-page report, like
> > the results of a
> > search engine lookup.
> >
>
> This is where the struts framework and mine differ.  I don't allow pages to
> be accessed directly.  The requests have to be funneled through the action
> servlet.  This is so that every request passes through the request
> preprocessor first.
>
> So the flow is always request -> action -> page.
>
> Ideally the page doesn't know anything about any other pages, so I needed an
> action that could choose other actions to execute.  The actions that this
> workflow action use are configurable, and the choice is made based on
> information in the request.
>

I don't have any problem with the "page doesn't know anything about other pages"
rule.  The only exception that I've considered for my own use is the multi-page
report scenario, where you re-use the current page again with a different
starting point in your collection of rows.  But that's an exeption to the
general  MVC design pattern (and I justify it to myself by saying "you're only
adjusting the view, not the model" :-).

>
> Besides choosing which actions to execute, the workflow action also forwards
> any output from one page, i.e. request parameters, to the next action in the
> workflow.
>
> To do this, I separately configure pages and actions.  Actions specify a
> logical name for a page (just like struts), but the logical page is defined
> separately from the action and it can have more than just a path attribute.
>

So an action can deal with more than one page's requests, and it can also deal
with more than one next step in the workflow, right?  So it has to know not only
what page the request came from (easy to determine) but what step in what
workflow it's currently doing?  I *think* I'm starting to get it.


>
> In this case, a page definition includes the names of the request parameters
> that it produces.  From this attribute a workflow action can tell what
> request parameters from the current request should be forwarded to the
> WebPage (ActionForward).  The forwarded parameters are stored in a class
> called WebContext (though ActionContext would be a better name); the
> WebContext is added to the request with setAttribute; and I have static
> helper methods (soon to be custom tags) than can automatically add this
> context data to a hyperlink.
>
> (sorry for the long explanation)
>

It would help me understand a little better if you could send me (privately is
fine) the config files for your pages and actions for a reasonably complete
application.  I'm sure I'd understand what you are describing better from that.

>
> > There was a proposal to extend the recent ActionForward mapping
> > values (that let
> > action classes refer to pages by logical names) into a global
> > resource that can
> > be accessed from a custom tag.  Then, in your page, you could generate a
> > hyperlink or button (for example) based on the logical name of
> > the next action
> > in the view.  Does that sound like it would be useful in your scenario?
> >
>
> I'm kinda doing this now, but without exposing the logical page inside the
> page since I want the pages to only refer to actions.  If I could extend the
> attributes of a logical 'PageMapping' just like an ActionMapping, then I
> think this would be a great feature.
>
> David
>

Craig



RE: FW: Does struts provide hooks for app-specific initialization?

Posted by David Chisholm <Da...@i2.com>.
comments below...

> -----Original Message-----
> From: Craig R. McClanahan [mailto:Craig.McClanahan@Eng.Sun.COM]
> Sent: Wednesday, June 21, 2000 11:13 AM
> To: struts-dev@jakarta.apache.org
> Subject: Re: FW: Does struts provide hooks for app-specific
> initialization?
>
>
> David Chisholm wrote:
>

<snip>

> > 1.  App-specific initialization
> >

<snip>

>
> There are a couple of approaches you can take:
>
> * Subclass the ActionServlet class, and override the init() method to do
>   something like this:
>
>     public void init() throws ServletException {
>
>         super.init();
>         initMyOwnStuff();
>
>     }
>
> * Create a second "startup" servlet that initializes your
> application specific
>   objects and stores them in the servlet context attributes.  The example
>   application that comes with Struts does this to initialize its
> "database"
>   objects, and I used appropriate <load-on-startup> values to initialize
>   the database information first.
>


Thanks, I'm leaning towards the former for the reason you mention below.


> >
> > 2.  Request pre-processing
> >
> > Is there a central point in struts where I can examine and modify all
> > requests before they are delegated to an Action?
> >
> > I use request pre-processing to perform common actions such as
> validating
> > sessions and parsing out cross site scripting special characters from
> > requests.  The request pre-processor class is configurable by the
> > application just as the app-specific initialization class is.
> >
>
> The processing logic to handle a request is performed in the
> process() method of
> ActionServlet, which is mostly a bunch of calls to other methods
> that do the
> more detailed processing.  You can again subclass ActionServlet,
> and override
> whichever particular processing method makes sense for what you
> are trying to
> do.  In this scenario, since you're actually modifying the behavior of
> ActionServlet, you would take the "override init()" approach to
> configuring it
> as well, in order to add the dynamic class loading of your
> pre-processor class.
>
> I'd be interested in your thoughts about some more general purpose
> "preprocessing" hook that could get called ahead of the remaining
> methods in the
> processing chain.
>


Well, what I had done was to create an interface with one primary method:

  public Boolean process(HttpServletRequest request) throws
RequestPreprocessorException;

If, for whatever reason, the preprocessor throws a
RequestPreprocessorException, then the exception contains the WebPage
(equivalent of ActionForward) to which the request will be forwarded or
redirected.

The Boolean return value indicates whether the request should be forwarded
or redirected.  This applies to the WebPage in the
RequestPreprocessorException as well as the WebPage returned by an Action.
The WebPage class contains a redirect property too, but the value returned
above will override it.  (I know this is a little confusing, and I plan to
make it simpler.)

Another feature that I need to add to the request pre-processor is the
ability to change the request and response objects.  Our application can
manage it's own clustered environment, but to do that, it needs to wrap the
servlet container's request and response objects with our own versions
before the request and response objects are passed to any Actions.  This
will also allow us to filter out special characters in the request before
sending the request to an Action.

Finally, pre-processors can be chained together using inheritance and
calling super.process(request).

Are these the kinds of ideas your interested in?



> >
> > 3.  Page parameterization
> >
> > Is there any way to declare output page parameters?
> >
> > In the applications that I'm working with, many of the pages are
> > inter-changeable between different workflows, and we make each page
> > independent of other pages and actions.
> >
> > A typical action that a page invokes is 'next', and it's up to
> the 'next'
> > action to figure out what exactly to do.  The 'next' action is
> actually a
> > composite Action that searches for the next Action in the
> workflow, executes
> > it, and returns that Action's jsp page.
> >
> > To make this work, pages have to declare what their output is, and this
> > allows the 'next' action to forward that output to the next page.
> >
> > Ideally, pages would also declare what beans that they require
> and actions
> > would declare what parameters they require and what beans they
> output.  Then
> > we could perform static analysis of the configuration files to find
> > mis-matches between actions and pages, but that's another to-do
> item on my
> > list.
> >
> > So does anyone have some information/ideas about how to handle
> these issues
> > with struts?
> >
>
> Actions do declare what ActionForm bean they use (if any), and support was
> recently added for ValidatingActionForm beans -- the controller
> servlet will
> call the validate() method and return to the original entry form
> if it detects
> any errors.
>


This is a nice feature.


> For the action classes themselves, the concept of looking up the
> next" page to
> be displayed (i.e. the next action in a workflow) by a logical
> name was added.
> The default Struts implementation lets you preconfigure lookup
> tables of either
> global logical names, or local names that are specific to this action (or
> both).  The example app's LogonAction uses this technique to
> forward to a page
> with logical name "success", for example, after an authenticated
> logon.  The
> fact that this page is named "/mainMenu.jsp" is a configuration parameter.
>


Understood.  This is what I do except that an action only has a single
logical page.


> Within a page, it is sometimes useful to be able to reference other pages
> directly (because you're only manipulating the view, not changing
> the state of
> the system -- for the latter, you should still go through an
> action that uses
> the logical mapping described in the previous paragraph).  An
> example would be
> the "Next" and "Previous" buttons of a multi-page report, like
> the results of a
> search engine lookup.
>


This is where the struts framework and mine differ.  I don't allow pages to
be accessed directly.  The requests have to be funneled through the action
servlet.  This is so that every request passes through the request
preprocessor first.

So the flow is always request -> action -> page.

Ideally the page doesn't know anything about any other pages, so I needed an
action that could choose other actions to execute.  The actions that this
workflow action use are configurable, and the choice is made based on
information in the request.

Besides choosing which actions to execute, the workflow action also forwards
any output from one page, i.e. request parameters, to the next action in the
workflow.

To do this, I separately configure pages and actions.  Actions specify a
logical name for a page (just like struts), but the logical page is defined
separately from the action and it can have more than just a path attribute.

In this case, a page definition includes the names of the request parameters
that it produces.  From this attribute a workflow action can tell what
request parameters from the current request should be forwarded to the
WebPage (ActionForward).  The forwarded parameters are stored in a class
called WebContext (though ActionContext would be a better name); the
WebContext is added to the request with setAttribute; and I have static
helper methods (soon to be custom tags) than can automatically add this
context data to a hyperlink.

(sorry for the long explanation)

> There was a proposal to extend the recent ActionForward mapping
> values (that let
> action classes refer to pages by logical names) into a global
> resource that can
> be accessed from a custom tag.  Then, in your page, you could generate a
> hyperlink or button (for example) based on the logical name of
> the next action
> in the view.  Does that sound like it would be useful in your scenario?
>

I'm kinda doing this now, but without exposing the logical page inside the
page since I want the pages to only refer to actions.  If I could extend the
attributes of a logical 'PageMapping' just like an ActionMapping, then I
think this would be a great feature.

David




> >
> > David
>
> Craig
>
>


Re: FW: Does struts provide hooks for app-specific initialization?

Posted by "Craig R. McClanahan" <Cr...@Eng.Sun.COM>.
David Chisholm wrote:

> Sorry if you get this twice...
>
> -----Original Message-----
> From: David Chisholm [mailto:David_Chisholm@i2.com]
> Sent: Tuesday, June 20, 2000 11:40 PM
> To: struts-user@jakarta.apache.org
> Subject: Does struts provide hooks for app-specific initialization?
>
> I've developed my own action framework, and I'm considering switching to
> struts given all of the benefits of an open source jakarta project, etc,
> etc.
>
> But I've come across a few issues that struts doesn't appear to have the
> flexibility (yet) to address.
>
> 1.  App-specific initialization
>
> Is there anyplace in struts where I can add a hook to perform application
> specific initialization when the struts action servlet is loaded?  If not,
> is there some other recommended method of doing this?
>
> In the framework I'm working on, I defined an initialization interface for
> applications to implement.  An application's concrete class is specified in
> a property file, and when loaded, the action servlet instantiated and
> executes the concrete class.  Typical dynamic class loading stuff.
>

There are a couple of approaches you can take:

* Subclass the ActionServlet class, and override the init() method to do
  something like this:

    public void init() throws ServletException {

        super.init();
        initMyOwnStuff();

    }

* Create a second "startup" servlet that initializes your application specific
  objects and stores them in the servlet context attributes.  The example
  application that comes with Struts does this to initialize its "database"
  objects, and I used appropriate <load-on-startup> values to initialize
  the database information first.

>
> 2.  Request pre-processing
>
> Is there a central point in struts where I can examine and modify all
> requests before they are delegated to an Action?
>
> I use request pre-processing to perform common actions such as validating
> sessions and parsing out cross site scripting special characters from
> requests.  The request pre-processor class is configurable by the
> application just as the app-specific initialization class is.
>

The processing logic to handle a request is performed in the process() method of
ActionServlet, which is mostly a bunch of calls to other methods that do the
more detailed procesing.  You can again subclass ActionServlet, and override
whichever particular processing method makes sense for what you are trying to
do.  In this scenario, since you're actually modifying the behavior of
ActionServlet, you would take the "override init()" approach to configuring it
as well, in order to add the dynamic class loading of your pre-processor class.

I'd be interested in your thoughts about some more general purpose
"preprocessing" hook that could get called ahead of the remaining methods in the
processing chain.

>
> 3.  Page parameterization
>
> Is there any way to declare output page parameters?
>
> In the applications that I'm working with, many of the pages are
> inter-changeable between different workflows, and we make each page
> independent of other pages and actions.
>
> A typical action that a page invokes is 'next', and it's up to the 'next'
> action to figure out what exactly to do.  The 'next' action is actually a
> composite Action that searches for the next Action in the workflow, executes
> it, and returns that Action's jsp page.
>
> To make this work, pages have to declare what their output is, and this
> allows the 'next' action to forward that output to the next page.
>
> Ideally, pages would also declare what beans that they require and actions
> would declare what parameters they require and what beans they output.  Then
> we could perform static analysis of the configuration files to find
> mis-matches between actions and pages, but that's another to-do item on my
> list.
>
> So does anyone have some information/ideas about how to handle these issues
> with struts?
>

Actions do declare what ActionForm bean they use (if any), and support was
recently added for ValidatingActionForm beans -- the controller servlet will
call the validate() method and return to the original entry form if it detects
any errors.

For the action classes themselves, the concept of looking up the next" page to
be displayed (i.e. the next action in a workflow) by a logical name was added.
The default Struts implementation lets you preconfigure lookup tables of either
global logical names, or local names that are specific to this action (or
both).  The example app's LogonAction uses this technique to forward to a page
with logical name "success", for example, after an authenticated logon.  The
fact that this page is named "/mainMenu.jsp" is a configuration parameter.

Within a page, it is sometimes useful to be able to reference other pages
directly (because you're only manipulating the view, not changing the state of
the system -- for the latter, you should still go through an action that uses
the logical mapping described in the previous paragraph).  An example would be
the "Next" and "Previous" buttons of a multi-page report, like the results of a
search engine lookup.

There was a proposal to extend the recent ActionForward mapping values (that let
action classes refer to pages by logical names) into a global resource that can
be accessed from a custom tag.  Then, in your page, you could generate a
hyperlink or button (for example) based on the logical name of the next action
in the view.  Does that sound like it would be useful in your scenario?


>
> David

Craig