1

我只是试图更改选择输入框的值。加载页面会进入 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 时触发 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、Richfaces 4.3.3、JSF 2.0

4

2 回答 2

3

转换器在JSF 生命周期的“流程验证”阶段 被调用,而设置器在稍后的“更新模型值”阶段被调用。每个阶段都会遍历整个页面,这意味着任何组件中的验证错误都会阻止所有模型更新。如果您没有在页面上看到验证错误,请尝试检查您的消息标签。

通过调用FacesContext.renderResponse()跳过生命周期阶段。有关详细信息,请参阅UIInput.executeValidate()LifeCycleImpl.execute()

于 2013-09-01T15:00:14.923 回答
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,因为它比较的是实例而不是内部状态。改用 equals this.id.equals(o.id)。一旦修复,错误Value is not valid就会消失。

毕竟,我注意到以下内容。如果您想使用带有标签属性的 selectOneMenuconverter而不是<f:converter ../>,例如 ...

<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 服务。例如

PubCategoryController pubCategoryController = ctx.getApplication().evaluateExpressionGet(ctx, "#{pubCategoryController}", PubCategoryController.class);
于 2013-09-01T17:46:31.437 回答