Why cant I get the value of a SessionScoped bean in the constructor of another bean? - jsf

I have this SessionScoped bean:
#ManagedBean
#SessionScoped
public class LoginBean implements Serializable {
/**
* Creates a new instance of LoginBean
*/
public LoginBean() {
this.usuario = new Usuario();
}
private Usuario usuario;
//getter & setter
}
The Usuario class:
public class Usuario {
public Usuario() {
}
private String password;
private String nombre;
private int idPlanta;
private int nivel;
private String idUsuario;
//getters & setters
}
And I want to get the value of the property idPlanta from the SessionScoped bean (LoginBean) here (in the constructor) see the comments:
#ManagedBean
#ViewScoped
public class PrincipalBean implements Serializable {
public PrincipalBean() {
System.out.println(this.login.getUsuario().getIdPlanta());
//AT THIS POINT THE VALUE OF idPlanta IS 0 but in the session I have 1...
//Method that uses the idPlanta value as a parameter
}
#ManagedProperty(value = "#{loginBean}")
private LoginBean login;
public LoginBean getLogin() {
return login;
}
public void setLogin(LoginBean login) {
this.login = login;
}
}
But when I show the value in the view it shows the value that really is in the Session idPlanta = 1. I dont understand why I cant get the value of that property in the constructor of that ViewScoped bean (PrincipalBean). I show the value in the view here(I know I can get it directly fron the LoginBean but this is just to show that the property login in PrincipalBean has the Session value):
<h:outputText class="titulo" value="Bienvenido(a) #{principalBean.login.usuario.nombre} Planta #{principalBean.login.usuario.idPlanta}" />
The value of idPlanta in PrincipalBean is very important because I use it as a method parameter to show more info when the view is showed.
Please help me. I still learning JSF.

You need to be using these values after the bean has been constructed. When your constructor is called, your bean has net yet been initialzed - therefore the injections have not yet happend. Using the #PostConstruct method you will be able to access the desired values from the injected objects.
For example :
#ManagedBean
#ViewScoped
public class PrincipalBean implements Serializable {
public PrincipalBean() {
}
#PostConstruct
public init() {
System.out.println(this.login.getUsuario().getIdPlanta());
//AT THIS POINT THE VALUE OF idPlanta IS 0 but in the session I have 1...
//Method that uses the idPlanta value as a parameter
}
#ManagedProperty(value = "#{loginBean}")
private LoginBean login;
public LoginBean getLogin() {
return login;
}
public void setLogin(LoginBean login) {
this.login = login;
}
}
See Also
Why use #PostConstruct?
Injecting Managed Beans In JSF 2.0
JSF injection with managed property, good pattern?

Related

Passing value between JSF Forms. I can't get it to work

I read the other posts about this subject but I still can't get it to work
This are my beans:
Bean1:
#ManagedBean()
#SessionScoped
public class Bean1 implements Serializable {
//Here are some important Properties
public String buttonPressed() {
return "bean2.xhtml";
}
}
<h:form>
<p:commandButton action="#{Bean1.buttonPressed}" value="Do Work"/>
</h:form>
Bean2:
#ManagedBean()
#SessionScoped
public class Bean2 implements Serializable {
#ManagedProperty(value = "#{Bean1}")
private Bean1 b1;
//getter/setter is here
public String doWorkOnSubmit() {
//Access important Properties from bean1
b1.getFoo()
}
}
Now I have two Problems
1.) How to call "doWorkOnSubmit" if the button in Bean1 is pressed? I can't use the constructor because it's SessionScoped and I don't know how to call doWorkOnSubmit un submit
2.)The managed property "b1" is sometimes null
Since on clicking of Do Work button you are calling Bean1.buttonPressed() action method you can call Bean2s doWorkOnSubmit() by injecting Bean2 in Bean1.
Here is your code altered:
#ManagedBean()
#SessionScoped
public class Bean1 implements Serializable {
//Here are some important Properties
/*
* Inject Bean2 here. since both beans are session scoped,
* there ain't gonna be any problem in injection.
*/
#ManagedProperty(value = "#{Bean2}")
private Bean2 b2;
//GETTER SETTER for b2
public String buttonPressed() {
//Here you will be invoking injected managed beans method.
b2.doWorkOnSubmit();
return "bean2.xhtml";
}
}

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>

