Skip to main content

How to avoid @PostConstruct on page Faces beans during postback?

19 replies [Last post]
bouteill
Offline
Joined: 2004-07-02

Hello, we're using GlassFishV2/JSAS9.1 with Mojarra 1.2_04-b22-p05 for a large project, and experiencing performance issues on form-less JSF commands when used in conjonction with @PostConstruct annotations. I feel this is an architectural issue I'm not able to resolve though, so I was wondering if anyone could shed some light on whether I'm missing something, there is some known workaround or it's a known JSF problem?

The scenario is as follows:
* Page my.jsp references Faces Beans MyFB.java
* MyFB has @PostContruct method, which execute expensive logic to initialize the data model before rendering phase
* my.jsp has a
* anotherFB.myCommand executes some logic and nav to another.jsp

Now what seems to happen is that when we click on the commandLink, JSF does a postback to the same URL, instantiates MyFB, calls @PostConstruct on MyFB, and then instantiate anotherFB to call myCommand on it and nav to another.jsp
In this situation, the expensive @PostConstruct logic to prepare data for rendering on my.jsp is executed although it is totally useless to the use case and hurts site performance a lot.
I tried to use immediate="true" attribute, but it doesn't seem to prevent the @PostConstruct...
In the case of a JSF form commandButton on the same bean, I can see how that would be necessary, but for a commandLink to another bean, why is JSF calling @PostConstruct on the previous page beans??

I seem to be able to workaround this problem doing an if (getFacesContext().getRenderKit().getResponseStateManager().isPostback(getFacesContext()) in our @PostConstruct method and then make sure all the getters are NPE-safe, but if the commandLink is in a common include file, I'd then have to do this in every single beans within my app, which is not reasonable IMHO.

Has anyone else experienced this problem? Or even maybe worked around it somehow?
I'm curious if I'm missing something or if this is a major JSF architectural issue...
Thanks!

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kenpaulsen
Offline
Joined: 2005-03-30

Somewhere (I don't have the MyFaces source) in the MakeAlias component, it appears they are using EL #{} which points to one of your MB's which is evaluated when they're doing the restore view. Perhaps near:

at org.apache.myfaces.custom.aliasbean.Alias.make(Alias.java:137)

This is not common in my experience... but I know nothing of the makeAlias component. Perhaps that is exactly what they intend to do in order to alias another component (which may require resolving it at unusual times, such as here). If you look at their source, I think you'll probably find your answer, especially if it's well documented.

The applyRequestValues evaluation of the rendered property is quite common. If a component is not rendered, most components will not attempt to apply their submitted values for good reason. The side-effect here is that MB's may be referenced when you don't want them to be.

Is there a way to avoid this? Sure, here are a couple options:

1) You can avoid using MB's in these 2 cases directly. For example, set a pageSession variable (i.e. a view attribute). This will still persist accross requests, not use session, and not invoke any MB's. To do this set the value(s) you need access to in pageSession (if your environment supports that), or perhaps find a way to reference attributes on the viewRoot... something like: #{view.attributes['foo']}. You can initialize foo in your @postconstruct.

2) You can use a lazy or proxy MB. In other words, use a light-weight one that avoids the expensive calls unless that data is absolutely necessary. Not sure if this is an option in your case. Or perhaps you can simply re-organize your MB methods to make the rendered / other values on a less demanding MB (again not sure if this will work for you). (Just saw Ryan's response... which is the same as this.)

Good luck!

Ken

bouteill
Offline
Joined: 2004-07-02

Ken, what is your understanding of what beans [u]should[/u] be invoked on a restore view? Ryan seemed to indicate ones would be if they're referenced in rendered conditions.

When debugging an example, I get 2 types of stack traces for unexpected @PostConstruct invocations:
1) reference in RESTORE_VIEW phase
2) reference in APPLY_REQUEST_VALUES phase
(see stack traces below)

What I'd really like to get clarity on is why those references are evaluated on postback of [u]my[/u] use case and whether this is an architectural requirement or something that could be optimized (or worked around).

