A couple of thoughts on the details of what you're describing:

* A value change listener does not have to be a separate class
  that is registered by a nested tag in the page -- for the standard
  components, at least, you can use a method binding:

    <h:inputText ... valueChangeListener="#{mybean.myListener}"/>

  where myListener() is a public void method that accepts a
  ValueChangeEvent.  This isn't a lot more concise than nested
  tags if you need them on every single input component, but is
  pretty handy if you only need a few of them.

* To transparently listen to *all* the events, one can gain an
  inspiration from understanding how event firing is actually done.
  A component that wants to fire an event will call (on itself)
  the queueEvent(FacesEvent) method.  The default implementation
  of this calls queueEvent() on the parent component, and so on up
  to the UIViewRoot at the root of the tree, which does the actual
  broadcasting later.  If you had a parent custom component around
  the form, or a custom form component itself, it could "notice" all the
  value change events that were being emitted and do something
  interesting with them.

As to general architectural style, I don't personally build
applicatons based on fine grained changes to individual fields ... I
find it easier to have my action handlers deal with all the values
(the same way that a Struts app would deal with all the form bean
fields), and dispatch to a processing chain (or whatever) there. 
Indeed, the Shale Use Cases example app (nightly builds at
<http://svn.apache.org/builds/struts/nightly/struts-shale/>)
illustrates my thoughts on how you do stuff like this, along the
following lines:

* Each JSP page has a corresponding backing bean
  (Shale calls it a ViewController) that contains the
  *values* of all the input fields (like a Struts form bean
  but JSF takes care of conversions for you), plus
  methods for all your submit buttons and event listeners.

* The backing bean is a managed bean in request scope,
  so it acts like a combination of a Struts form bean and an
  action (without having to worry about thread safety, since
  there is an instance per request)

* The JSP page uses value binding expressions on each
  input field to the corresponding property in the backing bean.

* The JSP page uses method bindings on the "action"
  attribute of submit buttons, binding them to an appropriate
  action method in the same backing bean.

* The action methods themselves would then gather up
  whatever values they need (from the instance variables,
  since you're in the same bean) and pass them to the
  facade.  Alternatively, if you're willing to tie your facade
  to view tier APIs, you could pass the backing bean itself,
  since it contains properties for all the relevant values.

Fine grained value change processing, for *all* input fields, strikes
me as a lot more work ... but if it works for you, that's ok too.

Craig



On Mon, 17 Jan 2005 11:34:43 -0500, Sean Schofield
<[EMAIL PROTECTED]> wrote:
> I'm going to be migrating an application to JSF during the course of
> this year and I am starting to think about some of the particular
> design issues.  Any feedback would be appreciated.
> 
> The problem is that I need a list of changes from a form.  The current
> way I'm doing this is to clone the "document" object that is bound to
> these values in my Struts form and then compare the two objects using
> some of the commons BeanUtils stuff.  This works pretty well and in
> the end, I get a list of changes that I can pass through a "chain of
> responsibility" pattern where each element of the chain can inspect
> the list of changes for ones they are interested in.
> 
> I love the value change listener option in JSF and I think this will
> be a big improvement for me.  I don't have to implement clone methods
> on my document bean (and the many properties that are also document
> beans).
> 
> What I'm trying to avoid is adding a listener manually through the JSF
> page to every element (since I'm basically interested in all changes
> so I need them all.)  I had an idea that I could have a request scope
> bean that could be the listener for all changes.  That bean would
> compile the master list of changes as it received that value change
> events from all of the components its listening to.
> 
> Then I could have a request-level bean that would listen for the end
> of the "update model values" phase.  That bean could take the list of
> changes and call some business logic methods through a facade.  Since
> the model would be updated at this point, I could pass references to
> those beans to the facade depending on the nature of the change (ex.
> change in document owner).
> 
> What do you guys think about this general approach?
> 
> sean
>

Reply via email to