JSF render phase (why is my code being executed?) - jsf

I'm currently investigating the performance of a JSF application. I have noticed that code is being executed even though rendered is set to false. For example, take this piece of code:
<h:panelGroup rendered="#{bean.render}">
<my composite component here/>
</h:panelGroup>
Even though #{bean.render} returns false, I can clearly see from debug logs, that the code for my composite component is being executed during the render phase. It also looks like the code is being executed before #{bean.render} is even called. It isn't rendered in the HTML returned to the client, but it still appears that the server is executing the code.
Can anyone explain this?
Thanks.

Composite components are built during render response phase. JSF needs to populate the component tree first and then generate HTML based on the component tree. You're inside the composite component apparently referencing some bean properties which are mandatory to be evaluated during view build time.
If you'd like to conditionally control the building of the composite component instead of the rendering, then you need to use a conditional view build time tag instead of the rendered attribute. JSTL offers the <c:if> and <c:choose> for that.
<c:if test="#{bean.build}">
<my:composite />
</c:if>
See also:
JSTL in JSF2 Facelets... makes sense?

Jsf have to know if your components are rendered or disabled or whatever. Let say you say disabled="false" it is shown on clint side and client may change value and submit the form, even though javascript is disabled by the client, jsf checks it's disabled false or true on server side. if it was true it is not acceptable and never comes to your bean because of process validation phase of jsf, same as rendered="false"

Related

primefaces update attribute not working on modal dialog opened from modal dialog [duplicate]

I have a question about the idea behind the fact, that only UIForm got the attribute prependId. Why is the attribute not specified in the NamingContainer interface? You will now probably say that's because of backward compability but I would preferre breaking the compability and let users which implement that interface, also implement methods for the prependId thing.
The main problem from my perspective about the prependId in the UIForm component is, that it will break findComponent()
I would expect that if I use prependId, then the NamingContainer behaviour would change, not only related to rendering but also when wanting to search for components in the component tree.
Here a simple example:
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
Now when i want to get the panelGroup component I would expect to pass the string "group" to the method findComponent(), but it won't find anything, I have to use "test:group" instead.
The concrete problem with that is, when using ajax with prependId="false". The ajax tag expects in the attributes update and process, that the values care of naming containers. It's a bit strange that when I use prependId="false" that I have to specify the full id or path, but okay.
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
<h:commandButton value="go">
<f:ajax render="test:group"/>
</h:commandButton>
</h:form>
Well this code will render without problems but it won't update the panelGroup because it cannot find it. The PartialViewContext will contain only the id "group" as element of the renderIds. I don't know if this is expected, probably it is but I don't know the code. Now we come to the point where the method findComponent() can not find the component because the expression passed as parameter is "group" where the method would expect "test:group" to find the component.
One solution is to write your own findComponent() which is the way I chose to deal with this problem. In this method i handle a component which is a NamingContainer and has the property prependId set to false like a normal UIComponent. I will have to do that for every UIComponent which offers a prependId attribute and that is bad. Reflection will help to get around the static definition of types but it's still not a really clean solution.
The other way would be introducing the prependId attribute in the NamingContainer interface and change the behaviour of findComponent() to work like described above.
The last proposed solution would be changing the behaviour of the ajax tag to pass the whole id, but this would only solve the ajax issue and not the programmatic issues behind the findComponent() implementation.
What do you think about that and why the hell is it implemented like that? I can't be the first having this problem, but I wasn't able to find related topics?!
Indeed, UIComponent#findComponent() as done by <f:ajax render> fails when using <h:form prependId="false">. This problem is known and is a "Won't fix": JSF spec issue 573.
In my humble opinion, they should never have added the prependId attribute to the UIForm during the JSF 1.2 ages. It was merely done to keep j_security_check users happy who would like to use a JSF form with JSF input components for that (j_security_check requires exact input field names j_username and j_password which couldn't be modified by configuration). But they didn't exactly realize that during JSF 1.2 another improvement was introduced which enables you to just keep using <form> for that instead of sticking to <h:form>. And then CSS/jQuery purists start abusing prependId="false" to avoid escaping the separator character : in their poorly chosen CSS selectors.
Just don't use prependId="false", ever.
For j_security_check, just use <form> or the new Servlet 3.0 HttpServletRequest#login(). See also Performing user authentication in Java EE / JSF using j_security_check.
For CSS selectors, in case you absolutely need an ID selector (and thus not a more reusable class selector), simply wrap the component of interest in a plain HTML <div> or <span>.
See also:
How to select JSF components using jQuery?
How to use JSF generated HTML element ID with colon ":" in CSS selectors?
By default, JSF generates unusable ids, which are incompatible with css part of web standards

How to change the order of creation/restoring managed beans?

I have a complex problem with order of 'JSF bean life cycle actions'.
I have two beans with different scopes. The first, let's call it, managerBean is session scope bean. The second one, someBean has view scope (someBean really is many different beans). ManagerBean takes some action once per page loading and few others view scope beans are using the results of this action in their constructors.
Everything was working just fine until I've started getting forms IDs in xhtml files from java beans. Now action from managerBean is taken after someBean is created and I'm getting expected result only when the page is reloaded (on refresh, so someBean is using the first results of ManagerBean work).
This is how it looks like now:
<!-- mainTemplate is a main templete of the page which is rendered once
per page view (every other actions are taken via ajax). This is a place
of ManagerBean work after re rendering the page -->
<ui:composition template="/mainTemplate.xhtml">
<ui:define name="mainContent">
<h:form id="#{someBean.formID}">
some inputs
</h:form>
(...)
</ui:define>
</ui:composition>
So when form id was constant String everything worked like I want and now it doesn't. It looks like JSF must calculate ID first and take any other after this (including ManagerBean action).
My question is: Is there a way to change this situation?
If something isn't clear enought, please ask. I was trying to simplify the problem because it has many factors. Maybe all my thinking is wrong (the way I want to take some action per page and some actions after it).
Any help will be good!
The id (and binding) attribute of a JSF UI component is evaluated during view build time. The view build time is that moment when the XHTML source code is turned into a JSF UI component tree. All other attributes of a JSF UI component like value and all events like preRenderView are evaluated/executed after the view build time, usually during view render time (when the JSF UI component tree needs to produce HTML output). This is not something which you can change by just turning a setting or so. It's just the way how JSF works. You can't render something which isn't built yet. You can only change this by writing code the right way.
I can't think of any real world scenario why you need to make the ID attribute dynamic like this. If it were inside a <c:forEach>, or part of dynamic component generation, then okay, but this seems just to be a static form. So I would in first place recommend to forget it and just hardcode the ID in the view and rely on other variables (perhaps a hidden input field? depends all on concrete functional requirement which isn't mentioned anywhere in the question nor guessable based on the code posted so far).
If you really need to make it dynamic, then you need to split the formID property off from the view scoped bean and move it to a different and independent bean, perhaps an application scoped one.
See also:
JSTL in JSF2 Facelets... makes sense? - component's id attribute has same lifecycle as JSTL tags

