Comment injecter @EJB, @PersistenceContext, @Inject, @Autowired, etc dans @FacesConverter?

Comment puis-je injecter une dépendance comme @EJB , @PersistenceContext , @Inject , @AutoWired , etc dans un @FacesConverter ? Dans mon cas spécifique, je dois injecter un EJB via @EJB :

@FacesConverter
public class MyConverter implements Converter {

  @EJB
  protected MyService myService;    

  @Override
  public Object getAsObject(FacesContext context, UIComponent component, String value) {
    // myService.doSomething
  }

}

cependant, il n'a pas été injecté et il reste null , résultant en NPE. Il semble que @PersistenceContext et @Inject ne fonctionne pas non plus.

comment injecter une dépendance de service dans mon convertisseur pour accéder à la base de données?

28
demandé sur BalusC 2011-10-05 22:08:55

5 réponses

puis-je utiliser @EJB pour injecter mon service dans un @FacesConverter ?

non, pas avant que JSF 2.3 soit libéré. Les gars du JSF/CDI y travaillent pour JSF 2.3. Voir aussi JSF spec issue 1349 et " Quoi de neuf en JSF 2.3?" article de mon collègue Arjan Tijms. Seulement alors l'injection de dépendance comme @EJB , @PersistenceContext , @Inject , etc fonctionnera dans un attribut @FacesConverter lorsque vous ajoutez explicitement managed=true à l'annotation.

@FacesConverter(value="yourConverter", managed=true)
public class YourConverter implements Converter {

    @Inject
    private YourService service;
    // ...
}

Si non, quelle est la "bonne" façon de faire cela?

avant JSF 2.3, vous avez plusieurs options:

  1. en font un haricot géré à la place. Vous pouvez en faire un JSF, CDI ou bean géré au printemps via @ManagedBean , @Named ou @Component . L'exemple ci-dessous en fait un haricot géré par le JSF.

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

    et l'exemple ci-dessous en fait un haricot géré par le CDI.

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

    L'appelle <h:inputXxx converter="#{yourConverter}"> au lieu de <h:inputXxx converter="yourConverter"> , ou <f:converter binding="#{yourConverter}"> au lieu de <f:converter converterId="yourConverter"> . N'oubliez pas de supprimer l'annotation @FacesConverter !

    l'inconvénient est que vous ne pouvez pas spécifier forClass et donc besoin définir manuellement le convertisseur partout dans la vue si nécessaire.

  2. injectez-le dans un haricot ordinaire à la place.

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

    et dans votre convertisseur, le saisir ou l'appeler via EL.

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

    de cette façon, vous pouvez continuer à utiliser @FacesConverter .

  3. saisir manuellement L'EJB de JNDI.

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

    le l'inconvénient est qu'il y a un certain risque que cela ne soit pas entièrement portable. Voir aussi injecter EJB bean à partir de JSF managed bean programmatically .

  4. Installer OmniFaces . Depuis la version 1.6, il ajoute de manière transparente le support pour @EJB (et @Inject ) dans un @FacesConverter sans aucune autre modification. Voir aussi la vitrine . Si vous avez besoin de la convertisseur pour <f:selectItem(s)> , puis l'alternative est d'utiliser son SelectItemsConverter qui effectuera automatiquement le travail de conversion basé sur des éléments sélectionnés sans avoir besoin d'une interaction de base de données.

    <h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
    

    Voir aussi Erreur de Conversion valeur de réglage pour la valeur 'null Converter" .

voir aussi:

51
répondu BalusC 2017-05-23 11:55:15

la réponse est Oui si vous pouvez accommoder le module seam Faces dans votre application web. S'il vous plaît vérifier ce post Injection de EntityManager ou de la fève CDI dans FacesConverter . Vous pouvez utiliser @EJB de la même manière.

2
répondu Karthikeyan Chockalingam 2014-01-10 14:09:29

vous pouvez y accéder indirectement via FacesContext, qui est un paramètre dans les deux méthodes de convertisseur.

le convertisseur pourrait également être annoté CDI nommé avec la portée de l'Application. Lors de l'accès à la façade, deux instances de la même classe sont utilisées. L'une est l'instance du convertisseur elle-même, muet, sans connaître l'annotation EJB. Une autre instance conserve son champ d'application et peut être consultée via le texte de la face. Cette instance est un objet nommé, donc elle sait the EJB annotation. Comme tout est fait en une seule classe, l'accès pourrait être protégé.

voir l'exemple suivant:

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

...
0
répondu Pavel Sedek 2015-06-09 15:23:35

@Inject ne fonctionnera que dans les instances gérées par le CDI

cela ne fonctionne au moins Java EE 7 et CDI 1.1 serveur:

@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();
  }

}
0
répondu ℛɑƒæĿ 2017-08-17 11:49:38

Par Luis Chacon, Sv

fonctionne bien, testé

définition EJB:

@Stateless
@LocalBean
public class RubroEJB {

    @PersistenceContext(unitName = "xxxxx")
    private EntityManager em;

    public List<CfgRubroPres> getAllCfgRubroPres(){
        List<CfgRubroPres> rubros = null;
        Query q = em.createNamedQuery("xxxxxxx");
        rubros = q.getResultList();
        return rubros;
    }
}

définir un bean avec l'Application de haricots portée, pour obtenir l'Objet d'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;
    }
}

final l'Accès aux Ejb Objet de Convertisseur:

@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<CfgCuentaPres> listCuentas=service.getCfgCuentaEJB().getAllCfgCuentaPres();


                ................
-3
répondu Luis Chacon 2016-10-26 22:29:28