Как добавить @EJB, @PersistenceContext, @Inject, @Autowired и т. Д. В @FacesConverter? - PullRequest
28 голосов
/ 05 октября 2011

Как я могу ввести зависимость типа @EJB, @PersistenceContext, @Inject, @AutoWired и т. Д. В @FacesConverter?В моем конкретном случае мне нужно ввести EJB через @EJB:

@FacesConverter
public class MyConverter implements Converter {

  @EJB
  protected MyService myService;    

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

}

Однако, он не был введен и остается null, что приводит к NPE.Кажется, что @PersistenceContext и @Inject также не работают.

Как добавить сервисную зависимость в мой конвертер, чтобы я мог получить доступ к БД?

Ответы [ 5 ]

53 голосов
/ 05 октября 2011

Могу ли я использовать @EJB для ввода моего сервиса в @FacesConverter?

Нет, пока JSF 2.3 не будет выпущен.Над этим работают ребята из JSF / CDI для JSF 2.3.См. Также выпуск спецификации JSF 1349 и связанную с ним «Что нового в JSF 2.3?» статью моего коллеги Арджана Тиймса.Только тогда внедрение зависимостей, например @EJB, @PersistenceContext, @Inject и т. Д., Будет работать в @FacesConverter при явном добавлении атрибута managed=true к аннотации.

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

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

Если нет, каков «правильный» способ сделать это?

До JSF 2.3 у вас есть несколько вариантов:

  1. Вместо этого сделайте это управляемым бобом.Вы можете сделать его управляемым bean-компонентом JSF, CDI или Spring через @ManagedBean, @Named или @Component.Приведенный ниже пример делает его управляемым компонентом JSF.

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

    И приведенный ниже пример делает его управляемым компонентом CDI.

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

    Ссылка на <h:inputXxx converter="#{yourConverter}"> вместо <h:inputXxx converter="yourConverter"> или <f:converter binding="#{yourConverter}"> вместо <f:converter converterId="yourConverter">.Не забудьте удалить аннотацию @FacesConverter!

    Недостатком является то, что вы не можете указать forClass и, следовательно, должны вручную определять конвертер везде, где это необходимо.

  2. Вместо этого введите его в обычный управляемый компонент.

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

    А в конвертере возьмите его или позвоните через 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);
    

    Таким образом, вы можете продолжать использовать @FacesConverter.

  3. Вручную извлекать EJB из JNDI.

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

    Недостатком является то, что существует определенный риск, что этоне совсем портативный.См. Также Программный ввод EJB-компонента из управляемого JSF-компонента .

  4. Установка OmniFaces .Начиная с версии 1.6, он прозрачно добавляет поддержку @EJB@Inject) в @FacesConverter без каких-либо дальнейших изменений.Смотрите также витрина .Если вам нужен конвертер для <f:selectItem(s)>, то альтернативой является использование его SelectItemsConverter, который будет автоматически выполнять задание конвертации на основе выбранных элементов без необходимости какого-либо взаимодействия с базой данных.

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

    См. Также Значение параметра «Ошибка преобразования» для «нулевого преобразователя» .

См. Также:

2 голосов
/ 14 октября 2011

Ответ Да, если вы можете разместить модуль Seam Faces в своем веб-приложении. Пожалуйста, проверьте этот пост Инъекция EntityManager или CDI Bean в FacesConverter . Вы можете использовать @EJB аналогичным образом.

0 голосов
/ 17 августа 2017

@ Inject будет работать только в управляемых CDI экземплярах

Это работает только по крайней мере Java EE 7 и 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();
  }

}
0 голосов
/ 27 октября 2016

Луис Чакон, Св

Работает нормально, проверено

определение 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;
    }
}

определить bean-компонент с областью действия Aplication bean для получения объекта 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 Доступ к объекту Ejb из конвертера:

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


                ................
0 голосов
/ 28 мая 2015

Вы можете получить к нему косвенный доступ через FacesContext, который является параметром в обоих методах конвертера.

Преобразователь также может быть аннотирован CDI с именем Application scope. При доступе к фасаду используются два экземпляра одного класса. Одним из них является сам экземпляр преобразователя, тупой, не зная аннотации EJB. Другой экземпляр остается в области приложения и может быть доступен через FacesContext. Этот экземпляр является Именованным объектом, поэтому он знает аннотацию EJB. Поскольку все сделано в одном классе, доступ может быть защищен.

См. Следующий пример:

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

...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...