You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Matt Tyson <ma...@gmail.com> on 2006/12/06 23:40:18 UTC

PhaseListener as managed bean?

Can you have a phase listener entry in the config.xml be a managed bean
reference?  

I've got a phase listener that needs a reference to another object to get
some data and I want to externalize that reference.

Thanks.

Matt
-- 
View this message in context: http://www.nabble.com/PhaseListener-as-managed-bean--tf2771203.html#a7729583
Sent from the MyFaces - Users mailing list archive at Nabble.com.


Re: PhaseListener as managed bean?

Posted by Matt Tyson <ma...@gmail.com>.
Simon,

Your idea for using the bean that programmatically creates the phase
listener seems promising ... maybe a servlet listener that just gets the jsf
context and creates the managed bean?

I'm creating an ajax component so what I've done is write out a hidden field
that has the value binding in it (this is set as a component attribute). 
Then when I make the ajax request, I grab that value and send it with the
request.  The phase listener then programmatically resolves the binding bean
(defined in faces-config) and uses it.

Don't know if that'll work in your situation...

Regards,
 Matt


Simon Kitching-3 wrote:
> 
> Matt Tyson wrote:
>> Can you have a phase listener entry in the config.xml be a managed bean
>> reference?  
>> 
>> I've got a phase listener that needs a reference to another object to get
>> some data and I want to externalize that reference.
> 
> Not as far as I know. I would also love this to be possible in order to 
> pass configuration data to phase listeners but haven't figured out how.
> 
> Of course, you do mean an application-scope managed bean, yes? No other 
> scope makes sense as phase listeners are global for a webapp.
> 
> It is possible to create a class that registers itself as a 
> PhaseListener when an instance is created. However if this is listed as 
> an application-scope managed bean, then it doesn't get created until 
> something references it from a page. It would be wonderful if there was 
> some "lazy-init=false" option for application-scope managed beans to 
> force them to be created on webapp startup but this doesn't exist AFAIK.
> 
> As the app I'm currently working on uses Spring, I declare a Spring 
> singleton bean which explicitly looks up the Lifecycle, gets the phase 
> listener list, searches it for an instance of my phase listener type, 
> then calls setter methods to push the config data defined in the spring 
> file into the phase listener. Spring singletons are created when spring 
> is initialised (which is just after JSF is initialised).  This 
> implementation is not terribly clean or intuitive so if anyone has 
> alternate suggestions I'd be keen to hear them..
> 
> Regards,
> 
> Simon
> 
> 

-- 
View this message in context: http://www.nabble.com/PhaseListener-as-managed-bean--tf2771203.html#a7746342
Sent from the MyFaces - Users mailing list archive at Nabble.com.


Re: PhaseListener as managed bean?

Posted by Mike Kienenberger <mk...@gmail.com>.
On 12/7/06, Matt Tyson <ma...@gmail.com> wrote:
> If I'm following you here, then you'd have a phase listener (call it
> 'listenerLoader') that basically instantiates the managedbean that will in
> turn become a phase listener itself?

On rereading your message, I see you're talking about how to
instantiate the configuration bean.   You don't have to worry about
this.   JSF will automatically instantiate it the first time it is
accessed (and create/destroy it as needed based on the scope).

All you need is your configuration bean definition in a
faces-config.xml file, and your phase listener.

Re: PhaseListener as managed bean?

Posted by Mike Kienenberger <mk...@gmail.com>.
No, nothing that clever.  :-)

All I'm suggesting is that you use a value binding to fetch a
reference to a configuration bean.   You could fetch the reference
directly, or you can define a application-scoped configuration-holding
bean that holds any number of needed references or values and fetch
that configuration bean.   You'll have to hardcode the name of the
bean into your phase listener code, so if you want to externally
manage it, I'd hardcode a configuration bean name in, and then read
properties from that bean (each of which could then be externally
managed).

