Jsf 如何让空输入组件的自定义非空值dispite解释\u empty\u STRING\u SUBMITTED\u VALUES\u为\u null=true

Jsf 如何让空输入组件的自定义非空值dispite解释\u empty\u STRING\u SUBMITTED\u VALUES\u为\u null=true,jsf,primefaces,Jsf,Primefaces,在我的faces config.xml中,我设置了 <context-param> <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name> <param-value>true</param-value> </context-param> 我尝试使用一个转换器,在呈现组件时,当从{myBean.someDat

在我的
faces config.xml
中,我设置了

<context-param>
 <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
 <param-value>true</param-value>
</context-param>
我尝试使用一个转换器,在呈现组件时,当从
{myBean.someDate}
接收到我的自定义值时,组件在
getAsString()
中返回一个
空字符串,或者在
null
或提交纯空值时,在
getAsObject()
中吐出我的自定义值:

import java.util.Date;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.DateTimeConverter;
import javax.faces.convert.FacesConverter;

@FacesConverter("mySpecialDateConverter")
public class MyConverter extends DateTimeConverter {

    private static final Date PAST = new Date(0);

    public MyConverter() {
        setPattern("MM/dd/yyyy");
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (PAST.equals(value)) {
            return "";
        }
        return super.getAsString(context, component, value);
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (null == value || "".equals(value.trim())) {
            return PAST;
        }
        return super.getAsObject(context, component, value);
    }

}
当bean属性等于
pass
时,呈现空日历组件的效果与预期相同。但是在没有输入的情况下提交日历会将属性设置为
null
,因为Primefaces
CalendarRenderer
在提交空白值时根本不咨询
转换器

package org.primefaces.component.calendar;

public class CalendarRenderer extends InputRenderer {
    // ...
    public Object getConvertedValue(FacesContext context, UIComponent component, Object value) throws ConverterException {
        Calendar calendar = (Calendar) component;
        String submittedValue = (String) value;
        SimpleDateFormat format = null;

        if (isValueBlank(submittedValue)) {
            return null;
        }

        //Delegate to user supplied converter if defined
        try {
            Converter converter = calendar.getConverter();
            if (converter != null) {
                return converter.getAsObject(context, calendar, submittedValue);
            }
        }
        // ...
    }
    // ...
}
这部分是正常的,正如
Converter.getAsObject()
上的JavaDoc所说:

/** 
 * @return <code>null</code> if the value to convert is <code>null</code>, 
 * otherwise the result of the conversion 
 */
因此,Primefaces没有理由解析空输入上的转换器。如果我们将
javax.faces.exploration\u EMPTY\u STRING\u SUBMITTED\u VALUES\u设置为\u NULL=false,则情况会有所不同。那么我认为上面的行为不正确,如<代码> >“<代码>不是<代码> null <代码> > 

为了完整起见,这是my bean又名
myBean

import java.io.Serializable;
import java.util.Date;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class MyBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private Date someDate;

    public Date getSomeDate() {
        return someDate;
    }

    public void setSomeDate(Date someDate) {
        this.someDate = someDate;
    }

}
我不想对该bean进行更改,因为在实际应用程序中,日历的值绑定到持久化的实体属性值。我也不想让持久层做这项工作

背景:


我想在一些数据库
DATE
字段中防止
null
值。例如,在周期的情况下,我希望开始默认值为应用程序上下文中不相关的某个遥远过去的日期,对于该周期的结束,我希望在遥远的将来的日期与应用程序上下文中不相关,并且两者都不必打扰用户默认的日期。这些默认日期有助于筛选当前
日期
在该期间之内或之外的实体,虽然用户的任何输入都不会被假定为永久的

期间,但JSF组件不会在null值或任何他们认为为null的值上调用转换器-对于JSF中的默认组件也是如此。因此,在这方面,我猜PrimeFaces的表现与预期相符,这是正确的结果。这里有两种方法可以避免这种情况,它们会立即浮现在脑海中

使用全方位 如中所述,OmniFaces
o:param
将调用转换器,而不考虑空值-您可以使用它将参数传递给组件。在你的具体情况下,你应该能够做类似的事情

<h:form id="myForm">
        <p:calendar value="#{myBean.someDate}" pattern="MM/dd/yyyy" locale="en" />
        <p:commandButton value="send" process="@form" update="@form">
            <o:param name="date" value="#{myBean.someDateConversion}"
                     converter="mySpecialDateConverter" /> 
        </p:commandButton>
        <hr />
        <h:outputText value="#{myBean.someDate}" />
</h:form>


使用自定义渲染器
第二个选项是使用自定义渲染器,只需修改组件的行为以始终调用转换器,如本答案中所述-。

感谢您的帮助-o:param似乎只使用转换器处理输出方向,以便通过
converter.getAsString()获得正确的字符串
用于已对我有效的渲染。它似乎没有通过
Converter.getAsObject()
将提交的值从用户输入导入bean属性。所以你认为我必须覆盖渲染器?你的两个链接都有相同的目标URL。顺便说一句@Selaron对此表示抱歉。修改了第二个链接。对于处理空输入,这两种方法都应该适用于您的目的<显然,code>o:param
不会调用getAsObject(),而是在它调用的setter方法中处理这个问题,并从父组件读取这个值。这是一种“强制”转换的简单方法。根据您的目标,您甚至可能不必在o:param中使用转换器-仅使用正常的
f:param
f:attribute
可能工作得很好。@Selaron和回答您的问题-真正依赖并确保JSF为您调用转换器-据我所知,您必须尽可能修改它的行为如上所述。另一个选项是解决这个问题,如前所述。我最终创建了一个自定义渲染器,它以类似于中所述的方式覆盖
CalendarRenderer.getConvertedValue
。非常感谢。
<h:form id="myForm">
        <p:calendar value="#{myBean.someDate}" pattern="MM/dd/yyyy" locale="en" />
        <p:commandButton value="send" process="@form" update="@form">
            <o:param name="date" value="#{myBean.someDateConversion}"
                     converter="mySpecialDateConverter" /> 
        </p:commandButton>
        <hr />
        <h:outputText value="#{myBean.someDate}" />
</h:form>