Render a jsf element on mouseover

I have a <h:panelGrid> and a h:commandLink(link is basically a image).Now I want that on mouseover event , Then link should be render(render='true') and on mouseout event, it gets removed render='false'.But I am unable to create the logic that How can I do this with these events as the approach I am using is To set the values of bean true and false on this event.
Here is my code
<h:form>
<h:panelGrid mouseover='** we cannot call a bean method here which changes the bean value **'>
This is the Div On which I want to apply mouseover event
</h:panelGrid>
<h:commandLink id="btn" render={renderBean.renderLink}>
<h:graphicImage url="image.jpg"/>
</h:commandLink>
</h:form>
The default value of renderLink attribute of renderBean is false. Now I want to know the way that How can I change its value to true on mouseover event? Is it possible? OR Anyother solution in JSF w.r.t this requirement
You have to remember in JSF that the page will first be processed server-side by the JSF engine in the web server. At that time all JSF tags will be converted into their HTML equivalent. The render attribute tells the server-side engine whether or not to output an HTML a (anchor) link in the place of the <h:commandLink> element.
The behavior you're looking for, namely responding to mouse events, is client-side functionality. It happens in the browser, not at the web server, so no JSF is involved. The solution is to handle the mouse events in JavaScript, not JSF. You will typically set (or remove) the CSS attribute display:none on the id called btn (unfortunately it's slightly more complex as JSF will mangle the element id a bit). There are lots of posts here on StackOverflow that deal with how to handle client-side events in JavaScript. Using jQuery for example is a really common approach.
I recommend to get started you take a look at the blog of one of our best JSF resources and long-time StackOverflow user BalusC: http://balusc.blogspot.com.
There's a lot to learn and you'll get a good start by going there first (and searching for his posts on SO).
Good luck.