How to access property of one managed bean in another managed bean

I have a managed bean (SessionScope as follow)
#ManagedBean(name="login")
#SessionScoped
public class Login implements Serializable {
private String userSession;
public Login(){
}
}
In this managedbean, somewhere in the login function, i store the email as a session.
I have another managed bean called ChangePassword (ViewScoped). I need to access the value of the email which is stored in the userSession.
The reason of doing so is that i need to find out the current userSession(email) before i can complete the change password function. (Need change password for that specific email)
How do i do so? New to JSF, appreciate any help!
Just inject the one bean as a managed property of the other bean.
#ManagedBean
#ViewScoped
public class ChangePassword {
#ManagedProperty("#{login}")
private Login login; // +setter (no getter!)
public void submit() {
// ... (the login bean is available here)
}
// ...
}
See also:
Communication in JSF 2.0 - Injecting managed beans in each other
In JSF2, I usually use a method like this:
public static Object getSessionObject(String objName) {
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extCtx = ctx.getExternalContext();
Map<String, Object> sessionMap = extCtx.getSessionMap();
return sessionMap.get(objName);
}
The input parameter is the name of your bean.
if your session scoped bean is like this :
#ManagedBean(name="login")
#SessionScoped
public class Login implements Serializable {
private String userSession;
public Login(){
}
}
you can access the values of this bean like :
#ManagedBean(name="changePassword")
#ViewScoped
public class ChangePassword implements Serializable {
#ManagedProperty(value="#{login.userSession}")
private String userSession;
public ChangePassword (){
}
}
public static Object getSessionObj(String id) {
return FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(id);
}
public static void setSessionObj(String id,Object obj){
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(id, obj);
}
Add them in your managed bean :

How to get managedbean property from another bean in JSF

I searched similar questions but I'm a bit confused. I have a login page, so LoginBean also which is;
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private String password="";
private String image="";
#ManagedProperty(value = "#{loginBeanIdentityNr}")
private String identityNr="";
...
after success, navigates to orderlist page, so I have also OrderBean.
#ManagedBean(name = "OrderBean")
#SessionScoped
public class OrderBean {
List<Ordery> sdList;
public List<Order> getSdList() {
try {
String identityNr ="";
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
LoginBean lBean = (LoginBean) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, "loginBean");
identityNr =lBean.getIdentityNr();
sdList = DatabaseUtil.getOrderByIdentityNr(identityNr);
...
}
I don't need the whole LoginBean, just ManagedProperty "loginBeanIdentityNr". But this code below doesn't work (of course);
identityNr = (String) FacesContext.getCurrentInstance()
.getApplication().getELResolver()
.getValue(elContext, null, "loginBeanIdentityNr");
this time it returns null to me.
I think if I need whole bean property, I can inject these beans, right? So, do you have any suggestions for this approach? can<f:attribute> be used?
The #ManagedProperty declares the location where JSF should set the property, not where JSF should "export" the property. You need to just inject the LoginBean as property of OrderBean.
public class OrderBean {
#ManagedProperty(value="#{loginBean}")
private LoginBean loginBean; // +setter
// ...
}
This way you can access it in the OrderBean by just
loginBean.getIdentityNr();
Alternatively, if you make your OrderBean request or view scoped, then you can also set only the identityNr property.
public class OrderBean {
#ManagedProperty(value="#{loginBean.identityNr}")
private String identityNr; // +setter
// ...
}
Unrelated to the concrete problem: initializing String properties with an empty string is a poor practice.

Resources