Внедрение JSF с управляемым свойством, хороший шаблон?

Я новичок в JSF и на самом деле не «привык» к другому мышлению, поэтому я борюсь с тем, что (я полагаю) является основным.

Допустим, у меня есть класс User, который является сессионным компонентом.

Допустим, у меня есть контроллер 10000 объектов, скажем Factory, который должен иметь возможность установить некоторые из них как «заблокированные», в нашем случае это означает, что поле «заблокировано» больше не становится нулевым, а ссылается на «LockedItem» объект.

Вот где я не могу заставить все работать: LockedItem, когда вы его создаете, должен ссылаться на пользователя, вошедшего в систему в данный момент. Как я должен это сделать?

Я пробовал инъекцию с помощью @managedproperty, но он имеет значение null в LockedItem.constructor (что, как я полагаю, нормально), затем я пытался использовать метод @PostConstruct, но этот метод никогда не вызывается (почему? Даже если я сделаю его управляемым компонентом... методы постконструкции вызываются только тогда, когда объект создается с помощью «.xhtml»?) Или мне следует использовать трюк «java se», например сделать пользователя статическим?


Код, поясняющий, почему не вызывается @PostConstruct (один из "Seat"):

.xhtml

<h:outputLabel id="user" value="Hello #{user.name}" />
<h:outputLabel id="car" value="you have #{car.brand}" />

Пользователь

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;
    }


}

Автомобиль

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;
    }


}

Место

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;
    }
}

Спасибо !


person Qualaelay    schedule 07.09.2012    source источник


Ответы (1)


@PostConstruct это правильный путь.

Он не вызывается, если вы сами создаете экземпляр компонента с помощью оператора new (очевидно). Он вызывается только в том случае, если JSF создает экземпляр и управляет самим компонентом всякий раз, когда на него ссылаются в первый раз в контексте EL, например так #{bean}. Это действительно обычно происходит на стороне представления, но это также может происходить на стороне модели/контроллера с помощью @ManagedProperty("#{bean}") или Application#evaluateExpressionGet().

Вы ни в коем случае не должны делать User статичным. Он будет общим для всего приложения, а не для всего сеанса.

В качестве альтернативы можно просто передать текущий User в качестве аргумента конструктора LockedItem или вызвать метод инициализации вы сами, если этот класс вообще не представляет законный вспомогательный компонент JSF.

person BalusC    schedule 07.09.2012
comment
Спасибо BalusC! Я попробовал все это в небольшом тестовом примере и до сих пор не могу получить PostConstruct класса (Seat), вызываемого с помощью @ManagedProperty. Вы случайно не знаете, что не так в моем коде (опубликованном как Ответить) ? (Обратите внимание, что он действительно вызывается, если у меня есть ‹h:outputLabel id=seat value=у вас есть #{seat.nb} мест /›) - person Qualaelay; 10.09.2012
comment
У вас должно быть @ManagedProperty("#{seat}") вместо new Seat(). - person BalusC; 10.09.2012
comment
Согласно вашим решениям, у меня все еще есть проблема с шаблоном из-за абстрактного. В моем конкретном случае у меня есть LibraryObject, который является абстрактным и определяет реализацию по умолчанию для блокировки объекта (то есть ассоциирование LockedItem). LockedItem должен знать, кто является User (сеансовым компонентом), чтобы получить его имя. Изначально ни LibraryObject, ни LockedItem не являются бобами. Лучший способ сделать это, кажется, сделать LibraryObject управляемым компонентом, в который я ввожу User и, как вы сказали, создаю новый LockedItem, дающий ссылку User, но я не могу, поскольку он абстрактный... Есть идеи? - person Qualaelay; 14.09.2012