Only First JSF Controller is Created. Others Are Ignored - jsf

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.

Related

Null when session scoped managed bean taken from session

Here is the managed bean declaration:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "user")
#SessionScoped
public class UserConsoleAction extends UserAction implements Serializable {
And the following code from servlet returns null:
UserConsoleAction uca = (UserConsoleAction) req.getSession().getAttribute("user");
This is an old code written on JSF 1 and now JSF 2.2 is using.
This was working fine & able to get session scoped managed bean from session when managed bean was declared in faces-config.xml.
<managed-bean>
<description>Used for user console functions</description>
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>com.web.admin.UserConsoleAction</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
But when I removed this faces-config.xml entry & used ManagedBean annotation, the code to get managed bean instance from session returns null.
What may be the cause for this change since it is only the declaration part changed from xml to annotation.
ManagedBean annotation worked fine when extends UserAction is removed. UserAction is a request scoped bean & UserConsoleAction is session scoped.

JSF init not called on page refresh

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

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

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