我只是尝试更改选择输入框的值。加载页面会运行到pubcategory属性的getter方法的断点。目前很好。更改值,不会调用setter方法。我触发Richfaces ajax处理。我确认,所有JSF阶段都已完成(我还看到了JPA-SQL选择查询,我希望在这里可以使用更新语句来更改值 - 好吧,如果没有触发setter方法,则不能这样做)。这是我的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。从此我得知,改变真的回到了服务器。但是 - 再次 - 它永远不会触发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,Richfaces 4.3.3,JSF 2.0
答案 0 :(得分:2)
转换器在&#34;过程验证&#34; JSF lifecycle的阶段,而稍后在&#34;更新模型值&#34;期间调用setter。相。每个阶段都会遍历整个页面,这意味着任何组件中的验证错误都会阻止所有模型更新。如果您不在页面上看到验证错误,请尝试检查邮件标记。
通过调用FacesContext.renderResponse()来跳过生命周期阶段。有关详细信息,请参阅UIInput.executeValidate()和LifeCycleImpl.execute()。
答案 1 :(得分: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
就会消失。
毕竟,我注意到了以下内容。如果您想使用带有标记属性converter
而非<f:converter ../>
的selectOneMenu,例如...
<h:selectOneMenu value="#{pubController.pubCategory}" converter="#{pubCategoryConverterController}">
...除了@ManagedBean
之外,您还需要将转换器注释为@FacesConverter
个实例,例如
@ManagedBean(name="pubCategoryConverterController")
@FacesConverter(value = "pubCategoryConverter")
另一方面,如果要使用<f:converter converterId="pubCategoryConverter">
标记,则需要引用faces转换器名称 - 不是托管bean的实例。请注意,转换器名称周围没有EL#{...}。但是,在这种情况下,您不能将bean注入转换器。因此,在转换器bean中,您需要从应用程序上下文实例化控制器才能使用EJB服务。 e.g。
PubCategoryController pubCategoryController = ctx.getApplication().evaluateExpressionGet(ctx, "#{pubCategoryController}", PubCategoryController.class);