JSF: how prevent stackoverflow due to recursion during build phase (despite rendered test)

喜你入骨 提交于 2019-12-01 22:42:17

That question is a perfect example why I dislike JSF: As soon as you do anything non-trivial (such as - gasp - trying to reuse code on a large scale), you need knowledge of JSF internals.

JSF represents a view with a component tree. That tree is built out of the view definition by tag handlers, is stateful, and lives until the user leaves the view. Inclusion of a composite component is done by a tag handler. c:if is also implemented by a tag handler.

The component tree is traversed during every phase of the request processing lifecycle. It is however up to the individual components to decide whether (or how many times) their children are processed. That's how the rendered attribute is implemented: During every phase, the component checks whether it is rendered, and skips processing of itself (and its children) if not.

The JSF view scope is kept within the UIViewRoot, which is the root node of the component tree. It is therefore unavailable while tag handlers are processed. That's one of its many shortcomings :-)

So what can you do?

  1. You can include a composite component for every activity in the activity tree, but because that inclusion happens at view build time, it can not occur on demand. Even setting aside problems of mutual recursion, it is likely wasteful to create a dialog for every subactivity on the off chance that the user will want to see that particular dialog. But you can of course limit recursion with c:if, you just need to put the information in a scope available at view build time.

  2. Alternatively, you can create a single dialog in the component tree, but have it show a different activity at different times by binding the current activity to an EL-expression whose target you update. Of course that means only a single dialog is shown at a time. If you need to stack the dialogs of subactivities, you might create as many dialogs as the tree is deep.

  3. Alternatively, you can create a single component that recursively processes itself in every phase of the request processing lifecycle. That can be either an existing component you adapt (such as a tree component), or one written from scratch (which is not exactly trivial because it the component tree is stateful, and state must be preserved and restored for every iteration of the child components).

Webel IT Australia - upvoter

Answering own questions after further research and trials.

Firstly, thanks to meriton, your response did not exactly answer my question but put me on the right path.

The short answer is that you can use c:if tests to control recursion during the build phase for @ViewScoped since Mojarra 2.1.18. In my case this now works:

        <c:if test="#{not cc.attrs.preventRecursionOnDialog}">

As so often, I was led to this answer (the need to upgrade to Mojarra >= 2.1.18 and explanations about improved handling of JSTL taglibs in @ViewScoped) by the contributions of BalusC to other postings including:

https://java.net/jira/browse/JAVASERVERFACES-1492

JSF2 Viewscope validation issue

http://balusc.blogspot.com.au/2010/06/benefits-and-pitfalls-of-viewscoped.html

JSTL in JSF2 Facelets... makes sense?

What are the main disadvantages of Java Server Faces 2.0?

I consider this matter extremely important for anybody working with JSF ! The ability to control what is built - as opposed to what is rendered - easily in @ViewScoped solves many problems and opens up many possibilities, and I recommend that anybody who is seriously working with JSF takes the time to read the remarks by BalusC in the above links.

BalusC, in case your read this, please know that you are are a true hero of JavaServer Faces and Enterprise Java. On behalf of every JSF enthusiast may I thank you.

And thanks to Ed Burns and Ted Goddard for your excellent work in reporting and fixing this: https://java.net/jira/browse/JAVASERVERFACES-1492 It is a major improvement for JSF2.

Finally, I had to use a dirty trick to get Mojarra 2.1.21 installed on NetBeans7.1+Glassfish3.1.1 (required because of 3rd party incompatibilities) as explained here: JSF how upgrade to Mojarra 2.1.21 in Netbeans7.1 (just sub jsf-api.jar and jsf-impl.jar fails)

This was an excellent result for my project. What would I do without Stackoverflow :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!