Stack #1:
[#|2009-04-16T10:42:29.508-0700|SEVERE|sun-appserver9.1|calliope.web.destination|_ThreadID=17;_ThreadName=httpSSLWorkerThread-8080-1;_RequestID=6dc63b7f-34d7-4ff4-a582-e46bf88df0c6;|DestHotelSearchFacesBean.initialize: calliope.web.destination.DestHotelSearchFacesBean initialize being called

java.lang.RuntimeException

at calliope.web.destination.DestHotelSearchFacesBean.initialize(DestHotelSearchFacesBean.java:75)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at com.sun.faces.vendor.GlassFishInjectionProvider$1.run(GlassFishInjectionProvider.java:277)

at java.security.AccessController.doPrivileged(Native Method)

at com.sun.faces.vendor.GlassFishInjectionProvider.invokeLifecycleMethod(GlassFishInjectionProvider.java:271)

at com.sun.faces.vendor.GlassFishInjectionProvider.invokePostConstruct(GlassFishInjectionProvider.java:201)

at com.sun.faces.vendor.GlassFishInjectionProvider.invokePostConstruct(GlassFishInjectionProvider.java:122)

at com.sun.faces.config.ManagedBeanFactoryImpl.newInstance(ManagedBeanFactoryImpl.java:327)

at com.sun.faces.application.ApplicationAssociate.createAndMaybeStoreManagedBeans(ApplicationAssociate.java:546)

at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:82)

at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143)

at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64)

at com.sun.faces.el.ChainAwareVariableResolver.resolveVariable(ChainAwareVariableResolver.java:96)

at org.apache.shale.faces.ShaleVariableResolver.resolveVariable(ShaleVariableResolver.java:157)

at com.sun.faces.el.VariableResolverChainWrapper.getValue(VariableResolverChainWrapper.java:100)

at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143)

at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64)

at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:86)

at com.sun.el.parser.AstValue.getValue(AstValue.java:127)

at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:206)

at org.apache.myfaces.custom.aliasbean.Alias.computeEvaluatedExpression(Alias.java:108)

at org.apache.myfaces.custom.aliasbean.Alias.make(Alias.java:137)

at org.apache.myfaces.custom.aliasbean.AliasBean.makeAlias(AliasBean.java:357)

at org.apache.myfaces.custom.aliasbean.AliasBean.makeAlias(AliasBean.java:342)

at org.apache.myfaces.custom.aliasbean.AliasBean.processRestoreState(AliasBean.java:230)

at org.apache.myfaces.custom.aliasbean.AliasBeansScope.processRestoreState(AliasBeansScope.java:190)

at javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)

at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:171)

at com.sun.faces.application.ViewHandlerImpl.restoreView(ViewHandlerImpl.java:290)

at org.apache.shale.view.faces.ViewViewHandler.restoreView(ViewViewHandler.java:160)

at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:193)

at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:141)

at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)

at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)

at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)

at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)

at calliope.web.servlet.ClpServletFilter.doFilter(ClpServletFilter.java:201)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)

at org.apache.shale.application.faces.ShaleApplicationFilter.doFilter(ShaleApplicationFilter.java:267)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:297)

at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)

at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)

at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)

at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)

at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)

at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)

at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)

at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)

at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)

at com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380)

at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)

at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)

|#]

Stack #2:
[#|2009-04-16T10:37:04.700-0700|SEVERE|sun-appserver9.1|calliope.web.destination|_ThreadID=17;_ThreadName=httpSSLWorkerThread-8080-1;_RequestID=6dc63b7f-34d7-4ff4-a582-e46bf88df0c6;|DestHotelSearchFacesBean.initialize: calliope.web.destination.DestHotelSearchFacesBean initialize being called

java.lang.RuntimeException

at calliope.web.destination.DestHotelSearchFacesBean.initialize(DestHotelSearchFacesBean.java:75)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at com.sun.faces.vendor.GlassFishInjectionProvider$1.run(GlassFishInjectionProvider.java:277)

at java.security.AccessController.doPrivileged(Native Method)

at com.sun.faces.vendor.GlassFishInjectionProvider.invokeLifecycleMethod(GlassFishInjectionProvider.java:271)

at com.sun.faces.vendor.GlassFishInjectionProvider.invokePostConstruct(GlassFishInjectionProvider.java:201)

at com.sun.faces.vendor.GlassFishInjectionProvider.invokePostConstruct(GlassFishInjectionProvider.java:122)

at com.sun.faces.config.ManagedBeanFactoryImpl.newInstance(ManagedBeanFactoryImpl.java:327)

at com.sun.faces.application.ApplicationAssociate.createAndMaybeStoreManagedBeans(ApplicationAssociate.java:546)

at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:82)

