JSF call a bean method before the page load [duplicate] - jsf

This question already has answers here:
Invoke JSF managed bean action on page load
(4 answers)
Closed 7 years ago.
I have to call a init method on my bean as first action on the page load, I have tried to simply call #{bean.init} at the very beginning of my page, but I have seen that the <c:if> tests are performed before the init(). I have something like
#{bean.init}
<c:if test="#{bean.conditionsCheck}">...</c:if>
and the conditionsCheck() method is called before the init(),
how can I fix it and call init() as really first thing?

You can use the #PostConstruct annotation to automatically invoke your init method:
#PostConstruct
public void init() {
// do something
}
This method is automatically invoked after construction of the bean.
Your solution looks more like a f:event with type="preRenderView" but this can't be used because the c:if tags are evaluated during view build time, while the f:event (respectively your solution) runs right before the view is rendered during render response phase. Have a look at this question and this question to get details.
Update: As you commented you are using a #SessionScoped bean where #PostConstruct is only called once per session and not on every page load. In this case another solution would be to call your init method as first statement in your conditionsCheck method (nearly the same as your suggestion with fake c:if boolean init). You could also use a custom PhaseListener but I guess that would be somewhat overdosed for this problem.
See also:
Why use #PostConstruct?

This works if you add a JSF Control like CommandButton, and in its value you write it as:
value="#{sessionScopedBean.method()}"
This method will be called whenever this page loads.

for anyone searching ...
We can use preRender of scriptCollector tag, if the used JSF implementation supports it, something like:
<scriptCollector id="scriptCollector1" preRender="#{bean.method}">
...
</scriptCollector>

Related

Executing two action listeners one after another in JSF

In a jsff file in my ADF project I have a button for searching some information which is displayed on the page.
<af:button actionListener="#{bindings.ExecuteWithParams.execute}"
text="SEARCH"
id="button"/>
After that I have a button for editing the displayed information.
<af:commandMenuItem text="edit"
actionListener="#{viewScope.bean.editPopup}"
id="editBtn" immediate="true">
The main idea here is when actionListener="#{viewScope.bean.editPopup}" is executed then actionListener="#{bindings.ExecuteWithParams.execute}" is executed after it, automatically.
Do you have any ideas how it can be achieved? Thank you!
In this case you can programmatically call executeWithParams in your ActionListener (editPopup)
Just add operation in your pageDef and call using OperationBinding
BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding method = bindings.getOperationBinding("methodAction");
Object result = method.execute();
You can capture the single button click in a backing bean and call both methods from there. This blog should help. Also this.
For the viewScope bean, there are helper Static classes that you can use to get a reference to the bean into your backing bean and then call the viewScope bean method there. Look at JSFUtils.java. This blog is older, but might help as well.

JSF templating and controller invocation

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.

ActionListener is called multiple times (Bug?) - Mojarra 2.1.3

I have the following button:
<h:commandButton
disabled="#{mybean.searching}"
binding="#{mybean.searchButton}"
actionListener="#{mybean.searchForLicenses}"
value="Search" />
When I debug I see that the actionListener is called twice first, then three times, next click four times and so on.
It seems like on every reload the actionListener is registered one more time.
I'm using Mojarra 2.1.3 (also tried 2.0.6) and Tomcat 7 with IceFaces.
The binding is done that way:
private javax.faces.component.UICommand searchButton;
public void setSearchButton(UICommand searchButton) {
this.searchButton = searchButton;
}
public UICommand getSearchButton() {
return searchButton;
}
That can happen if you've bound the component to a session or application scoped bean instead of a request scoped bean. This is simply a bad design. The very same component would be reused among multiple requests/views. You need to put the bean in the request scope, or to get rid of the component binding altogether.
Note that binding the component directly to a bean is often a sign of poor design somewhere in the code. What is it, the functional requirement and/or problem for which you thought that this is the solution? If you elaborate on that, we may be able to propose the right approach.
Also note that using an action listener alone is also a design smell. I'd expect "searchForLicenses" to be a normal action method. See also Differences between action and actionListener.
The similar issue takes place when component is using binding and validator or valueChangListener and backing bean is of View, Session or Application scope. Then corresponding listeners are called many times but not once during request (+1 time with every new request).
One possible solution is to override jsf class AttachedObjectListHolder which is used for storing component listeners. Current implementation simply add new listener to component even though the same listener is already there. So the proposed fix is to check that listener does not exist before adding it.
Details of the fix you can see here

JSF CDI Bean initialization on every page access

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

How to call an action method of a UICommand Component which was rendered conditionally?

action method is not called Please refer to this question - , One of my UICommand Component is rendered conditionally , it was said in the answer of the linked question - point 5 - that if the Component's or any of its parents rendered or disabled attributes are false - then the action method will not be called ? If thats the case- How do i achieve the same functionality? Is there a work around ? or a trick ? or any other approach ?
Thanks!
To the point, you'd like to retain the property responsible for the rendered condition in the subsequent request. There are several solutions for this problem:
Put bean in session scope. It's easy, but it hurts. It's bad for user experience since changes will be reflected in all tabs/windows the user has open in the same session.
Use <h:inputHidden> to transfer the property. In theory easy, but in practice it hurts as well. The value will namely get lost whenever a validation/conversion error has occurred in any of other inputs in the same form. This is an odditity in how JSF handles hidden input elements. A workaround is to use <h:inputHidden binding="#{bean.hidden}"> and do a hidden.getValue() and hidden.setValue() in bean.
If you're using <h:commandLink> instead of <h:commandButton>, then you can use <f:param> to transfer the property. It will be available as request parameter, you can check for it in bean's (post)constructor.
Use Tomahawk's <t:saveState>. The perfect solution as far. This will retain the value (or even a complete bean) in the subsequent request.
If you're already on JSF 2.0, the #ViewScoped would have solved this all. It behaves like the <t:saveState>.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
The trick is to have 'rendered' evaluate to true when it is time to run the action and then change the condition to false in the action method.
Let's say you have a link rendering based on a boolean in your bean called 'editing'. Then your action would look something like this:
public String myAction() {
// whatever you want your action to do
editing = false;
}
Edit: this assumes that the bean is either session scoped or the boolean get propagated between requests.
In my case, Javascript came for rescue, Which means, whatever was to be displayed conditionally , put them in a HTML Portion and don't display them display: none until the desired event occurs.
HTML Portion can have any JSF Tags(including CommandButtons) as you wish and would work (invoking the action methods and the stuff )perfectly okay.

Resources