2013-09-01 2 views
1

Я просто попытался изменить значение поля ввода select. Загрузка страницы выполняется в мою точку останова для метода getter свойства pubcategory. До сих пор хорошо. Изменяя значение, НЕ вызывается метод setter. Я запускаю обработку ajax Richfaces. Я подтверждаю, что все фазы JSF проходят (я также вижу запросы выбора JPA-SQL, где я ожидаю, что оператор обновления для изменения значения - ну, не может быть, если метод setter не запускается). Это мой selectOneMenu кодSetter h: selectOneMenu не вызывается

<h:selectOneMenu id="pubCategoryId" converter="#{pubCategoryConverter}" value="#{pubController.pubCategory}">       
<f:selectItems value="#{listPubCategoryController.pubCategories}" var="category" itemLabel="#{category.name}" itemValue="#{category}" /> 
<a4j:ajax event="change" execute="@this" /> 
</h:selectOneMenu> 
<h:message for="pubCategoryId" style="color:red" /> 

Мой конвертер вызывается в оба раза. метод getAsString, когда я загружаю страницу и getAsObject, когда запускается действие on-change. Из этого я убеждаюсь, изменение действительно возвращается к серверу. Но - снова - он никогда не запускает метод setter.

@ManagedBean(name = "pubCategoryConverterController") 
@FacesConverter(value = "pubCategoryConverter") 
//@Named 
public class PubCategoryConverter implements Converter { 
@Inject 
private PubCategoryRepository pubCategoryRepository; 

public PubCategoryConverter() { 
} 

// from page to backing bean 
@Override 
public Object getAsObject(FacesContext ctx, UIComponent component, 
     String value) { 

    PubCategory pubCat = pubCategoryRepository.getPubCategoryById(new Long(
      value)); 
    return pubCat; 
} 

// from backing bean to page 
@Override 
public String getAsString(FacesContext fc, UIComponent uic, Object o) { 
    PubCategory pubCat = ((PubCategory) o); 
    return pubCat.getId().toString(); 
} 
} 

Та же история, если я аннотировать конвертер с @Named вместо @ FacesConverter/@ ManagedBean. Любая подсказка или намекает кому-нибудь?

Использование JBoss 7.1.1, 4.3.3 RichFaces, JSF 2.0

+0

вы пытались с помощью '' вместо ''? – Daniel

+0

Nope. Пробовал это раньше. Не имеет никакого значения. То же поведение: проходит через все стороны JSF, но НЕ запускает метод setter. (спасибо в любом случае за ваши отзывы) – feder

+1

у вас есть сообщения в журнале сервера, я имею в виду, попробуйте добавить id к этому 'h: message', например:' 'и визуализируйте его с помощью ' – Daniel

ответ

2

Я подключил фазовый прослушиватель и напечатал event.getFacesContext().getMessageList(). И, есть ошибка, хотя и не напечатана на <h:Message for="pubCategoryId"/>. Ошибка msg j_idt18:pubFormE:pubCategoryId: Validation Error: Value is not valid

package com.foo; 

import java.util.List; 
import java.util.logging.Logger; 
import javax.faces.event.PhaseEvent; 
import javax.faces.event.PhaseListener; 
import javax.faces.application.FacesMessage; 
import javax.faces.context.FacesContext; 

public class PhaseTracker implements PhaseListener { 

    private static final Logger logger = Logger.getLogger("org.exadel.helper"); 

    public void beforePhase(PhaseEvent e) { 
     List<FacesMessage> msgs = e.getFacesContext().getMessageList(); 
     for (FacesMessage msg : msgs) { 
      logger.info("before msg " + msg.getSummary() + " :: " + msg.getDetail()); 
     } 
     logger.info("BEFORE " + e.getPhaseId()); 
    } 

    public void afterPhase(PhaseEvent e) { 
     logger.info("AFTER " + e.getPhaseId()); 
    } 
} 

проблема связана с методом equals(Object o) в пределах объектной модели (некоторые называют, что DTO). Как указано во многих форумах, значения, которые вы сравниваете в рамках этого метода, не должны выглядеть, например. this.id == o.id, поскольку он сравнивает экземпляры не с внутренним состоянием. Вместо этого используйте равные this.id.equals(o.id). Как только это исправлено, ошибка Value is not valid исчезнет.

В конце концов, я заметил следующее. Если вы хотите использовать selectOneMenu с атрибутом тега converter вместо <f:converter ../>, например. ...

<h:selectOneMenu value="#{pubController.pubCategory}" converter="#{pubCategoryConverterController}"> 

... Вам нужно аннотировать конвертер также как @ManagedBean, например, в дополнение к @FacesConverter, например,

@ManagedBean(name="pubCategoryConverterController") 
@FacesConverter(value = "pubCategoryConverter") 

С другой стороны, если вы хотите использовать <f:converter converterId="pubCategoryConverter"> тег, вы должны ссылаться на имя лица преобразователя - не экземпляр управляемого компонента. Обратите внимание, что нет имени EL # {...} вокруг имени конвертера. Однако в этом случае вы НЕ МОЖЕТЕ вставлять компонент в ваш конвертер. Как следствие, в вашем компоненте конвертера вам необходимо создать экземпляр контроллера из контекста приложения, чтобы использовать службы EJB. например

PubCategoryController pubCategoryController = ctx.getApplication().evaluateExpressionGet(ctx, "#{pubCategoryController}", PubCategoryController.class); 
+1

Вы должны удалить аннотацию '@ FacesConverter', чтобы использовать ее так. Это не нужно. –

+0

Правда. Это улучшение. – feder

2

Преобразователь вызывается в фазе "Process Validations" из JSF lifecycle, тогда как связующий вызывается позже, во время фазы "Обновить" Model Values , Каждая фаза проходит через всю страницу, что означает ошибку проверки в любой компонент предотвратит все обновления модели. Если вы не видя ошибки проверки на странице, попробуйте проверить свои теги сообщений.

Пропуск фаз жизненного цикла осуществляется по телефону FacesContext.renderResponse(). См. UIInput.executeValidate() и LifeCycleImpl.execute().

Смежные вопросы