2011-09-23 14 views
24

Da poche ricerche, questo sembra un problema che è stato in giro per un po '. Ho scritto un FacesConverter che assomiglia al seguente. L'oggetto Categoria è un'entità JPA e CategoryControl è il DAO che lo preleva.CDI Injection in a FacesConverter

@FacesConverter(value = "categoryConverter") 
public class CategoryConverter implements Converter { 

@Inject private CategoryControl cc; 

public CategoryConverter() { } 

@Override 
public Object getAsObject(FacesContext context, UIComponent component, String value) { 
    if (cc != null) return cc.getByName(value); 
    System.out.println("CategoryConverter().getAsObject(): no injection!"); 
    return null; 
} 

@Override 
public String getAsString(FacesContext context, UIComponent component, Object value) { 
    if (!(value instanceof Category)) return null; 
    return ((Category) value).getName(); 
} 

} 

Come probabilmente avete indovinato ormai, non ho mai ottenere l'iniezione. Ho ottenuto questa soluzione da this page, che assomiglia a questo .:

Workaround for this problem: create this method in your localeController: 

public Converter getConverter() 
{ 
    return FacesContext.getCurrentInstance().getApplication().createConverter("localeConverter"); 
} 

and use converter="#{localeController.converter}" in your h:selectOneMenu. 

Tuttavia non posso fare questo lavoro sia. Il mio backing bean crea e restituisce un convertitore, ma non viene iniettato dall'oggetto.

Sto utilizzando MyFaces CODI 1.0.1. Con l'attuale contenitore GlassFish/Weld. Qualcuno può suggerire una soluzione prima di ricodificare per non utilizzare un convertitore?

risposta

53

Sostituire

@FacesConverter(value = "categoryConverter") 

da

@Named 

e utilizzare

<h:inputSomething converter="#{categoryConverter}" /> 

o

<f:converter binding="#{categoryConverter}" /> 

inste annuncio di

<h:inputSomething converter="categoryConverter" /> 

o

<f:converter converterId="categoryConverter" /> 

proposito, problema simile esiste per @EJB all'interno di una @FacesConverter. Offre tuttavia un modo per essere afferrato manualmente da JNDI. Vedi anche Communication in JSF 2.0 - Getting an EJB in @FacesConverter and @FacesValidator. In questo modo è possibile utilizzare un @FacesConverter(forClass=Category.class) senza definirlo manualmente ogni volta. Sfortunatamente non posso dire da capo come realizzarlo per i fagioli CDI.


Aggiornamento: se vi capita di usare JSF libreria di utilità OmniFaces, a partire dalla versione 1.6 aggiunge il supporto è trasparente per l'utilizzo di @Inject e @EJB in una classe @FacesConverter senza alcuna configurazione o le annotazioni aggiuntive. Vedi anche the CDI @FacesConverter showcase example.

+3

Beh, sarò bloccato. Ho implementato una soluzione alternativa che fondamentalmente chiama l'applicazione per valutare un'espressione dall'interno del convertitore, ma penso che questo sia più elegante. Quindi ho un'altra domanda @BalusC - non è ora che hai scritto un libro su JSF? – AlanObject

+3

Prego. Per quanto riguarda il libro, non sei di gran lunga il primo a chiederlo ... – BalusC

+0

Beh, non è che tu debba scrivere molto, basta modificare tutte le cose che hai già scritto. Seriamente ho pensato ad uno schema per un libro se sei interessato a una collaborazione fammelo sapere. – AlanObject

3

Basta usare @Advanced di CODI per il tuo @FacesConverter vedere lo Wiki.

Non appena un convertitore o un validatore viene annotato con @Advanced, è possibile utilizzare @Inject.

2

risposta di Per BalusC here, ho deciso di aggiungere JSF (requestscoped) gestito fagioli che contenevano solo @FacesConverter e convertitore per risolvere questo problema nella mia app, dal momento che sto migrando da JSF è riuscito fagioli per CDI fagioli gestiti.

Ho provato CODI @Advanced contro @FacesConverter, ma non inietta affatto il bean.

6

L'annotazione @Inject funziona solo nelle istanze gestite da CDI. Se si desidera utilizzare le funzionalità CDI all'interno di un'istanza gestita non-CDI (come un validatore JSF o un convertitore JSF), è possibile semplicemente programmare contro l'API CDI.

Questo funziona solo in almeno Java EE 7 + CDI 1.1 server.

@FacesValidator("userNameValidator") 
public class UserNameValidator implements Validator { 

    private UserService userService; 

    public UserNameValidator(){ 
     this.userService = CDI.current().select(UserService.class).get(); 
    } 

    @Override 
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { 
    .... 
    } 
} 

https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html

Con tutta l'AnnotationHell nelle persone Java EE dimenticare come codice.