How to set value in bean using use c:set with jsf?

I have another problem to solve. I have a code on my xhtml page:
<t:dataList id="myDataList" value="#{myBean.myList}" var="element" first="0" `rows="10" dir="LTR" frame="hsides" rules="all">`
<c:set target="#{myBean}" property="fid" value="#{element[0]}"/>
...
</t:dataList>
The problem is that value of 'fid' in a bean is null when I`m checking it. When I wrote:
<c:set target="#{myBean}" property="fid" value="8"/>
everything works fine and value is set to '8'. How should i fix this? Thanks for replies.
JSTL tags runs during view build time. JSF tags runs during view render time. You can visualize it as follows: JSTL runs from top to bottom first when the JSF component tree is to be populated, then hands over the component tree to JSF and finally JSF runs from top to bottom to render the HTML.
The element[0] is not there when JSTL is creating the view. It's only there when JSF is rendering the HTML. However, 8 is hardcoded and it is always there.
There are several ways to achieve it the proper way, but since the functional requirement is unclear, I can't suggest a proper approach. Maybe you need f:setPropetyActionListener. Maybe you need DataModel#getRowData() or UIData#getRowData(). Or maybe you don't need it at all.

JSF2 ignores Action attribut [duplicate]

This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 2 years ago.
my xhtml code:
<h:commandLink action="#{detailController.updateProject}" class="positive" >
<h:graphicImage library="img" name="tick.png" alt=""/>
<h:outputText value="Save" />
</h:commandLink>
This action (updateProject()) is not being called from JSF framework! Even if I delete it in the managedBean there is no exception thrown.
Does anybodyelse has had problems like that? I can't even explain that -.- I mean this action ethod is there!
ADD: Yes it is in a h:form tag! But I have two forms in that view! May that be the problem?
ADD2: I should also mention that if I hit the button it throws me back to the previous view! So my action method is being ignored and instead it opens another view ?!?!
To provide more information, my page is built like that:
panelGroup name=show rendered=!controller.edit
form
buttons
outputtext
/form
/panelGroup
panelGroup name=edit rendered=controller.edit
form
buttons
inputText
/form
/panelGroup
So I have both, edit and show of one entity at one file! But only the buttons in the bottom form show that strange behaviour (see above).
Answering BalusC:
1. I use two forms (they aren't nested!)
2. In the bottom form I had already placed a h:messages
I'm gonna try putting my controller into viewScop for checking 3 and 4
I don't know how to check 5.
Thank you for that..
This can have a lot of possible causes. #romaintaz has mentioned only the most obvious one (the most common beginner's mistake): UICommand components must be placed inside an UIForm component.
There are however more causes:
You have multiple nested forms. This is illegal in HTML. The behaviour is dependent on the webbrowser used, but usually the button won't do anything. You may not nest forms, but you can use them in parallel.
A validation or conversion error has occurred which is not been catched by a h:message. Normally this is logged to stdout, but you can also use h:messages to get them all.
The UICommand component is been placed inside an UIData component (e.g. h:dataTable) whose value is not been preserved the right way during the subsequent request. If JSF cannot find the associated data row, the action won't be invoked. Putting bean in view scope should help a lot.
The component or one of its parents has a rendered or disabled attribute which evaluated false during apply request values phase. JSF won't invoke the action then. Putting bean in view scope should help a lot.
Some PhaseListener, EventListener, Filter or Servlet in the request-response chain has changed the JSF lifecycle to skip the invoke action phase or altered the request parameters so that JSF can't invoke the action.
Just a quick question: is your <h:commandLink> nested inside a <h:form>?
If this is not the case, you must include your command link inside a form element, otherwise it will not work.
Just for code simplification, you can use the value attribute instead of adding a <h:outputText> component:
<h:commandLink action="#{detailController.updateProject}" class="positive" value="Save">
<h:graphicImage library="img" name="tick.png" alt=""/>
</h:commandLink>
Unfortunately, I don't know where the mistae was. I guess it was about wrong my JSF code.
I solved this problem by simplifying my code. From that xhtml page and that one controller I made 3 xhtml-pages and 3 Controller. After refactoring all that my code looks much easier and it works now :-)
Thank you for your helpful suggestions

Resources