JSF: проблема конвертера selectOneRadio - PullRequest
1 голос
/ 17 мая 2011

У меня проблемы с использованием компонента selectOneRadio. Я получаю исключение NullPointerException в getAsString моего конвертера. Это исключение выдается еще до того, как я смог увидеть этот компонент.

Вот как это выглядит:

            <h:selectOneRadio id="bookA"
                value="#{bookHandler.compareBookA}">
                 <f:converter converterId="bookConverter" />
                <f:selectItems value="#{bookHandler.selectedBooks}"
                    var="book" itemLabel="#{book.shortname}" itemValue="#{book}" />
            </h:selectOneRadio>

Свойство compareBookA является объектом типа Book.

Это метод, который бросает NPE:

@Override
public String getAsString(FacesContext fc, UIComponent uic, Object value)
        throws ConverterException {
    Book book = (Book) value;
    if (book == null ) {
        throw new ConverterException("NPE...");
    }
    return book.getShortname();
}

Я также перезаписал toString ().

По какой-то причине компонент отображается, если я изменяю его на selectManyCheckbox (а остальное оставляю как есть).

Я использую JSF 2 (реализация MyFaces) с Tomahawk на Tomcat.

Бонусный вопрос: зачем мне конвертер? Если я оставлю конвертер вне, компонент будет визуализирован, но я хочу передать выбранную книгу какому-либо методу действия, и тогда это не будет книга.

Есть идеи? Спасибо!

Ответы [ 2 ]

3 голосов
/ 17 мая 2011

Видимо #{bookHandler.compareBookA} это просто null.

Вы не должны бросать ConverterException, когда Book равно null, а просто отпустить.

return (book != null) ? book.getShortname() : null;

Что касается бонусного вопроса, вам нужны конвертеры, потому что HTML-ответ в основном одна большая строка . Все объекты Java должны быть преобразованы в строку, чтобы встроиться в ответ HTML. Кроме того, параметры HTTP-запроса по умолчанию являются строками. request.getParameter() возвращает String. HTML / HTTP совершенно не знает, как обрабатывать и передавать полноценные объекты Java.

Смотри также:

1 голос
/ 17 мая 2011

Конвертер предоставляет механизм для преобразования POJO в представление String (HTML), а затем преобразовывает эту строку обратно в экземпляр того же POJO. В вашем примере вы не хотите выдавать исключение, а просто возвращаете ноль, когда Book равен нулю.

Одна вещь, которую я часто делаю в своем приложении, - это создание универсального конвертера, который работает для всех моих selectItems. Это легко, если все ваши сущности реализуют общий интерфейс, например, со свойством id.

public interface Entity extends Serializable {

    /**
     * Return the primary key for this entity
     * 
     * @return id
     */
    public BigInteger getId();

}

Затем вы можете создать соглашение о том, как все сущности должны быть преобразованы в строку и обратно в объект. Обычно я объединяю имя класса и идентификатор, а затем кодирую их в Base64, чтобы преобразовать объект в строку и затем обратить преобразование:

/*
 * (non-Javadoc)
 * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
 */
@SuppressWarnings("unchecked")
public Object getAsObject(FacesContext context, UIComponent component, String value) {

    Object objectValue = null;

    try {            
        BigInteger id = null;

        value = this.unhash(value);            
        String[] array = value.split(CLASS_KEY_SEPARATOR);

        if (array.length == 2) {
            id = new BigInteger(array[1]);
        }

        Collection<UIComponent> childComponents = component.getChildren();

        for (UIComponent childComponent : childComponents) {

            if (childComponent.getClass().equals(UISelectItems.class)) {

                Collection<Entity> values = 
                    (Collection<Entity>) childComponent.getValueExpression("value").getValue(FacesContext.getCurrentInstance().getELContext());

                for (Entity selectItemValue : values) {
                    if (id.equals(selectItemValue.getId())) {
                        return selectItemValue;
                    }
                }
            }
        }            

    } catch (Exception ex) {
        LOGGER.error(ex.getMessage(), ex);
    }

    return objectValue;
}

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

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