2

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 !

Andrea
  • 1,057
  • 1
  • 20
  • 49
Qualaelay
  • 713
  • 2
  • 10
  • 21

1 Answers1

5

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks BalusC ! I've tried all this in a small test case, and still can't seem to get the PostConstruct of a class ("Seat") called using the @ManagedProperty, would you happen to have any idea of what's wrong in my code (posted as reply) ? (Note that it is indeed called if I have ) – Qualaelay Sep 10 '12 at 09:27
  • You should have a `@ManagedProperty("#{seat}")` instead of `new Seat()`. – BalusC Sep 10 '12 at 10:49
  • According to your solutions, I still have a "pattern" issue actually because of abstract. In my concrete case, I have a `LibraryObject` which is abstract and defines a default implementation for locking a object (which is, associating a `LockedItem`). `LockedItem` must know who is the `User` (session bean) to get its name. Initially, nor `LibraryObject` nor `LockedItem` are beans. The best way to do it seems to make the `LibraryObject` a managedBean on which I inject the `User` and, as you said, create a new `LockedItem` giving the `User` reference, but I can't since its abstract... Any idea ? – Qualaelay Sep 14 '12 at 09:17