JSF init not called on page refresh - jsf

I have jsf session scoped bean. Its init method having annotation #PostConstruct is called when the page is loaded for the first time but not on every reload or refresh. I want to call some method on every page refresh. What annotation or change in xhtml file do I need to use

Try change your annotation tag as follows
Just change it to ViewScope. import javax.annotation.PostConstruct;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class YourControllerClass implements Serializable {
#PostConstruct
public void init(){
}
}

If you want to call a method on every page refresh it 's better to use ComponentSystemEvent.
You can refer below link
https://www.tutorialspoint.com/jsf/jsf_applicationevents_tag.htm

Related

Only First JSF Controller is Created. Others Are Ignored

My first time trying Java and this error is rather strange and I seem to be the only one having the problem on this planet.
I have two web pages:
<h:link outcome="index">Home</h:link>
<h:link outcome="about">About</h:link>
I have two controllers, shown below in the order I created them in package Controller:
HomeController.java
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class HomeController implements Serializable{
public HomeController() {
System.out.println("Home Controller Created......");
}
}
AboutController.java:
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class AboutController implements Serializable{
public AboutController() {
System.out.println("About Controller Created......");
}
}
If I visit home.xhtml, I see Home Controller Created...... but I don't see any message on about.xhtml. The Controller doesn't get called even when I Debug with NetBeans.
Your package declaration is wrong.
Firstly:
Use javax.faces package when playing with JSF, thus your #SessionScope package is wrong.
Secondly:
You need to use #ManagedBean instead of #Named. JSF automatically creates SessionScope bean for you with first reference to it. Don't put anything in constructor because JSF can create the bean when it wants and if the construction fails (Nullpointer etc.) then you have problem. JSF style is to use #PostConstruct annotation to initialise data after construction.
If in your xhtml you have for example <h:outputText value="#{aboutcontroller.someValue}then the AboutBean is created once/session.
(You can also use #ManagedBean(name="aboutController") and reference to it in xhtml with #{aboutController.someValue}
Btw: JSF is all about controllers, usually controllers are in #RequestScope. You can divide your session in those 2 #SessionScope beans, but in the end you only have 1 session. Consider removing the other SessionScope bean, and using #RequestScope beans to manipulate the data in #SessionScope bean. Another good option is to use #ViewScope bean if you are validating some fields and showing error messages with incorrect field values.

Inject CDI bean into JSF #ViewScoped bean

I have a problem with JSF, CDI project. I did a lot of research and I found that in CDI there is no #ViewedScoped annotation. I solving problem with ajax based page with dialog. I want to pass variable to dialog from datatable. For this purpose, I can't use #RequestedScoped bean because value is discard after end of request. Can anyone help me to solve it? I can't use #SessionScoped but it's a bad practice IMHO. Or maybe save only this one variable into session who knows. Can you guys give me any hints how to solve this problem elegantly?
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class ServiceBean implements Serializable {
...
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class SomeBean {
#Inject
ServiceBean serviceBean;
#Postconstruct ...
Here is the error message:
com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean warDetailBean
First, If you are attempting to use CDI, you need to activate it by putting a WEB-INF/beans.xml file in your application (note that this file can be empty), more informations about that file could be found in the Weld - JSR-299 Reference Implementation.
As you are using Tomcat, please be sure to respect all the configuration requirements by following the steps in How to install CDI in Tomcat?
Second, Even if you can use #Inject inside a JSF managed bean, It's preferable that you don't mix JSF managed beans and CDI, please see BalusC's detailed answer regarding Viewscoped JSF and CDI bean.
So if you want to work only with CDI #Named beans, you can use OmniFaces own CDI compatible #ViewScoped:
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
#Named
#ViewScoped
public class SomeBean implements Serializable {
#Inject
ServiceBean serviceBean;
}
Or, if you want to work only with JSF managed beans, you can use #ManagedProperty to inject properties:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class SomeBean{
#ManagedProperty(value = "#{serviceBean}")
ServiceBean serviceBean;
}
See also:
ManagedProperty in CDI #Named bean returns null
Omnifaces CDI ViewScoped

Cannot find CDI beans

I created this simple CDI bean:
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
#Named("DashboardController")
#ViewScoped
public class Dashboard implements Serializable
{
.......
}
I removed all configuration from faces-config.xml. I created this beans.xml file into WEB-INF directory:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
When I opened the JSF page the bean cannot be found. Can you tell me what am I missing? I don't want to declare the beans into faces-config.xml.
P.S I don't know if this is important or not but this is a WAB package with CDI beans.
You'll need to use ViewAccessScoped instead of ViewScoped.
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ViewAccessScoped;
//Note the different import
import javax.faces.context.FacesContext;
import javax.inject.Named;
#Named("dashboardController")
#ViewAccessScoped
public class Dashboard implements Serializable
{
.......
}
You should also start the name in Named with a non-capital letter.
You might need to add the faces_config file to your META-INF folder of your WAB as described in this thread
That aside, even if the bean is found, you might still have problems with the scoping; You can't apply a JSF scope to a CDI bean.
CDI's #ConversationScoped is a somewhat less than convenient alternative to JSF's #ViewScoped. The inconvenience of the scope lies in the fact that you need to inject an extra managed object and you have to actively manage the scope yourself. To use:
Annotate your bean with #ConversationScoped
#Named("DashboardController")
#ConversationScoped
public class Dashboard implements Serializable
{
}
Inject the Conversation object into your bean
#Inject
private Conversation conversation;
On this object, you need to call begin() and end() to start the "conversation" (a la viewscope) and "end" the conversation (like JSF does by destroying a viewscoped bean) respectively. This is a matter of design and context. At the very least, you can call conversation.begin() in a #PostConstructor. Where you end the conversation depends on your specific use case

Injecting one view scoped bean in another view scoped bean causes it to be recreated

I need to use some data saved in a view scoped bean in an other view scoped bean.
#ManagedBean
#ViewScoped
public class Attivita implements Serializable {
//
}
and
#ManagedBean
#ViewScoped
public class Nota implements Serializable {
#ManagedProperty("#{attivita}")
private Attivita attivita;
// Getter and setter.
}
Now, maybe my theory about it is still quite poor, I have noticed that when #{attivita} is injected, the Attivita constructor is invoked and thus creating another instance. Is it the right behaviour? What about if I want to reference the same instance and not create a new one?
This will happen if you're navigating from one to the other view on a postback. A view scoped bean is not tied to a request, but to a view. So when you navigate to a new view, it will get a brand new instance of the view scoped bean. It won't reuse the same bean instance which is associated with a previous view.
I understand that the attivita bean is created on the initial view and reused on postback. I understand that nota bean is associated with the new view where you're navigating to. When injecting attivita in it, it will simply get a new and distinct instance even though there's another instance in the very same request. This is all expected (and admittedly a bit unintuitive) behaviour.
There is no standard JSF solution for this. CDI solves this with #ConversationScoped (the bean lives as long as you explicitly tell it to live) and the CDI extension MyFaces CODI goes a bit further with #ViewAccessScoped (the bean lives as long as the navigated view references it).
You could however workaround this by storing the bean as an attribute in the request scope.
#ManagedBean
#ViewScoped
public class Attivita implements Serializable {
public String submit() {
FacesContext.getCurrentInstance().getExternalContext()
.getRequestMap().put("attivita", this);
return "nota";
}
}
and
#ManagedBean
#ViewScoped
public class Nota implements Serializable {
private Attivita attivita;
#PostConstruct
public void init() {
attivita = (Attivita) FacesContext.getCurrentInstance().getExternalContext()
.getRequestMap().get("attivita");
}
}
Note that this is rather hacky. There may be better solutions depending on the concrete functional requirement. Also note that you should in the nota view reference the desired Attivita bean instance as #{nota.attivita} and not as #{attivita}, because it would give you a new and different instance, for the reasons already explained before.
Your attivita bean is #ViewScoped and that doesn't guarantee that your instance will be hold in session. You need a #SessionScoped bean. However, if you need attivita for some reason to be #ViewScoped, then you can pass params through them in other ways, e.g. using viewParam or using other #SessionScoped bean between them.
Page Params
http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/
JSF 2 Managed Bean Scopes
http://balusc.blogspot.com.es/2011/09/communication-in-jsf-20.html#ManagedBeanScopes

Inject Bean that uses #Named with value

how can I Inject a Bean, that uses a #Named annotation along with a value?
#Named
public class LanguageService{
...
}
public class SomeOtherBean{
#Inject
private LanguageService languageService
}
works without Problem - but how to inject, if i'm using:
#Named("lang")
public class LanguageService{
...
}
#Inject can't have a value as #ManagedProperty does. (But I wan't to stay with CDI)
Edit:
I noticed that it doesn't matter how the bean is named. My Fault that leads to an NPE was simple that i created SomeOtherBean manually, and ofc. no Injection was done. My fault.
CDI selects injectable beans by type (and qualifiers) and not by the annotation parameter. The name is used to address a CDI bean from views, e.g. facelets.

Resources