Come iniettare @EJB, @PersistenceContext, @Inject, @Autowired, ecc in @FacesConverter?

Come posso iniettare una dipendenza come @EJB , @PersistenceContext , @Inject , @AutoWired , ecc in un @FacesConverter ? Nel mio caso specifico ho bisogno di iniettare un EJB tramite @EJB :

 @FacesConverter public class MyConverter implements Converter { @EJB protected MyService myService; @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { // myService.doSomething } } 

Tuttavia, non è stato iniettato e rimane null , risultando in NPE. Sembra che anche @PersistenceContext e @Inject non funzionino.

Come faccio ad iniettare una dipendenza del servizio nel mio convertitore in modo che possa accedere al DB?

Posso usare @EJB per iniettare il mio servizio in un @FacesConverter ?

No, non prima che venga rilasciato JSF 2.3. I ragazzi JSF / CDI stanno lavorando su questo per JSF 2.3. Vedi anche il numero 1349 delle specifiche JSF e questo ha riguardato “Cosa c’è di nuovo in JSF 2.3?” articolo del mio collega Arjan Tijms. Solo l’iniezione di dipendenza come @EJB , @PersistenceContext , @Inject , ecc funzionerà in @FacesConverter quando si aggiunge esplicitamente l’attributo managed=true all’annotazione.

 @FacesConverter(value="yourConverter", managed=true) public class YourConverter implements Converter { @Inject private YourService service; // ... } 

In caso contrario, qual è il modo “corretto” per farlo?

Prima di JSF 2.3, hai diverse opzioni:

  1. Rendilo invece un bean gestito. Puoi renderlo un bean gestito da JSF, CDI o Spring tramite @ManagedBean , @Named o @Component . L’esempio seguente lo rende un bean gestito JSF.

     @ManagedBean @RequestScoped public class YourConverter implements Converter { @EJB private YourService service; // ... } 

    E l’esempio seguente lo rende un bean gestito da CDI.

     @Named @RequestScoped public class YourConverter implements Converter { @Inject private YourService service; // ... } 

    come invece di , o come invece di . Non dimenticare di rimuovere l’annotazione @FacesConverter !

    Lo svantaggio è che non è ansible specificare forClass e quindi è necessario definire manualmente il convertitore ovunque nella vista, laddove necessario.

  2. Inietti invece in un bean gestito regolarmente.

     @ManagedBean @RequestScoped public class YourBean { @EJB private YourService service; // ... } 

    E nel tuo convertitore, afferralo o chiamalo tramite EL.

     YourBean yourBean = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class); // Then eg either YourEntity yourEntity = yourBean.getService().findByStringId(value); // Or YourEntity yourEntity = yourBean.findEntityByStringId(value); 

    In questo modo puoi continuare a utilizzare @FacesConverter .

  3. Afferrare manualmente l’EJB da JNDI.

     YourService yourService = (YourService) new InitialContext().lookup("java:global/appName/YourService"); 

    Lo svantaggio è che esiste un certo rischio che questo non sia interamente portatile. Vedi anche Inietti bean EJB dal bean gestito JSF a livello di programmazione .

  4. Installa OmniFaces . Dalla versione 1.6, aggiunge in modo trasparente il supporto per @EJB (e @Inject ) in un @FacesConverter senza ulteriori modifiche. Vedi anche la vetrina . Se ti serve il convertitore per , l’alternativa è usare il suo SelectItemsConverter che eseguirà automaticamente il processo di conversione sulla base di elementi selezionati senza la necessità di alcuna interazione con il database.

      

    Vedi anche Errore conversione valore di impostazione per “Convertitore nullo” .

Guarda anche:

  • Come iniettare in @FacesValidator con @EJB, @PersistenceContext, @Inject, @Autowired
  • Iniezione CDI in un FacesConverter
  • Ottenere un @EJB in @FacesValidator e @FacesConverter

La risposta è Sì se puoi ospitare il modulo Seam Faces nella tua applicazione web. Si prega di controllare questo post Iniezione di EntityManager o CDI Bean in FacesConverter . Puoi usare @EJB in modo simile.

È ansible accedervi indirettamente tramite FacesContext, che è un parametro in entrambi i metodi di conversione.

Il convertitore può anche essere annotato CDI denominato con ambito applicazione. Quando si accede alla facciata, vengono utilizzate due istanze della stessa class. Uno è l’istanza del convertitore stessa, stupida, senza conoscere l’annotazione EJB. Un’altra istanza conserva l’ambito dell’applicazione e potrebbe essere accessibile tramite FacesContext. Quell’istanza è un object con nome, quindi conosce l’annotazione EJB. Poiché tutto viene eseguito in una singola class, l’accesso potrebbe essere protetto.

Guarda il seguente esempio:

 @FacesConverter(forClass=Product.class) @Named @ApplicationScoped public class ProductConverter implements Converter{ @EJB protected ProductFacade facade; protected ProductFacade getFacadeFromConverter(FacesContext ctx){ if(facade==null){ facade = ((ProductConverter) ctx.getApplication() .evaluateExpressionGet(ctx,"#{productConverter}",ProductConverter.class)) .facade; } return facade; } @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { return getFacadeFromConverter(context).find(Long.parseLong(value)); } ... 

@Inject funziona solo nelle istanze gestite da CDI

Funziona solo con almeno Java EE 7 e server CDI 1.1 :

 @FacesConverter public class MyConverter implements Converter { protected MyService myService; @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { myService = CDI.current().select(MyService .class).get(); myService.doSomething(); } } 

Di Luis Chacon, Sv

Funziona bene, testato

definizione EJB:

 @Stateless @LocalBean public class RubroEJB { @PersistenceContext(unitName = "xxxxx") private EntityManager em; public List getAllCfgRubroPres(){ List rubros = null; Query q = em.createNamedQuery("xxxxxxx"); rubros = q.getResultList(); return rubros; } } 

definire il bean con l’ambito del bean Aplication, per ottenere l’object EJB

 @ManagedBean(name="cuentaPresService", eager = true) @ApplicationScoped public class CuentaPresService { @EJB private RubroEJB cfgCuentaEJB; public RubroEJB getCfgCuentaEJB() { return cfgCuentaEJB; } public void setCfgCuentaEJB(RubroEJB cfgCuentaEJB) { this.cfgCuentaEJB = cfgCuentaEJB; } } 

accesso finale all’object Ejb dal convertitore:

 @FacesConverter("cuentaPresConverter") public class CuentaPresConverter implements Converter { @EJB RubroEJB rubroEJB; public Object getAsObject(FacesContext fc, UIComponent uic, String value) { if(value != null && value.trim().length() > 0) { try { CuentaPresService service = (CuentaPresService) fc.getExternalContext().getApplicationMap().get("cuentaPresService"); List listCuentas=service.getCfgCuentaEJB().getAllCfgCuentaPres(); ................