Nicklas Karlsson wrote:

    * the JSP page is executed. As each JSF tag is encountered, a
       component object is created, then its properties set, then it is
       added to the view tree, and then that component is immediately
       rendered.



So I would basically have to compile my own version of the class that does the
adding of component to the tree and do the work there?



Well, what I was actually suggesting is that you might like to look into
using Facelets as the JSF layout technology rather than JSP. This
project seems to be quite popular; I haven't used it personally as the
project manager has basically mandated use of JSP for the project I'm
currently working on but from my brief investigations it seems much
nicer to work with than JSP - and in particular I believe it won't
suffer from the JSP-related problem I describe above because the entire
UIComponent tree is built before rendering on the first view of the page.

If you have to use JSP, then maybe you'll find this info useful:

It would be easy to intercept the creation of components; that's done by
the Application.createComponent method and you could fairly simply
provide your own Application wrapper. However that's no good, because
the component's ID is set after the component is created and you need
the id to do the filtering you want.

You could override Application.createComponent to always return a proxy
object generated by java.lang.reflect.Proxy, wrapping the real
UIComponent and intercepting the setId method. However that's horribly
inefficient and may not play well with saving/restoring the view state.

The JSF lifecycle is also easy to override, but that's no use in this
case, as the component is being both created and rendered within the
"render" phase of the lifecycle.

The point at which the component's id is assigned is
UIComponentTag.createComponentInstance, and the component is added to
the tree in UIComponentTag.findComponent. However there are no easy
hooks for customising this behaviour. It would be a maintenance
nightmare to actually use your own version of this class. Maybe the
myfaces developers would consider a patch to add a "component creation"
callback hook into this class for purposes like yours that want to
access every component as soon as it is added to its parent.

Adding is actually done via parentComponent.getChildren().add(child).
The getChildren method returns a special list type,
_ComponentChildrenList. However I can't imagine fiddling with this will
lead to any good. That seems to be a dead-end approach too.


Another approach would be to try and intercept stuff as each component
is rendered; for your purposes that's fine, yes? So how about this:
* Override the default RenderKit with a wrapper of your own.
* On each call to addRenderer(...), call:
    super.addRenderer(new MyRendererWrapper(r));
  so all the standard renderer objects have a custom wrapper around them
* Your custom wrapper then intercepts encodeBegin(), and potentially
  updates the component's "rendered" state before delegating on to the
  real renderer.


I can't think of anything else at the moment.

I hope some of this helps.


Regards,

Simon

Reply via email to