Инъекция CDI в FacesConverter

Из нескольких поисков это похоже на проблему, которая была вокруг некоторое время. Я написал FacesConverter, который выглядит следующим образом. Объект Категория является объектом JPA, а CategoryControl - это DAO, который его извлекает.

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

}

Как вы, наверное, догадались, я никогда не получаю инъекцию. Я получил это решение из этой страницы, которая выглядит следующим образом:

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.

Однако я не могу выполнить эту работу. Моя поддержка bean создает и возвращает конвертер в порядке, но он не получает объект, введенный в него.

Я использую MyFaces CODI 1.0.1. С текущим контейнером GlassFish/Weld. Может ли кто-нибудь предложить решение до того, как я перекодирую, чтобы не использовать конвертер?

Ответ 1

Заменить

@FacesConverter(value = "categoryConverter")

по

@Named

и используйте

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

или

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

вместо

<h:inputSomething converter="categoryConverter" />

или

<f:converter converterId="categoryConverter" />

Кстати, аналогичная проблема существует для @EJB внутри a @FacesConverter. Однако он предлагает способ захвата JNDI вручную. См. Также Связь в JSF 2.0 - Получение EJB в @FacesConverter и @FacesValidator. Таким образом вы можете использовать @FacesConverter(forClass=Category.class) без ручного определения его каждый раз. К сожалению, я не могу сказать с самого начала, как понять, что для CDI beans.


Обновить: если вы используете библиотечную утилиту JSF OmniFaces, поскольку версия 1.6 добавляет прозрачную поддержку для использования @Inject и @EJB в классе @FacesConverter без каких-либо дополнительных настроек или аннотаций. См. Также пример демонстрации CDI @FacesConverter.

Ответ 2

Аннотация @Inject работает только в управляемых экземплярах CDI. Если вы хотите использовать функции CDI внутри управляемого экземпляром, отличным от CDI (например, JSF Validator или JSF Converter), вы можете просто программировать против API CDI.

Это работает только, по крайней мере, на сервере Java EE 7 + CDI 1.1.

@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

Со всеми AnnotationHell в Java EE люди забывают, как кодировать.

Ответ 3

Просто используйте @Advanced of CODI для вашего @FacesConverter, чтобы увидеть Wiki.

Как только конвертор или валидатор аннотируются с помощью @Advanced, можно использовать @Inject.

Ответ 4

Per BalusC answer здесь, я решил добавить JSF (запрошенный) управляемый beans, который содержал только @FacesConverter и Converter для решения этой проблемы в моем приложении, поскольку Я перехожу из управляемого JSF beans в управляемый CDI beans.

Я попробовал CODI @Advanced против @FacesConverter, но он вообще не вводит bean.