I'm new to JSF, I've read some of the specs but there are still many things I don't understand.
I have joined a project with JSF1.2 + Richfaces 3.3 + some EL that allows to call methods with parameters.
I have created a template xhtml that is meant to be reusable, and I have a bean that holds all the data the template needs to build and render itself. The bean is referenced in the controller.
The template take 2 parameters, the controller and a string value feature that is used to produce the bean that holds the data. I do something very ugly to invoke the method that will produce the bean on the controller :
<h:outputText value="#{controller.loadFeature(feature)}" />
Then I use the bean that is referenced by the controller to build the view
<ui:include src="#{controller.myLoadedBean.widgetPath}">
I need this bean at the build time because depending on the data, I have to include other nested xhtml templates. But I don't know how to manage this :
If the controller is request-scoped, the loadFeature method is invoked too late, at the RENDER_RESPONSE phase, the view is not built with the loaded data
If the controller is session-scoped, it's even worse, the loadFeature method in invoked at the RENDER_RESPONSE, so the first time I try to load the page I have an error, and the the pages are build with the data of the previous request.
Basically, what I need is to be able to call a method of the controller with a template parameter at the view build time.
I don't know how to achieve this, or if it is possible at all. Maybe there are some other mechanism in JSF I don't know of that allow a controller to be invoked before/when the view is being built.
Any help would be appreciated, thank you
I finally got my template working. I was wrong, JSF and Facelet components should not call a method so they can fill themselves.
The correct MVC way is to call a method of the controller before, the controller will build the view bean and then only redirect to the JSF view.
Related
I am working on a ADF application which has a lot of jspx pages. Each jspx page was built with lot of UI components binding to viewscoped managed bean.
Structure of jspx page is like
<jsp:root>
<f:view>
<af:document>
<af:form>
<af:panelgrouplayout>
<af:paneltabbed>
<af:showdetailitem>
<af:table>
And a few UI components(popups,outputtexts,inputtexts etc) inside panelgrouplayout.
My problem is whenever I made a partial page request most of UI components setter methods are getting invoked in managed bean. It seems entire UI View root is reconstructing for every partial request.
For Eg: value change listener on table - Before calling the exact value change event method most of the UI components setter methods are getting triggered (More than once). Restore view and render response phases are taking more time compared to exact business logic.
I already checked from few questions in stackoverflow that binding of components has to be avoided or at least should not bind to any scope more than request/backingbean. For that I have to do lot of refactoring. How can I improve the performance of partial page request?
When a JSF form field is wired into an entity bean field (which is mapped to a DB field), each setter in the entity bean is called regardless of whether the user changed the form field value in the front end, i.e. the setters on unchanged fields are invoked the same as those that have changed but their new value is the same as the old value.
My question is simple: Is there a way to configure JSF to only call the setters mapped to the fields that have changed in the front end? The reason for this is that I have a requirement by which I have to detect deltas on every persist and log them, more about which can be read in this question.
Maybe I didn't understand you clearly, but why are you mapping directly your entity beans to a JSF view ?! IMHO it would be better if you add managed beans between your JSF pages and the entities in order to better separate your business logic from data access.
Any way, I think the easiest solution to impelement for that case is by making use of Value Change Events which are invoked "normally" after the Process Validations phase (unless you make use of the immediate attribute).
The good news about Value Change Events (regarding your example) is they are invoked ONLY after you force form submit using JavaScript or Command components AND the new value is different from the old value.
So, as an example on how to use value change listeners, you can add valueChangeListner attribute to each of your JSF tags like following:
<h:inputText id="input" value="#{someBean.someValue}"
valueChangeListener="#{someBean.valueChanged} />
Then, implement your valueChanged() method to look something like:
public void valueChanged(ValueChangeEvent event) {
// You can use event.getOldValue() and event.getNewValue() to get the old or the new value
}
Using the above implementation, may help you to separate your logging code (it will be included in the listeners) from your managed properties setters.
NB: Value Change Listeners may also be implemetend otherwise using the f:valueChangeListener Tag, but this is not the best choice for your example (you can find some examples in the section below, just in case)
See also:
Valuechangelistener Doubt in JSF
JSF 2 valueChangeListener example
When to use valueChangeListener or f:ajax listener?
Having gone through these excellent posts:
Why JSF saves the state of UI components on server?
Why does JSF save component tree state?
and midway the JavaEE6 tutorial I still have the following questions:
When I am developing a custom UI component whose values (styleClass, value, etc) are either defined statically(in the xhtml) or set via a bean, do I need to explicitly save/restore state in the extended component as well?
Is it correct to say that the scope of the UI components is view scoped?
How is the view identified behaviour? (If I navigate away from a view, the view gets rebuild the next time around. But if I open another tab, it is restored - at least the bean!)
When I am executing an Ajax call, I would expect that 'execute' part of the UI component would be restored&processed and the 'rendered' part would be restored&updated. After running into some problems with UI:repeat, it is not clear to which extend the component tree is to be restored and if is possible to partially edit.
As an example (I am not sure that it works like this): I define a UI:repeat that iterates over some values and creates some Ajax commandlinks. Whenever I call the command, it will restore the whole ui:repeat regardless of the Ajax scope (execute/render) that I have defined. So it will re-render the whole ui:repeat. Furthermore, I don't understand how it could ever -not- restore the ui:repeat as due to being a namingcontainer it will edit the id of my newly added component.
How can I define a build-time component (vs render-time) and why would I want to do this? (It seems that build time components are troublesome when mixed with rendertime, so why have both)
Thanks
When I am developing a custom UI component whose values (styleClass, value, etc) are either defined statically(in the xhtml) or set via a bean, do I need to explicitly save/restore state in the extended component as well?
Yes. You normally use StateHelper for this.
See also:
How to save state when extending UIComponentBase
JSF custom component: support for arguments of custom types, the attribute setter is never invoked
Adding Custom Attributes to Primefaces Autocomplete Component in JSF
Is it correct to say that the scope of the UI components is view scoped?
Absolutely not. UI component instances are request scoped. Only anything which is stored via StateHelper is in essence view scoped (and restored into newly created component instances during "restore view" phase).
See also:
JSF composite component - weird behavior when trying to save state
Backing bean in composite component is recreated on every request
How is the view identified behaviour? (If I navigate away from a view, the view gets rebuild the next time around. But if I open another tab, it is restored - at least the bean!)
It's likely requested from browser cache. Try submitting a form therein. The chance is big that you get a ViewExpiredException. You need to tell the browser to not cache dynamic pages. Putting a breakpoint on bean's constructor would also confirm that it's never been invoked.
See also:
Avoid back button on JSF web application
Is JSF 2.0 View Scope back-button safe?
javax.faces.application.ViewExpiredException: View could not be restored
When I am executing an Ajax call, I would expect that 'execute' part of the UI component would be restored&processed and the 'rendered' part would be restored&updated.
This is not true as to restore part. The "whole" view state is restored. Note that the view state does since JSF 2.0 not necessarily represent the entire component tree. You've found the explanation/answer to that already in the two links mentioned in your question.
How can I define a build-time component (vs render-time) and why would I want to do this? (It seems that build time components are troublesome when mixed with rendertime, so why have both)
This is called a "tag handler". I.e. just extend from TagHandler instead of UIComponent and implement according its contract. Tag handlers are useful if the sole goal is to build the view (the JSF component tree). They do not appear in the JSF component tree. As to when to create a custom component or a custom tag handler, check the "components" and "taghandlers" sections of OmniFaces showcase, it may give some new insights as to real world use cases of those things.
See also:
Custom Facelet component in JSF
JSTL in JSF2 Facelets... makes sense?
Does anyone have a solution for such a problem:
In my app I'm using a complex, programmatically build dashboard based on the primefaces dashboard. To overcome problems with nonunique id's of the panels building the dashboard, I'm binding this component to a request-scoped bean. I'd also like to rebuild the dashboard based on some changable parameters after clicking a commandButton.
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired (in the Invoke Application phase). So, although the dashboard is rebuild eventually, it's not beeing refreshed in the rendered response.
On the other hand, if I try to set immediate attribute of the button to true, the actionListener is fired in the Apply Request Values phase, but still after the getter. Than the lifecycle goes directly to the Render Response phase, and the outcome is the same.
Anyone?
Thank you for the answer. Let me add a bit detail to my problem.
I store a model of a sports tournament as a property of a session scoped bean. It goes like this: the bean has a property "tournament". This class has a list of groups, each with it's table of matches. The idea was to use three different programmatically built components as renderers of this tournament model.
The dashboard would be used for drag-and-drop edition of contestant placement in groups. For viewing match tables and editing their matches I use a tab panel, with panel grid for every table. Finally, I use a panel grid to show a tournament tree. Every of those three components render some part of the model for the user to edit.
Since the model (and therefore those rendering components) are dynamically build depanding on chosable parameters like number of groups for example, i had a problem with id uniqnes when binding them to a session-scoped bean. So I bound them to a request scoped bean. With every request changing the model (mostly ajax) I wanted to rerender those components depending on the parameters set by the user (also stored in the session scoped bean).
The problem is, that when I rebuild the model in the invoke application phase (in a action listener fired by the "rebuild-my-model" button), the components bound to a request-scoped bean have already been "get-ed" from the bean (or so it seems), and they do not refresh on the page.
I would be very gratefull for a clue to what i'm doing wrong, and perhaps a suggestion, if the approach mentioned above is completelly stupid :)
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired
I'm not sure why exactly that forms a problem for you. Perhaps you're incorrectly doing business logic in the getter method instead of in the action listener method? Or perhaps you're manually creating the component instead of referencing the JSF-created one and thus always overridding the one in the JSF view?
A proper JSF getter method basically look like this:
public UIComponent getDashboard() {
return dashboard;
}
It should not contain any other line of code. The same applies to the setter method by the way. Any actions wherein you need to manipulate the component's children needs to be done in an action(listener) method, not in a getter/setter method.
I'm currently learning about JSF 2.0 and i dont know how to initialize something in my CDI bean everytime a jsf page is accessed ?
For example, let's say in my case, i have one CDI bean that is used in one JSF page. Somewhere inside the bean, i would like to query and initialize something, or check authorization everytime the page is accessed (not everytime the action method is called).
I could put it into the bean's constructor, but that doesnt guarantee that the constructor would be called for every calls of the jsf page ? Or should i call using the #{myBean.initialize()} on the JSF page ?
Regards,
Albert Kam
If you declare the managed bean #RequestScoped, then it will be created for every HTTP request (yes, that's "everytime a JSF page is accessed" as you say in enduser's terms). You can just do the initialization job in the bean's constructor or #PostConstruct method. This has nothing to do with CDI.
check authorization everytime the page is accessed (not everytime the action method is called).
For that, a javax.servlet.Filter or very maybe a javax.faces.event.PhaseListener is a much better solution.
You could have a look at https://cwiki.apache.org/confluence/display/EXTCDI/JSF+Usage
If I am not mistaken, the constructor is called every time the page loads - as soon as you apply your bean to the jsf page, that object is constructed. Hence, must have a constructor without any parameters