at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143)

at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64)

at com.sun.faces.el.ChainAwareVariableResolver.resolveVariable(ChainAwareVariableResolver.java:96)

at org.apache.shale.faces.ShaleVariableResolver.resolveVariable(ShaleVariableResolver.java:157)

at com.sun.faces.el.VariableResolverChainWrapper.getValue(VariableResolverChainWrapper.java:100)

at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143)

at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64)

at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:86)

at com.sun.el.parser.AstValue.getValue(AstValue.java:127)

at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:206)

at javax.faces.component.UIComponentBase.isRendered(UIComponentBase.java:370)

at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:993)

at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1001)

at org.apache.myfaces.custom.aliasbean.AliasBeansScope.processDecodes(AliasBeansScope.java:214)

at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1001)

at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:493)

at org.apache.shale.view.faces.ShaleViewRoot.processDecodes(ShaleViewRoot.java:55)

at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:101)

at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)

at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)

at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)

at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)

at calliope.web.servlet.ClpServletFilter.doFilter(ClpServletFilter.java:201)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)

at org.apache.shale.application.faces.ShaleApplicationFilter.doFilter(ShaleApplicationFilter.java:267)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:297)

at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)

at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)

at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)

at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)

at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)

at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)

at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)

at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)

at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)

at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)

at com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380)

at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)

at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)

|#]

rlubke
Offline
Joined: 2003-08-21

> 1) reference in RESTORE_VIEW phase

For this case it looks like t:aliasBean, when restoring its state, will evaluate the bean expression.

> 2) reference in APPLY_REQUEST_VALUES phase

The rendered attribute has to be evaluated in order to determine whether or
not the component should be decoded.

So this leads back to my original suggestion. Partition your beans such that those
with expensive logic aren't referenced in attributes that will be evaluated at several
points in the lifecycle such as the 'rendered' attribute. It seems the same holds true
for those that are referenced by t:aliasBean due to how it restores state.

bouteill
Offline
Joined: 2004-07-02

Hi Ryan,
I understand the rendered attributed *is* "evaluated in order to determine whether or not the component should be decoded" and *has* to on a standard form submit.
I also understand the workaround you suggest.
My question was: is it really necessary in my use case for rendered attributes to be evaluated since there's no inputs and the action is on a different bean.
In other words, is this a valid RFE to optimize this use case?
Thanks,

rlubke
Offline
Joined: 2003-08-21

>My question was: is it really necessary in my use case for rendered attributes to be evaluated >since there's no inputs and the action is on a different bean.
>In other words, is this a valid RFE to optimize this use case?

Per the spec, *all* components will have processDecodes() called upon them. The default implementation of processDecodes() will evaluate the rendered attribute.

Keep in mind that other components aside from UIInput need to take action during this phase.
UIForm and UIData are examples of this.

The processing shouldn't make any assumptions about what a particular component type may or may not need to do.

That said, you could create a custom UIViewRoot that overrides processDecodes() to call or not call processDecodes() as you see fit.

bouteill
Offline
Joined: 2004-07-02

Ok so you're saying it's needed regardless for other internal processes of JSF that I'm missing and you do not think there is any opportunity of RFE for the spec development to optimize for this use case so as to not make developer do customizations?
It is ok to say yes, I'm just trying to get a clear answer :)

rlubke
Offline
Joined: 2003-08-21

You can certainly log an RFE against the specification [1].
I don't see us making any changes to the runtime to support custom decode processing. That's where the power of JSF comes in. You can customize just about everything for your needs.

[1] https://javaserverfaces-spec-public.dev.java.net

kenpaulsen
Offline
Joined: 2005-03-30

> The h:form in this use case is dedicated to the
> commandLink. There is [b]nothing else[/b] in it.
> There is no reference to myFB, not even in the
> commandLink. Yet Mojarra still re-instantiate all the
> beans referenced on that page...

