I agree - I would like to see the inclusion of events for any and all
interesting events.

I think the following article link may be of some interest as well:

http://www.sys-con.com/java/archives/0601/grant/

It includes an interesting implementation of events for template based
processing - for pre and post processing of jsp includes.  I like the
concepts of a Document class and ModelContext.

Personally, I would like to see a View class/interface and ViewContext and
Controller class/interface and Controller Context as well.

Coupled with appropriate event subscriptions and notifications Struts would
more closely resemble the original MVC model.

It would be interesting to use this notification mechanism to allow for
multiple Views to be notified of Model Change Events.  This would open the
door ( a little wider at least ) for other types of application development
such as B2B.

The controller seems the appropriate place from which to fire events.

    * Single ActionEvent class, or subclasses for various types
      of events that have different properties (some events care
      about the current ActionMapping and some don't).

Subclasses

    * SIngle registrations of ActionListeners that receive all types of
      events, or separate registrations for separate event families?

Seperate event listener registrations for event families seems the cleanest
implementation and would eliminate event-storm like activity.

    * An ActionEvent, or the ActionListener that receives it,
      should have knowledge of the ActionServlet
      it is associated with, to provide access to underlying resources
      provided by the servlet.  (The whole event listener model is
      intimately tied to Struts anyway, so this does not seem onerous).

This would be a good place for the Controller class/interface and
ControllerContext.

Just my 2 cents.

Thanks,

Larry

-----Original Message-----
From: Craig R. McClanahan
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Sent: 12/26/00 9:57 PM
Subject: Re: Proposal: RetroFit Struts with the Delegation Event Model

I like the basic idea of event listeners for Struts events.  About the
particular proposal, though, I've got some comments and questions I
would like
feedback on.

* As fleshed out, the only events reported with this model so far
  are before and after an Action's perform() method is called.
  The abstract talks about building listeners for all "interesting"
  events.  If we're going to do a listeners model, I think we should
  extend it to basically all of the processXxx methods, not just
  processPerform().

* If we go with generalized events, putting the firing logic inside
  Action seems wrong -- general purpose support classes, or
  public methods inside ActionServlet, seem more appropriate.

* Given that there will be many more events, we've got some
  representation choices:

    * Single ActionEvent class, or subclasses for various types
      of events that have different properties (some events care
      about the current ActionMapping and some don't).

    * SIngle registrations of ActionListeners that receive all types of
      events, or separate registrations for separate event families?

* I also have a couple of nit-picky type thoughts:

    * Event type codes inside the ActionEvent seem redundant,
      given that the type is implicitly defined by which listener
      method you call.

    * An ActionEvent, or the ActionListener that receives it,
      should have knowledge of the ActionServlet
      it is associated with, to provide access to underlying resources
      provided by the servlet.  (The whole event listener model is
      intimately tied to Struts anyway, so this does not seem onerous).

    * We need to use collection classes (with an implementation I'm
      currently working on) that do not require lots of synchronization
locks
      or new object creations when processing event notifications, since
      they happen on every request.

Thoughts?

Craig



David Geary wrote:

> ABSTRACT
>
> It's often convenient, and sometimes necessary, to handle Struts
events,
> such as when an action has its locale set, or when the action servlet
> processes an action's form. This document proposes retrofitting Struts
> with the delegation event model. That model, which is used by the AWT
> and
> Swing, makes event handling simple, flexible, and scalable.
>
> CREDITS
>
> Delegation and Event Model for Struts? -- posted to struts-dev by
>                                           Robert Leland
>
> INTRODUCTION
>
> Currently, you can use inheritance to handle Struts events like those
> described above. Typically, that means extending ActionServlet and
> overriding a protected method, such as
> ActionServlet.processActionPerform.
>
> Inheritance-based event handling is inflexible and does not scale well
> because event sources and listeners are tightly coupled at compile
time.
> This was evident to AWT engineers, who replaced the AWT's original
> inheritance-based event model with the delegation event model.
>
> The delegation event model, which has its roots in java.util,
implements
> the Observer design pattern to loosely couple event sources and event
> listeners at runtime. That loose coupling makes it easy to associate
> disparate types of objects, so that event listeners can easily react
to
> changes in event sources.
>
> STRUTS AND THE DELEGATION EVENT MODEL
>
> So what does it mean to retrofit Struts with the delegation event
model?
> It means that Struts will fire events when it performs certain
> functions. You can register with Struts as an event listener, and
> handle events as you see fit.
>
> This proposal advocates firing events for all interesting Struts
> functions; for example, the action servlet should fire a robust set of
> events for processing actions and forms, performing mappings, etc.
> Implementing support for those events follows the same
> design pattern discussed in this proposal for implementing action
> events.
>
> This proposal illustrates how to modify Struts to fire events just
> before, and immediately after, a Struts action has its perform method
> invoked. Those events are hereafter known as action events.
>
> IMPLEMENTING ACTION EVENTS AND ACTION LISTENERS
>
> Getting Struts to fire action events is easy. First, we define a
> listener interface and an event class:
>
> org/struts/apache/event/action/ActionListener.java
> org/struts/apache/event/action/ActionEvent.java
>
> Here's the listing for ActionListener:
>
>    public interface ActionListener {
>       public void beforeActionPerform(ActionEvent event)
>                                 throws ServletException;
>       public void afterActionPerform(ActionEvent event)
>                                 throws ServletException;
>    }
>
> ActionListener methods are passed instances of ActionEvent. Here's the
> listing for that class:
>
>    public class ActionEvent extends java.util.EventObject {
>       public static final int BEFORE_ACTION_PERFORM=0,
>                               AFTER_ACTION_PERFORM=1;
>       private int eventType;
>       private HttpServletRequest request;
>       private HttpServletResponse response;
>       public ActionEvent(Action action, int eventType,
>                          HttpServletRequest request,
>                          HttpServletResponse response) {
>          super(action);  // specifies action as the event source
>          this.eventType = eventType;
>          this.request   = request;
>          this.response  = response;
>       }
>       public int getEventType() { return eventType; }
>       public HttpServletRequest  getRequest()   { return request; }
>       public HttpServletResponse getResponse()  { return response; }
>    }
>
> Through action events, action listeners have access to:
>
> event type (BEFORE_ACTION_PERFORM, AFTER_ACTION_PERFORM)
> action
> request
> response
>
> HANDLING ACTION EVENTS
>
> Here's how you use action events and listeners:
>
>    // first, implement a listener that handles action events
>
>    public class MyListener implements
>                    org.apache.struts.event.ActionListener {
>       public void beforeActionPerform(ActionEvent event) {
>          // handle event
>       }
>       public void afterActionPerform(ActionEvent event) {
>          // handle event
>       }
>    }
>
>    // Then register your listener with an action:
>
>    someAction.addActionListener(new MyListener());
>
> Thereafter, MyListener.beforeActionPerform and
> MyListener.afterActionPerform will be called before and after
> someAction's perform method, respectively.
>
> Let's see what changes need to be made to Struts to make this work.
>
> STRUTS MODIFICATIONS FOR SUPPORTING ACTION EVENTS
>
> Only two Struts classes need to be modified to support firing action
> events: Action and ActionServlet. Methods are added to the Action
class
> for registering action listeners and firing events:
>
>    // the following is added to org.apache.struts.action.Action:
>
>    import java.util.Enumeration;
>    import java.util.Vector;
>    import org.apache.struts.event.action.ActionEvent;
>    import org.apache.struts.event.action.ActionListener;
>
>    public class Action {
>       ...
>
>       protected static Vector listeners = new Vector();
>
>       public void addActionListener(ActionListener listener) {
>          listeners.addElement(listener);
>       }
>       public void removeActionListener(ActionListener listener) {
>          listeners.remove(listener);
>       }
>       public void beforeAction(ActionEvent event)
>                                         throws ServletException {
>          fireEvent(event);
>       }
>       public void afterAction(ActionEvent event)
>                                         throws ServletException {
>          fireEvent(event);
>       }
>       protected void fireEvent(ActionEvent event)
>                                        throws ServletException {
>          Enumeration it = listeners.elements();
>
>          while(it.hasMoreElements()) {
>             ActionListener listener =
>                         (ActionListener)it.nextElement();
>
>             switch(event.getEventType()) {
>                case ActionEvent.BEFORE_ACTION_PERFORM:
>                             listener.beforeActionPerform(event);
>                             break;
>                case ActionEvent.AFTER_ACTION_PERFORM:
>                             listener.afterActionPerform(event);
>                             break;
>             }
>          }
>       }
>       ...
>    }
>
> Now Struts actions can fire action events to registered action
> listeners. ActionServlet.processActionCreate is modified to call
> Action.fireEvent, like this:
>
>    protected void processActionPerform(Action action,
>                                         ActionMapping mapping,
>                                         ActionForm formInstance,
>                                         HttpServletRequest request,
>                                         HttpServletResponse response)
>                                         throws IOException,
>                                                ServletException {
>       action.fireEvent(new ActionEvent(action,
>                        ActionEvent.BEFORE_ACTION_PERFORM,
>                        (HttpServletRequest)request,
>                        (HttpServletResponse)response));
>
>        // Perform the requested action
>       ActionForward forward =
>             action.perform(mapping, formInstance, request, response);
>
>       action.fireEvent(new ActionEvent(action,
>                                 ActionEvent.AFTER_ACTION_PERFORM,
>                                 (HttpServletRequest)request,
>                                 (HttpServletResponse)response));
>       ...
>    }
>
> CONCLUSION
>
> Struts will be a more powerful and extensible framework if developers
> can handle Struts events, which can be accomplished as outlined in
this
> proposal with the delegation event model.
>
> This proposal has illustrated modifying Struts to fire action events.
If
> this proposal is accepted, Struts should be modified to fire many
> meaningful events. The ActionServlet class alone is rife with methods
> that should fire events; for example, initApplication,
> processActionForm, processLocale, etc.
>
> A practical use of the action events discussed in this proposal can be
> found in the proposal 'Tokens and Events: Handling Illicit Access to
> Sensitive Pages'. That proposal implements an action listener
> that restricts access to actions that are sensitive to the back
button,
> reload button, or bookmarks.

Reply via email to