Target Unreachable, 'null' returned null in JSF2 - jsf

I am quite new to JSF and I have this problem. I was reading some posts about that but I could found answer( or I didnt understood one...).
I have following user bean:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="user")
#SessionScoped
public class User implements Serializable {
private String login;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
}
and login bean:
#ManagedBean(name="login")
#SessionScoped
public class Login implements Serializable{
private static final long serialVersionUID = 1L;
#ManagedProperty("#{user}")
private User user;
#PostConstruct
public void init() {
System.out.println("Init called");
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
And my view looks like this:
<h:inputText id="login" value="#{login.user.login}" required="true"/>
<h:commandButton value="Login" action="#{login.user.login}"/><br/>
I want access to user fields in few classess and this how I am trying to achieve this. Unfortunately I keep got this error.
I have found some information that I need beans.xml. Is that true? Where can I find sample? I am using JSF2.
Answer
My fault was that I choose same name for field and for login method. Because of that I was using login.login( before implementing User class) for geting login, and login.login as a action of commandButton. After I implemented User class I changed both login.login to login.user.login.
Thanks again for help.

You are binding a method User#login() to your CommandButton, which does not exist. There is only a property login (get/set).
You need a proper action method in your User bean:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="user")
#SessionScoped
public class User implements Serializable {
private String login;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public void doLogin() {
// whatever you want to do here
}
}
and bind to the doLogin() method:
<h:commandButton value="Login" action="#{login.user.doLogin}"/>
beans.xml is required to enable CDI, which you don't use here. You are using jsf managed beans. CDI is a more powerful alternative.

Related

how to access one managedbean from another in jsf

I have two managedbean class(UserBean.java & HelloBean.java) and one index.xhthl class. In HelloBean.java class, I have used #ManagedProperty anotation for accessing the property of UserBean.java and I have a method within HelloBean.java class.
here, my classes:
UserBean.java
package com.bean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="ubean", eager=true)
#SessionScoped
public class UserBean {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
HelloBean.java
package com.bean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
#ManagedBean(name="hellobean", eager=true)
#RequestScoped
public class HelloBean {
#ManagedProperty(value="#{ubean}")
private UserBean mbean;
private String username;
public String getUsername() {
if(mbean!=null){
username=mbean.getUsername();
}
return username;
}
public void setMbean(UserBean mbean) {
this.mbean = mbean;
}
public UserBean getMbean() {
return mbean;
}
public void showMsg(){
System.out.println("UserName :"+username);
}
}
And, index.xhtml
<body>
<h:form>
<h:inputText id="username" value="#{ubean.username}"></h:inputText>
<h:commandButton value="submit" action="#{hellobean.showMsg}"></h:commandButton>
</h:form>
</body>
I want to invoke the showMsg() method from index.xhtml class. The method is fired by clicking commandButton, but it always returns null instead of inputText value. What's the problem in my codes. Someone, helps...
Thanks in advance..
Here username is the property of UserBean.java class. As a result, you must have to call the username variable through a object of the parent(UserBean.java) class.So, try it, mbean.getUsername() instead of only username.

inject the same #SessionScoped Bean in different #Named Beans

I have a little javaee webproject and i need bean injection in it. i have a tomee server with cdi enabled. Here is a little test case.
Here is my #SessionScoped User object
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
#SessionScoped
public class User implements Serializable {
String userName;
public User () {}
public User (String userName) { this.userName = userName; }
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
}
and here are my two nearly identical beans:
#Named
#RequestScoped
public class BeanOne {
private String message;
#Inject User user;
#PostConstruct
public void init() { user = new User("TestName"); }
public String getMessage() { return user.getUserName(); }
}
In this bean i create a new user. the method getMessage returns the correct user name. I thought the user should still exist in the second bean because its #SessionScoped. Here is my second bean.
#Named
#RequestScoped
public class BeanTwo {
private String message;
#Inject User user;
public String getMessage() { return user.getUserName(); }
}
But in this bean the user.getUserName() returns null. How am i supposed to inject a #SessionScoped bean?
This happens because you have manually initialized user object in BeanOne init method. The purpose of dependency injection is to let some container create instances of objects for you, so you should never initialize objects manually. So just set a name for this user and it will be visible during session for all other beans.
#PostConstruct
public void init() { user.setUserName("TestName"); }

How to use CDI and Dependency Injection

I want to use the same object "User" within the Farma and the Pata objects. The object user is first initialized inside the Farma object. I tried to annotated with #inject, but the object user inside Pata, has the name with null value. Please, can anyone help me understand what I am doing wrong? Thank!
#Named
#SessionScoped
public class Farma implements Serializable {
#Inject private User user;
#PostConstruct
public void initialize(){
user.setName("MyName");
}
// Getters and Setters
}
#Named
#SessionScoped
public class Pata implements Serializable {
#Inject private User user;
public String getFuzzyName() {
// Here I want to use the object "user" with the name "MyName" to do some logic
}
// Getters and Setters
}
public class User implements Serializable {
private String name;
// Getters and Setters
Just scoping a User object won't allow you to initialize it.
Use "producer method" to control bean's creation.
Try this:
#SessionScoped
public class Pata implements Serializable {
#Inject
#SessionUser // inject here using the producer method
private User user;
public String getFuzzyName() {
return user.getName();
}
}
#SessionScoped
public class Farma implements Serializable {
#Produces
#SessionUser // qualifier to tie injection points to this method
#SessionScoped // to ensure it will be called once per session for any number of injection points
public User produceUser() {
System.out.println("Creating user");
User u = new User();
u.setName("User");
return u;
}
}
////// that's your custom qualifier, it's in a separate file
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface SessionUser {}
// no scopes here, it is defined by the producer method
public class User implements Serializable {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
You need to understand scoping of CDI beans. The default scope, if none is specified, is the #Dependent scope, which means that an object exists to serve exactly one client (bean) and has the same lifecycle as that client (bean).
In this case it means that the user in Farma only exists for the Farma class and lives for the life of the Farma class.
The user in Pata is a different instance, and its lifecycle matches that of Pata.
You need to properly scope the User object.
As axiopisty said, adding #Named #SessionScoped is the correct way.
I tried and it works great.
#Named
#SessionScoped
public class Pata implements Serializable {
#Inject
private User user;
public String getFuzzyName() {
System.out.println(user.getName());
return user.getName();
}
public User getUser() {
return user;
}
public void setUser(final User user) {
this.user = user;
}
}
#Named
#SessionScoped
public class Farma implements Serializable {
#Inject
private User user;
#PostConstruct
public void initialize() {
user.setName("MyName");
}
// Getters and Setters
public User getUser() {
return user;
}
public void setUser(final User user) {
this.user = user;
}
}
#Named
#SessionScoped
public class User implements Serializable {
private String name = "Default";
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
<h:outputText value="#{farma}"></h:outputText><br />
<h:outputText value="#{pata}"></h:outputText><br />
<h:outputText value="#{pata.fuzzyName}"></h:outputText>

Why is an exception thrown when an #ManagedProperty is referenced?

I have a JSF web application with a view-scoped bean and a session-scoped bean. I'd like to modify the session bean's members from the view bean, and I followed this guide from a certain well-known JSF guy, but I can't seem to get it to work without a runtime exception. The reference to the managed session bean, "home" is null when referenced, similar to this question except I've already followed the advice of the accepted answer.
package brian.canadaShipping;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
#ManagedBean(name= "requestBean")
#ViewScoped
public class CpstcRequestBean implements Serializable {
#ManagedProperty(value="#{home}")
private CpstcHomeBean homeBean;
public CpstcHomeBean getHomeBean() {
return homeBean;
}
public void setHomeBean(CpstcHomeBean homeBean) {
this.homeBean = homeBean;
}
private static final long serialVersionUID = -5066913533772933899L;
public String testVar = "hello world";
private boolean displayOutput = false;
public boolean isDisplayOutput() {
return displayOutput;
}
public void setDisplayOutput(boolean displayOutput) {
this.displayOutput = displayOutput;
}
public String getTestVar() {
return testVar;
}
public void setTestVar(String testVar) {
this.testVar = testVar;
}
public CpstcRequestBean()
{
System.out.println("TEST: " + homeBean.toString());
System.out.println("Hello, ResuestBean!");
}
}
The first bit of my "home" bean is as follows:
#ManagedBean(name= "home")
#SessionScoped
public class CpstcHomeBean implements Serializable {
...
UPDATE: I've followed Jordan's suggestions and I have the following in my view-scoped bean:
#ManagedBean(name= "requestBean")
#ViewScoped
public class CpstcRequestBean implements Serializable {
#Inject #Named("home") CpstcHomeBean homeBean;
public CpstcHomeBean getHomeBean() {
return homeBean;
}
public void setHomeBean(CpstcHomeBean homeBean) {
this.homeBean = homeBean;
}
public CpstcRequestBean()
{
System.out.println("TEST: " + homeBean.toString());
System.out.println("Hello, ResuestBean!");
}
...
as well as this in my session-scoped bean:
#Named("home")
#SessionScoped
public class CpstcHomeBean implements Serializable {
...
yet my "home" bean reference is still null. Any ideas?
UPDATE 2: It turns out that you must use #Named in both classes, not just the injected class. My web app now loads but some elements are blank. In my console log, I see, "Target Unreachable, identifier 'home' resolved to null." I'm running on Tomcat 7, if that affects things. Any ideas?
You can either change your session bean's #ManagedBean to #Named and then just inject it into your view scoped bean OR you can reference the session bean as is like this:
FacesContext fc = FacesContext.getCurrentInstance()
private CpstcHomeBean homeBean = (CpstcHomeBean) fc.getApplication().evaluateExpressionGet(fc, "#{home}", CpstcHomeBean.class);

JSF injection with managed property, good pattern?

I'm quite new to JSF and not really "used" to the different thinking so I'm struggling on what (I assume) is basic.
Lets say I have a class User, which is a session bean.
Lets say I have a controller of 10000 objects, say Factory, that needs to be able to set some of them as "locked", in our case it means that the "locked" field does not become null anymore but reference a "LockedItem" object.
This is where I can't get things working : LockedItem, when you instanciate it, is supposed to reference the user currently logged in. How am I supposed to do that ?
I tried injection with #managedproperty, but it is null in LockedItem.constructor (which is normal I assume) then I tried in a #PostConstruct method, but that method is never called (why ? Even if I make it a managedbean... are the postconstruct methods only called when the object is created by the ".xhtml" ?)
Or should I use a "java se" trick, like making the User static ?
Code to clarify why is a #PostConstruct not called (the one of "Seat") :
.xhtml
<h:outputLabel id="user" value="Hello #{user.name}" />
<h:outputLabel id="car" value="you have #{car.brand}" />
User
package test;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class User implements Serializable {
private String name ;
public User()
{
name = "toto";
System.out.println("User constructor");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Car
package test;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
#ManagedBean
public class Car implements Serializable {
private String brand ;
private Seat seat ;
public Car()
{
brand = "audi" ;
seat = new Seat();
System.out.println("Car constructor") ;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
Seat
package test;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
#ManagedBean
public class Seat implements Serializable {
private int nb ;
private String userName ;
#ManagedProperty("#{user}")
private User user ;
public Seat()
{
nb = 4 ;
userName="na";
System.out.println("! Seat constructor ") ;
}
#PostConstruct
public void init()
{
System.out.println("!! Seat postconstruct : "+user.getName());
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public int getNb() {
return nb;
}
public void setNb(int nb) {
this.nb = nb;
}
}
Thanks !
The #PostConstruct is the right way.
It's not called if you instantiate the bean yourself using new operator (obviously). It's only called if JSF instantiates and manages the bean itself whenever it's referenced for the first time in EL context like so #{bean}. This indeed usually happens in the view side, but this can also happen in model/controller side by #ManagedProperty("#{bean}") or Application#evaluateExpressionGet().
You should absolutely not make the User static. It would be shared applicationwide, not sessionwide.
An alternative is to just pass the current User as constructor argument of LockedItem, or to invoke the initialization method yourself, for sure if that class does not represent a legit JSF backing bean at all.

Resources