I would have expected (as you are expecting), that if the MB's aren't involved, then they wouldn't be involved. :) Apparently this is not happening. One of the many reasons I shy away from using Managed Beans in my own projects (too much work to mange all that "free" management they give you ;) ).

Perhaps you can print a stack trace from inside your @PostConstruct method (or stop the debugger at that location and see the call stack)... that might give you a hint as to the code path that is leading to it being called. Are you using client-side state saving? Maybe in this case, during restore view, it needs to look up something in the bean which has the @PostConstruct?

> I'll refrain from commenting on the arrogant last
> paragraph, but re: GETs, that's what we do right now
> and this is also unsatisfactory in that:
> 1) if you have multiple actions for the URL, you end
> up with an ugly if/else/if/else/etc. in prerender

You are using prerender as your action? I think this is not what you want.

Any GET/action solution should allow you to do anything you want in the action and then let you choose to forward/redirect however you'd want. I haven't used RestFaces myself, but I suspect it should support this. Perhaps the other framework mentioned does as well.

> 2) it forces you to navigate before you know the
> result of the action

It shouldn't.

> JSF command framework is great, I was just looking
> for an optimized version for form-less action use
> cases, but I guess this doesn't exist yet...

Yes, I understand what you're getting at... I'd be curious to see the stack trace to see what is forcing the MB to instantiate. Perhaps a binding attribute will cause this, do you using bindings? (I recommend avoiding the binding hack -- but that's another story...)

Good luck!

Ken

Lincoln Baxter, III

Actually, I spoke too soon, the latest version of PrettyFaces now lets
you skip action methods onPostback.
And it also handles the form-less GET actions.

On Tue, 2009-04-14 at 22:13 -0700, webtier@javadesktop.org wrote:

> > The h:form in this use case is dedicated to the
> > commandLink. There is [b]nothing else[/b] in it.
> > There is no reference to myFB, not even in the
> > commandLink. Yet Mojarra still re-instantiate all the
> > beans referenced on that page...
>
> I would have expected (as you are expecting), that if the MB's aren't involved, then they wouldn't be involved. :) Apparently this is not happening. One of the many reasons I shy away from using Managed Beans in my own projects (too much work to mange all that "free" management they give you ;) ).
>
> Perhaps you can print a stack trace from inside your @PostConstruct method (or stop the debugger at that location and see the call stack)... that might give you a hint as to the code path that is leading to it being called. Are you using client-side state saving? Maybe in this case, during restore view, it needs to look up something in the bean which has the @PostConstruct?
>
> > I'll refrain from commenting on the arrogant last
> > paragraph, but re: GETs, that's what we do right now
> > and this is also unsatisfactory in that:
> > 1) if you have multiple actions for the URL, you end
> > up with an ugly if/else/if/else/etc. in prerender
>
> You are using prerender as your action? I think this is not what you want.
>
> Any GET/action solution should allow you to do anything you want in the action and then let you choose to forward/redirect however you'd want. I haven't used RestFaces myself, but I suspect it should support this. Perhaps the other framework mentioned does as well.
>
> > 2) it forces you to navigate before you know the
> > result of the action
>
> It shouldn't.
>
> > JSF command framework is great, I was just looking
> > for an optimized version for form-less action use
> > cases, but I guess this doesn't exist yet...
>
> Yes, I understand what you're getting at... I'd be curious to see the stack trace to see what is forcing the MB to instantiate. Perhaps a binding attribute will cause this, do you using bindings? (I recommend avoiding the binding hack -- but that's another story...)
>
> Good luck!
>
> Ken
> [Message sent by forum member 'kenpaulsen' (kenpaulsen)]
>
> http://forums.java.net/jive/thread.jspa?messageID=342199
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: webtier-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: webtier-help@glassfish.dev.java.net
>
[att1.html]

kenpaulsen
Offline
Joined: 2005-03-30

> In the case of a JSF form commandButton on the same
> bean, I can see how that would be necessary, but for
> a commandLink to another bean, why is JSF calling
> @PostConstruct on the previous page beans??

I think there is a misunderstanding here. An h:commandLink is the same as an h:commandButton. The difference is only in how they are presented on the screen. A commandLink submits all the data back to the server, which is causing your beans to be used. If this is in a header area, perhaps putting the h:commandLink in its own form will prevent your problem?

I responded to this thread on another email list, and suggested pageSession or conversation scope for caching. While conversation scope may be more difficult to guarantee that it gets cleaned up, pageSession is associated with the UIViewRoot, so it gets managed automatically with the page (note: you don't have to have JSFT or JSF 2.0 to use this, you can do viewRoot.getAttributes().get/put()).

Now that I realize they want a get request + an action (not a h:commandLink or h:outputLink), it might be worth looking at restfaces (https://restfaces.dev.java.net/) or implementing similar behavior. This allows actions to be invoked on GET requests.

All that said... their design seems to be fundamentally flawed as it will make Ajax or even full page refreshes perform poorly if they require their data to be recalculated every (refresh) request. Perhaps a little consulting or training at the customer site would go a long way, there are plenty of good resources available that would be able to clean this up.

Good luck!

Ken

bouteill
Offline
Joined: 2004-07-02

I understand a commandLink also technically submits an h:form. I was just wondering if there was a way to make it behave such as to not re-instantiate beans on the hosting page that have nothing to do with the postback.
The h:form in this use case is dedicated to the commandLink. There is [b]nothing else[/b] in it. There is no reference to myFB, not even in the commandLink. Yet Mojarra still re-instantiate all the beans referenced on that page...

As I responded to Lincoln, caching beans is a workaround but it would also increase memory requirements and require flush considerations for things which should really just be request based... It's not better than prerender IMHO.

I'll refrain from commenting on the arrogant last paragraph, but re: GETs, that's what we do right now and this is also unsatisfactory in that:
1) if you have multiple actions for the URL, you end up with an ugly if/else/if/else/etc. in prerender
2) it forces you to navigate before you know the result of the action
JSF command framework is great, I was just looking for an optimized version for form-less action use cases, but I guess this doesn't exist yet... (at least in out-of-the-box JSF, restfaces project does look interesting)

Message was edited by: bouteill

Lincoln Baxter, III

On Tue, 2009-04-14 at 16:05 -0700, webtier@javadesktop.org wrote:

> I was just looking for an optimized version for form-less action use
> cases, but I guess this doesn't exist yet...

Consider PrettyFaces... although you still need to check
FacesContext.getCurrentInstance().isPostback() yourself.

http://ocpsoft.com/prettyfaces

//getFacesContext().getRenderKit().getResponseStateManager().isPostback(getFacesContext())

[att1.html]

Lincoln Baxter, III

If your bean is Request Scoped, then it will execute @PostConstruct
every request. My first thought would be to use a Session Scoped bean,
or to implement a custom caching solution.

--Lincoln

On Thu, 2009-04-09 at 17:12 -0700, webtier@javadesktop.org wrote:

> Hello, we're using GlassFishV2/JSAS9.1 with Mojarra 1.2_04-b22-p05 for a large project, and experiencing performance issues on form-less JSF commands when used in conjonction with @PostConstruct annotations. I feel this is an architectural issue I'm not able to resolve though, so I was wondering if anyone could shed some light on whether I'm missing something, there is some known workaround or it's a known JSF problem?
>
> The scenario is as follows:
> * Page my.jsp references Faces Beans MyFB.java
> * MyFB has @PostContruct method, which execute expensive logic to initialize the data model before rendering phase
> * my.jsp has a
> * anotherFB.myCommand executes some logic and nav to another.jsp
>
> Now what seems to happen is that when we click on the commandLink, JSF does a postback to the same URL, instantiates MyFB, calls @PostConstruct on MyFB, and then instantiate anotherFB to call myCommand on it and nav to another.jsp
> In this situation, the expensive @PostConstruct logic to prepare data for rendering on my.jsp is executed although it is totally useless to the use case and hurts site performance a lot.
> I tried to use immediate="true" attribute, but it doesn't seem to prevent the @PostConstruct...
> In the case of a JSF form commandButton on the same bean, I can see how that would be necessary, but for a commandLink to another bean, why is JSF calling @PostConstruct on the previous page beans??
>
> I seem to be able to workaround this problem doing an if (getFacesContext().getRenderKit().getResponseStateManager().isPostback(getFacesContext()) in our @PostConstruct method and then make sure all the getters are NPE-safe, but if the commandLink is in a common include file, I'd then have to do this in every single beans within my app, which is not reasonable IMHO.
>
> Has anyone else experienced this problem? Or even maybe worked around it somehow?
> I'm curious if I'm missing something or if this is a major JSF architectural issue...
> Thanks!
> [Message sent by forum member 'bouteill' (bouteill)]
>
> http://forums.java.net/jive/thread.jspa?messageID=341444
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: webtier-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: webtier-help@glassfish.dev.java.net
>
[att1.html]

bouteill
Offline
Joined: 2004-07-02

Lincoln, your suggestions would be a valid workaround, but it would also increase memory requirements and cause cache update considerations for things which should really just be request based... This would also require all FBs of our site to change scope because of possible common include with commandLink (not very scalable IMHO putting the burden on the rest of the webapp). I was hoping for a less tightly-coupled solution where our commandLink could act in such a way as to not disrupt other beans on the page?

rlubke
Offline
Joined: 2003-08-21

You're not experiencing a bug. The spec requires that @PostConstruct/@PreDestroy annotations be processed when the bean comes into or out of scope.

There currently is no way to change this behavior.

Outside of asking the RequestStateManager if the current request is a post-back, and the other suggestions that have already been offered, the only thing I can think of is to partition your managed beans so that those that have expensive rendering requirements are not referenced
in attributes such as rendered or disabled as these expressions will be evaluated multiple times during the lifecycle processing of your view.

bouteill
Offline
Joined: 2004-07-02

Thanks for the clarification Ryan.
I do understand it's a requirement for @PostConstruct to be invoked *if* the bean is to be used.
I guess where I'm at loss is understanding why myFB is invoked on a . Why does the implementation need to instantiate myFB? What is the purpose of that? What does the rendered/disable condition of JSF components in my.jsp have anything to do with anotherFB.myCommand processing?

Ryan Lubke

On 4/13/09 4:28 PM, webtier@javadesktop.org wrote:
> Thanks for the clarification Ryan.
> I do understand it's a requirement for @PostConstruct to be invoked *if* the bean is to be used.
> I guess where I'm at loss is understanding why myFB is invoked on a. Why does the implementation need to instantiate myFB? What is the purpose of that? What does the rendered/disable condition of JSF components in my.jsp have anything to do with anotherFB.myCommand processing?
>
The rendered/disable attribute suggestion was just a general comment. I
can't say why myFB is being instantiated. You'll need to provide more info.
What does the view you're posting back to look like? Does anotherFB
inject a bean that may rely on myFB?

> [Message sent by forum member 'bouteill' (bouteill)]
>
> http://forums.java.net/jive/thread.jspa?messageID=341890
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: webtier-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: webtier-help@glassfish.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: webtier-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: webtier-help@glassfish.dev.java.net

bouteill
Offline
Joined: 2004-07-02

Hi Ryan,
There is no cross-bean injection scenario in this simple use case. I cannot think of why myFB should be instantiated besides the references in rendered attributes of UI components of my.jsp view, which I do have. I'm assuming this is what is happening in the restore view phase?
Can you please confirm whether this is expected JSF behavior to do that on a commandLink to another bean?
If so, could you please explain why JSF feels the need to re-instantiate myFB to execute rendered conditions in this scenario?
If not, are you suggesting that I have some other type of reference to myFB than rendered?

bouteill
Offline
Joined: 2004-07-02

[i]From: Lincoln Baxter, III (linc...@gmail.com)
Date: Apr 9, 2009 10:45:48 pm
List: net.java.dev.glassfish.webtier
If your bean is Request Scoped, then it will execute @PostConstruct every request. My first thought would be to use a Session Scoped bean, or to implement a custom caching solution.
--Lincoln [/i]

Thanks Lincoln. Sorry your response on the mailing list didn't seem to get posted back on the online forum so I missed it.
Your suggestions would be a valid workaround, but it would also increase memory requirements and cause cache update considerations for things which should really just be request based... This would also require all FBs of our site to change scope because of possible common include with commandLink (not very scalable IMHO putting the burden on the rest of the webapp). I was hoping for a less tightly-coupled solution where our commandLink could act in such a way as to not disrupt other beans on the page?