Внедрение CDI в FacesConverter

Судя по нескольким поискам, это похоже на проблему, которая существует уже некоторое время. Я написал FacesConverter, который выглядит следующим образом. Объект Category — это объект 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.

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

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


person AlanObject    schedule 23.09.2011    source источник


Ответы (4)


Заменять

@FacesConverter(value = "categoryConverter")

by

@Named

и использовать

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

or

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

вместо

<h:inputSomething converter="categoryConverter" />

or

<f:converter converterId="categoryConverter" />

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


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

person BalusC    schedule 23.09.2011
comment
Что ж, я буду проклят. Я реализовал обходной путь, который в основном вызывает приложение для оценки выражения изнутри преобразователя, но я думаю, что это более элегантно. Итак, у меня есть еще один вопрос @BalusC - не пора ли вам написать книгу о JSF? - person AlanObject; 23.09.2011
comment
Ну, не то чтобы вам пришлось много писать — просто отредактируйте все, что вы уже написали. Серьезно, я подумал о наброске книги, если вы заинтересованы в сотрудничестве, просто дайте мне знать. - person AlanObject; 23.09.2011
comment
Что ж, можете ли вы поверить в это, почти ровно через год после первоначальной публикации я снова столкнулся с этой проблемой в новом проекте, сделал поиск в Google и пришел со своим собственным сообщением! Я не помню, чтобы писал это выше, но компьютеры никогда не лгут. - person AlanObject; 30.09.2012
comment
@BalusC Как и многие другие ваши ответы, люди ссылаются на этот и по сей день, например, stackoverflow.com/questions/18183176/. Вы можете подумать о редактировании, чтобы включить поддержку, предоставляемую Omnifaces, в 1.6, как только он выйдет :) - person rdcrng; 14.08.2013
comment
SelectItemsConverter из [OmniFaces] (code.google.com/p/omnifaces), спасите меня. Спасибо @BalusC! - person Gilberto; 18.03.2014
comment
@BalusC Вам не нужно писать книгу. Ты должен жениться на мне. - person Jin Kwon; 09.11.2016

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

Это работает, по крайней мере, на сервере 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 люди забывают, как программировать.

person FuryFart    schedule 08.10.2015


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

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

person Howard    schedule 20.11.2012