JSF CDI Bean initialization on every page access - jsf

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

Related

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 passing view parameters by reference - when object must be instantiated

Let's say I've got a register page & a register confirm page. I enter user
details into the register page, navigate to the register confirm page where
I can return back to the register page if there are any mistakes.
I'm going to use view parameters to make the registration data available
from the register page to the confirm page, and vice versa.
Supposing there are 20 items of data to be moving from page to page, that's
a lot of view parameters and a lot of setPropertyActionListeners, especially
as all the data is going to end up nicely packaged in a User object.
So what I want to do is input the data on the register page into the
properties of a User record and send a reference to it to the register
confirm page. What gave me an idea was seeing the BalusC WeakHashMap
converter. This is a JSF converter which has a static weak hash map and
generates a uuid as the value for a map entry and the object reference as
the key. So by specifying this as a converter for f:viewParam you send
the uuid in the query string.
This works fine. The issue I have is that on the register page I have to
get an instance of a User class with new. Then I can do:
<h:inputText value="#{bean.user.firstname}"/>
(etc...), and pass the user instance as a view parameter. It works fine from
the register to the confirm page. The issue is that when I perform the
reverse, sending the user reference back to the register page from the
confirm page I absolutely cannot prevent the register page backing bean
from re-instantiating the user object, after the setter has been called
as a result of the view parameter.
So the converter does it's job and retrieves the User object from the
hash map, calls setUser() in the backing bean, and then I see the
constructor for the User class firing.
I've tried calling new User() from the bean constructor, in #PostConstruct,
in a preRenderView (also checking if an ajax request), but nothing I try
prevents the work of the view parameter from getting wiped out if new is
involved. I'm sure there's a simple solution but I just can't see it right
now.
I'd be grateful for any suggestions for how to solve this problem.
The issue I have is that on the register page I have to get an instance of a User class with new.
So what code is initially creating this new User instance then? If you do this in the preRenderView handler, then you can simply check for null, can't you?
If the view parameter and converter haven't done their job, user would still be null and you create a new instance. The bean constructor and #PostConstruct won't do you any good here, since they both run before the view parameter does its thing, but the preRenderView event is guaranteed to run after it.
#ManagedBean
public class Bean {
private User user;
public void onPreRenderView() {
if (user == null) {
user = new User();
}
}
}
(Something to additionally consider is that the conversation scope already does exactly what you're trying to do here. This is part of CDI not JSF, but if you're running in a Java EE 6 Web Profile compliant AS (JBoss AS 6 or 7, Glassfish V3, Resin 4, ...) you already have it. Otherwise it's just an extra jar.)
After several attempts over more than a year to find a solid long term solution
to this problem, at last! I've found one. The solution comes in the form of the
Apache Myfaces CDI extensions project, aka Myfaces CODI.
This provides additional scopes such as the #ViewAccessScoped which ensures that
if a bean is referenced by a page then it is available for that page. Also
provided is support for conversation groups. In the scenario where I want to
pass an object reference from a register page to a register confirm page, the
confirm page can just access the registerView bean directly on the next request.
Alternatively you can #Inject one bean into another and access it on the next
request, or use f:setPropertyActionListener from the source page.
Myfaces CODI works fine with Mojarra and also with ajaxified component libraries
such as primefaces. The concept is similar to what is provided by Jboss Seam,
though I've found the additional scope support to be better thought out and I've
tested this on glassfish 3.1.1 with no problems.
If you're using #ManagedBean and scope annotations from the javax.faces.bean
package in your code, codi intercepts these annotations and uses it's own
CDI based versions, so you can convert to CDI simply by adding codi as a
dependency to your project and not changing any code.
For me this is like moving from black and white TV to colour TV, I wish I'd
found this stuff sooner.
CODI documentation

Bean value update problem in jsf 1.1

I have One Jsf form that contains 2 Beans. First Bean scope: Session. Second Bean scope: request.
When some values are added via First Bean to second Bean, the updated value is not displayed in the form. I don't know how to do. Please help me.
Either you fired a redirect which caused the request scoped bean being renewed, or the values are updated at the wrong moment which caused them being overridden later in the JSF lifecycle.
To fix the first, ensure that you aren't including <redirect/> in navigation case nor did call ExternalContext#redirect() in bean action method. To fix the second, well, run a debugger. This article may also help a lot in understanding what's going on under the JSF hoods.
BalusC has shown what are the possible reasons for this problem.
In case it is the redirection one, removing the redirect solves the problem, but adds another - the user is asked to resubmit the form if he refreshes the page.
A preferred way to achieve such transitions from one page to another is to use a conversation. MyFaces Orchestra provides a special conversation scope to solve this and many more problems.

Between a jsf page and a managed bean, why the getter method is called twice

I have a jsf page with a form has an outputtext in it. The value of outputtext component is called from a backing bean (or managed bean). I know when I code it as #{MyBean.myString}
Jsf rename it and calls getMyString() method. However the wierd thing is, when I put a breakpoint to the getter method of this component, I see it is called twice during the page is being rendered.
The outputtext is in a h:form, and it is the only component wich is bind to a backingbean. I mean, it is so wierd that jsf should get the value when it first come to the getter method, however it needs to go to the getter method twice.
Can you explain what is the reason of this behaviour in jsf?
Any help would be appreciated,
Best wishes,
Baris
The getter, as its name already self-describes, is just there with the pure purpose to retrieve the data. JSF doesn't cache this data. It will call it whenever needed. The cost of calling a getter is in practice nihil --unless you do something more than returning the data, e.g. hitting the DB everytime, this logic should then be moved out of the getter or be turned into lazy loading.
In case of a form submit, the first get call is usually fired during validations phase to check if there is any initial value so that JSF can handle the value change event. The second call is usually fired during render response phase to display the model value in the view.
You may find this article useful as well to learn more about the JSF lifecycle. You may find this answer useful to learn more about ways to do preprocessing/initialization in a backing bean.

Resources