On 12/7/06, Matt Tyson <ma...@gmail.com> wrote:
>
> If I'm following you here, then you'd have a phase listener (call it
> 'listenerLoader') that basically instantiates the managedbean that will in
> turn become a phase listener itself?
>
> Seems like it should work...
>
>
>
> Mike Kienenberger wrote:
> >
> > What about creating a normal application-scoped managed bean to store
> > your configuration and then manually fetching a reference to it using
> > a value binding in the phase listener?
> >
> > To borrow Jeff's example:
> >
> >                FacesContext context = FacesContext.getCurrentInstance();
> >                ValueBinding binding =
> > context.getApplication().createValueBinding("configBean");
> >                return (ConfigBean)binding.getValue(context);
> >
> >
> > On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
> >> Matt Tyson wrote:
> >> > Can you have a phase listener entry in the config.xml be a managed bean
> >> > reference?
> >> >
> >> > I've got a phase listener that needs a reference to another object to
> >> get
> >> > some data and I want to externalize that reference.
> >>
> >> Not as far as I know. I would also love this to be possible in order to
> >> pass configuration data to phase listeners but haven't figured out how.
> >>
> >> Of course, you do mean an application-scope managed bean, yes? No other
> >> scope makes sense as phase listeners are global for a webapp.
> >>
> >> It is possible to create a class that registers itself as a
> >> PhaseListener when an instance is created. However if this is listed as
> >> an application-scope managed bean, then it doesn't get created until
> >> something references it from a page. It would be wonderful if there was
> >> some "lazy-init=false" option for application-scope managed beans to
> >> force them to be created on webapp startup but this doesn't exist AFAIK.
> >>
> >> As the app I'm currently working on uses Spring, I declare a Spring
> >> singleton bean which explicitly looks up the Lifecycle, gets the phase
> >> listener list, searches it for an instance of my phase listener type,
> >> then calls setter methods to push the config data defined in the spring
> >> file into the phase listener. Spring singletons are created when spring
> >> is initialised (which is just after JSF is initialised).  This
> >> implementation is not terribly clean or intuitive so if anyone has
> >> alternate suggestions I'd be keen to hear them..
> >>
> >> Regards,
> >>
> >> Simon
> >>
> >
> >
>
> --
> View this message in context: http://www.nabble.com/PhaseListener-as-managed-bean--tf2771203.html#a7746386
> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>
>

Re: PhaseListener as managed bean?

Posted by Simon Kitching <si...@rhe.co.nz>.
Matt Tyson wrote:
> If I'm following you here, then you'd have a phase listener (call it
> 'listenerLoader') that basically instantiates the managedbean that will in
> turn become a phase listener itself?
> 
> Seems like it should work...

Could do. The original phase listener could then remove itself.

I have been thinking of a more general solution: an "eager bean loader" 
servlet context listener that somehow determines a list of managed bean 
names to load, and instantiates them on webapp startup. It would then be 
possible to write a standard class that uses
   LifecycleFactory.getLifecycle(id).addPhaseListener(this)
in its constructor to register itself on startup, rather than listing it 
in a <listener> tag.

One problem with this is that the "eager bean loader" needs to 
instantiate the objects which means doing something like:
   NeededBean neededBean
     = (NeededBean) facesContext.getApplication()
       .getVariableResolver().resolveVariable(facesContext,
         "neededBean");
which means creating a FacesContext instance when there is no 
ServletRequest/ServletResponse available which means mocking up 
instances of them.


Regards,

Simon

Re: PhaseListener as managed bean?

Posted by Matt Tyson <ma...@gmail.com>.
If I'm following you here, then you'd have a phase listener (call it
'listenerLoader') that basically instantiates the managedbean that will in
turn become a phase listener itself?

Seems like it should work...



Mike Kienenberger wrote:
> 
> What about creating a normal application-scoped managed bean to store
> your configuration and then manually fetching a reference to it using
> a value binding in the phase listener?
> 
> To borrow Jeff's example:
> 
>                FacesContext context = FacesContext.getCurrentInstance();
>                ValueBinding binding =
> context.getApplication().createValueBinding("configBean");
>                return (ConfigBean)binding.getValue(context);
> 
> 
> On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
>> Matt Tyson wrote:
>> > Can you have a phase listener entry in the config.xml be a managed bean
>> > reference?
>> >
>> > I've got a phase listener that needs a reference to another object to
>> get
>> > some data and I want to externalize that reference.
>>
>> Not as far as I know. I would also love this to be possible in order to
>> pass configuration data to phase listeners but haven't figured out how.
>>
>> Of course, you do mean an application-scope managed bean, yes? No other
>> scope makes sense as phase listeners are global for a webapp.
>>
>> It is possible to create a class that registers itself as a
>> PhaseListener when an instance is created. However if this is listed as
>> an application-scope managed bean, then it doesn't get created until
>> something references it from a page. It would be wonderful if there was
>> some "lazy-init=false" option for application-scope managed beans to
>> force them to be created on webapp startup but this doesn't exist AFAIK.
>>
>> As the app I'm currently working on uses Spring, I declare a Spring
>> singleton bean which explicitly looks up the Lifecycle, gets the phase
>> listener list, searches it for an instance of my phase listener type,
>> then calls setter methods to push the config data defined in the spring
>> file into the phase listener. Spring singletons are created when spring
>> is initialised (which is just after JSF is initialised).  This
>> implementation is not terribly clean or intuitive so if anyone has
>> alternate suggestions I'd be keen to hear them..
>>
>> Regards,
>>
>> Simon
>>
> 
> 

-- 
View this message in context: http://www.nabble.com/PhaseListener-as-managed-bean--tf2771203.html#a7746386
Sent from the MyFaces - Users mailing list archive at Nabble.com.


Re: PhaseListener as managed bean?

Posted by Simon Kitching <si...@rhe.co.nz>.
Mike Kienenberger wrote:
> It's not hard to create a FacesContext instance.   I do this in my
> servlet filters.
> http://www.thoughtsabout.net/blog/archives/000033

Yes, but in a PhaseListener constructor there are no 
ServletRequest/ServletResponse objects, so creating a faces context is 
less trivial; mock instances need to be created.

> 
> It's personal preference, but having one hardcode bean seems better
> than iterating through registered phase listeners and pushing values
> to them.

Depends on where the phase listener is. If it's in a library (as mine 
is) then hard-wiring a bean name that webapps using that lib must define 
is not nice. Allowing the using webapp to find and configure the phase 
listener is more elegant. Obviously if the phase-listener is part of the 
webapp then a hard-wired bean name is less of an issue..

> 
> I'd also prefer your beforePhase flag method over constructing a 
> FacesContext.
> 
> As you say, if you only need to fetch the data once, it's

?? missing something :-) ??

> On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
>>
>> It should be possible to get the Application object directly rather than
>> via a FacesContext:
>>   Application app = ((ApplicationFactory)
>>     FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
>>     .getApplication();

Arrgh. Yes, this is possible. However then evaluating the value binding 
required a FacesContext anyway:


>> > To borrow Jeff's example:
>> >
>> >               FacesContext context = FacesContext.getCurrentInstance();
>> >               ValueBinding binding =
>> > context.getApplication().createValueBinding("configBean");
>> >               return (ConfigBean)binding.getValue(context);

Actually, I would prefer using resolveVariable over createValueBinding, 
but that also needs a context param:
   NeededBean neededBean
     = (NeededBean) facesContext.getApplication()
       .getVariableResolver().resolveVariable(facesContext,
          "neededBean");

So creating a FacesContext is indeed needed, which means mocking 
ServletRequest/ServletResponse again...

Regards,

Simon


Re: PhaseListener as managed bean?

Posted by Mike Kienenberger <mk...@gmail.com>.
It's not hard to create a FacesContext instance.   I do this in my
servlet filters.
http://www.thoughtsabout.net/blog/archives/000033

It's personal preference, but having one hardcode bean seems better
than iterating through registered phase listeners and pushing values
to them.

I'd also prefer your beforePhase flag method over constructing a FacesContext.

As you say, if you only need to fetch the data once, it's
On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
> The problem with this approach is that there is no faces context
> available when the phase listener constructor runs. Potentially the
> listener could have an "isIntialised" flag, and on every call to
> beforePhase, if the initialised flag is false then do what you describe
> below. Not elegant though. And as a phase listener needs to be
> thread-safe, any initialisation process occurring in beforePhase would
> need synchronisation.
>
> It should be possible to get the Application object directly rather than
> via a FacesContext:
>   Application app = ((ApplicationFactory)
>     FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
>     .getApplication();
> I haven't checked whether the Application will have been correctly
> initialised if it is fetched like this from within the constructor of a
> PhaseListener. If it is, then this seems better than initialising in
> beforePhase.
>
> Regardless, this approach means that the phase listener needs to
> hard-wire the name of an application-scope bean. ecch. Maybe if it
> simply requires an app-scope bean that has a name matching the
> fully-qualified classname of the listener that isn't *too* ugly; there
> is generally only one instance of a PhaseListener class registered.
>
> Errors also get reported only on the first access, not at app startup;
> not critical but not elegant either.
>
> Cheers,
>
> Simon
>
> Mike Kienenberger wrote:
> > What about creating a normal application-scoped managed bean to store
> > your configuration and then manually fetching a reference to it using
> > a value binding in the phase listener?
> >
> > To borrow Jeff's example:
> >
> >               FacesContext context = FacesContext.getCurrentInstance();
> >               ValueBinding binding =
> > context.getApplication().createValueBinding("configBean");
> >               return (ConfigBean)binding.getValue(context);
> >
> >
> > On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
> >> Matt Tyson wrote:
> >> > Can you have a phase listener entry in the config.xml be a managed bean
> >> > reference?
> >> >
> >> > I've got a phase listener that needs a reference to another object
> >> to get
> >> > some data and I want to externalize that reference.
> >>
> >> Not as far as I know. I would also love this to be possible in order to
> >> pass configuration data to phase listeners but haven't figured out how.
> >>
> >> Of course, you do mean an application-scope managed bean, yes? No other
> >> scope makes sense as phase listeners are global for a webapp.
> >>
> >> It is possible to create a class that registers itself as a
> >> PhaseListener when an instance is created. However if this is listed as
> >> an application-scope managed bean, then it doesn't get created until
> >> something references it from a page. It would be wonderful if there was
> >> some "lazy-init=false" option for application-scope managed beans to
> >> force them to be created on webapp startup but this doesn't exist AFAIK.
> >>
> >> As the app I'm currently working on uses Spring, I declare a Spring
> >> singleton bean which explicitly looks up the Lifecycle, gets the phase
> >> listener list, searches it for an instance of my phase listener type,
> >> then calls setter methods to push the config data defined in the spring
> >> file into the phase listener. Spring singletons are created when spring
> >> is initialised (which is just after JSF is initialised).  This
> >> implementation is not terribly clean or intuitive so if anyone has
> >> alternate suggestions I'd be keen to hear them..
> >>
> >> Regards,
> >>
> >> Simon
> >>
>
>

Re: PhaseListener as managed bean?

Posted by Simon Kitching <si...@rhe.co.nz>.
The problem with this approach is that there is no faces context 
available when the phase listener constructor runs. Potentially the 
listener could have an "isIntialised" flag, and on every call to 
beforePhase, if the initialised flag is false then do what you describe 
below. Not elegant though. And as a phase listener needs to be 
thread-safe, any initialisation process occurring in beforePhase would 
need synchronisation.

It should be possible to get the Application object directly rather than 
via a FacesContext:
  Application app = ((ApplicationFactory)
    FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
    .getApplication();
I haven't checked whether the Application will have been correctly 
initialised if it is fetched like this from within the constructor of a 
PhaseListener. If it is, then this seems better than initialising in 
beforePhase.

Regardless, this approach means that the phase listener needs to 
hard-wire the name of an application-scope bean. ecch. Maybe if it 
simply requires an app-scope bean that has a name matching the 
fully-qualified classname of the listener that isn't *too* ugly; there 
is generally only one instance of a PhaseListener class registered.

Errors also get reported only on the first access, not at app startup; 
not critical but not elegant either.

Cheers,

Simon

Mike Kienenberger wrote:
> What about creating a normal application-scoped managed bean to store
> your configuration and then manually fetching a reference to it using
> a value binding in the phase listener?
> 
> To borrow Jeff's example:
> 
>               FacesContext context = FacesContext.getCurrentInstance();
>               ValueBinding binding =
> context.getApplication().createValueBinding("configBean");
>               return (ConfigBean)binding.getValue(context);
> 
> 
> On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
>> Matt Tyson wrote:
>> > Can you have a phase listener entry in the config.xml be a managed bean
>> > reference?
>> >
>> > I've got a phase listener that needs a reference to another object 
>> to get
>> > some data and I want to externalize that reference.
>>
>> Not as far as I know. I would also love this to be possible in order to
>> pass configuration data to phase listeners but haven't figured out how.
>>
>> Of course, you do mean an application-scope managed bean, yes? No other
>> scope makes sense as phase listeners are global for a webapp.
>>
>> It is possible to create a class that registers itself as a
>> PhaseListener when an instance is created. However if this is listed as
>> an application-scope managed bean, then it doesn't get created until
>> something references it from a page. It would be wonderful if there was
>> some "lazy-init=false" option for application-scope managed beans to
>> force them to be created on webapp startup but this doesn't exist AFAIK.
>>
>> As the app I'm currently working on uses Spring, I declare a Spring
>> singleton bean which explicitly looks up the Lifecycle, gets the phase
>> listener list, searches it for an instance of my phase listener type,
>> then calls setter methods to push the config data defined in the spring
>> file into the phase listener. Spring singletons are created when spring
>> is initialised (which is just after JSF is initialised).  This
>> implementation is not terribly clean or intuitive so if anyone has
>> alternate suggestions I'd be keen to hear them..
>>
>> Regards,
>>
>> Simon
>>


Re: PhaseListener as managed bean?

Posted by Mike Kienenberger <mk...@gmail.com>.
What about creating a normal application-scoped managed bean to store
your configuration and then manually fetching a reference to it using
a value binding in the phase listener?

To borrow Jeff's example:

               FacesContext context = FacesContext.getCurrentInstance();
               ValueBinding binding =
context.getApplication().createValueBinding("configBean");
               return (ConfigBean)binding.getValue(context);


On 12/7/06, Simon Kitching <si...@rhe.co.nz> wrote:
> Matt Tyson wrote:
> > Can you have a phase listener entry in the config.xml be a managed bean
> > reference?
> >
> > I've got a phase listener that needs a reference to another object to get
> > some data and I want to externalize that reference.
>
> Not as far as I know. I would also love this to be possible in order to
> pass configuration data to phase listeners but haven't figured out how.
>
> Of course, you do mean an application-scope managed bean, yes? No other
> scope makes sense as phase listeners are global for a webapp.
>
> It is possible to create a class that registers itself as a
> PhaseListener when an instance is created. However if this is listed as
> an application-scope managed bean, then it doesn't get created until
> something references it from a page. It would be wonderful if there was
> some "lazy-init=false" option for application-scope managed beans to
> force them to be created on webapp startup but this doesn't exist AFAIK.
>
> As the app I'm currently working on uses Spring, I declare a Spring
> singleton bean which explicitly looks up the Lifecycle, gets the phase
> listener list, searches it for an instance of my phase listener type,
> then calls setter methods to push the config data defined in the spring
> file into the phase listener. Spring singletons are created when spring
> is initialised (which is just after JSF is initialised).  This
> implementation is not terribly clean or intuitive so if anyone has
> alternate suggestions I'd be keen to hear them..
>
> Regards,
>
> Simon
>

Re: PhaseListener as managed bean?

Posted by Simon Kitching <si...@rhe.co.nz>.
Matt Tyson wrote:
> Can you have a phase listener entry in the config.xml be a managed bean
> reference?  
> 
> I've got a phase listener that needs a reference to another object to get
> some data and I want to externalize that reference.

Not as far as I know. I would also love this to be possible in order to 
pass configuration data to phase listeners but haven't figured out how.

Of course, you do mean an application-scope managed bean, yes? No other 
scope makes sense as phase listeners are global for a webapp.

It is possible to create a class that registers itself as a 
PhaseListener when an instance is created. However if this is listed as 
an application-scope managed bean, then it doesn't get created until 
something references it from a page. It would be wonderful if there was 
some "lazy-init=false" option for application-scope managed beans to 
force them to be created on webapp startup but this doesn't exist AFAIK.

As the app I'm currently working on uses Spring, I declare a Spring 
singleton bean which explicitly looks up the Lifecycle, gets the phase 
listener list, searches it for an instance of my phase listener type, 
then calls setter methods to push the config data defined in the spring 
file into the phase listener. Spring singletons are created when spring 
is initialised (which is just after JSF is initialised).  This 
implementation is not terribly clean or intuitive so if anyone has 
alternate suggestions I'd be keen to hear them..

Regards,

Simon

Re: PhaseListener as managed bean?

Posted by Dave Brondsema <da...@brondsema.net>.
Matt Tyson wrote:
> Can you have a phase listener entry in the config.xml be a managed bean
> reference?  
> 
> I've got a phase listener that needs a reference to another object to get
> some data and I want to externalize that reference.
> 
> Thanks.
> 
> Matt


I use the SpringBasedPhaseListenerProxy from

http://www.thearcmind.com/confluence/display/SpribernateSF/Configuring+Hibernate,+Spring,+Portlets,+and+OpenInSessionPhaseListener+with+IBM+WebSphere+Portal+Server#ConfiguringHibernate%2CSpring%2CPortlets%2CandOpenInSessionPhaseListenerwithIBMWebSpherePortalServer-SpringBasedPhaseListenerProxy


http://www.springframework.org/docs/api/org/springframework/web/jsf/DelegatingPhaseListenerMulticaster.html
looks interesting too


-- 
Dave Brondsema
Software Developer
Cornerstone University