小编Mar*_*ler的帖子

如果仅更改了比例,则不会调用BigDecimal值的ValueChangeListener

我有一个JSF 2.2应用程序,用户必须输入BigDecimal<h:inputText>.对于这样的输入字段,a valueChangeListener被配置为在输入变化时被调用.这是XHTML代码:

<h:form id="theForm">
  <h:inputText id="bd" value="#{bean.bd}"
               valueChangeListener="#{bean.bdChangedListener()}"/>
  <h:commandButton id="submit" value="Submit" />
</h:form>
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,这样做很好.bdChangedListener()当值改变并按下提交按钮时,将调用该方法.该值已正确提交给模型.

但是,如果我进入1.1并改变它1.10,新的值被提交到模型,但valueChangeListener从来没有所谓!Debuging表明,其原因在于javax.faces.component.UIInput#compareValues().这种方法的JavaDoc 说:

如果新值与先前值不同,则返回true.首先通过将值传递给参数previous之前的equals方法来比较这两个值.如果该方法返回true,则返回true.如果该方法返回false,并且两个参数都实现java.lang.Comparable,则通过将值传递给参数previous之前的compareTo方法来比较这两个值.如果此方法返回0,则返回true,否则返回false.

所以在我看来,这是故意的.但为什么?

用户输入已更改,并且存在应用程序,其中a的比例BigDecimal是相关的.所以JSF不应该忽略改变的输入,而是通知我!它使用新值更新模型,为什么它会跳过valueChangeListener-method?

我怎样才能避免这种行为并以干净的方式得到通知?(我知道我可以挂进制定者,但这不是我所谓的干净方式!)

有任何想法吗?

进一步阅读和评论

除了上面我想提到的,我已经读过像BigDecimal equals()和compareTo()这样的问题.我确实理解为什么BigDecimal equals()compareTo()他们的行为一样,我说它是正确的.BigDecimal的行为不是问题,UIInput.compareValues()而是问题.

此外,转换器(如评论或已删除的答案中所示)将无法保存我的一天.用户输入已正确转换,我需要BidDecimal,包括我的应用程序中的确切比例.任何返回BigDecimal的转换器都不会改变观察到的行为.

围绕BigDecimal的包装类可能会解决我的问题,但不是我认为的干净解决方案.我真的想知道为什么UIInput的行为方式.

jsf

10
推荐指数
1
解决办法
287
查看次数

为什么<o:validateAll>的行为与其他验证器不同?

我使用OmniFaces的<o:validateAll>验证器来验证许多输入组件.只要我没有将它放入RichFaces <rich:tabPanel>,这就可以正常工作.当我这样做并将字段留空时,验证失败(如预期的那样),但无论验证失败,活动选项卡都会更改.我试过的其他验证器会tabPanel在验证失败时阻止切换到另一个选项卡.

这可能是什么原因?

我目前在Wildfly 9.0.2上使用OmniFaces 2.1和RichFaces 4.5.17.Final与Mojarra 2.2.12.

以下是重现问题的XHTML代码:

<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:f="http://xmlns.jcp.org/jsf/core"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:o="http://omnifaces.org/ui"
                xmlns:rich="http://richfaces.org/rich">

    <h:form id="form">

      <rich:messages />

      <rich:tabPanel id="tabPanel">

        <rich:tab id="tab1" header="Tab 1">
          <h:inputText id="myDouble" value="#{someDoubleVal}">
            <f:validateDoubleRange minimum="1.0" maximum="2.0"/>
          </h:inputText>
          <o:validateAll id="allValid" components="myDouble" message="Missing value!" />
        </rich:tab>

        <rich:tab id="tab2" header="Tab 2">
          Just another tab to switch.
        </rich:tab>

      </rich:tabPanel>

    </h:form>

</ui:composition>
Run Code Online (Sandbox Code Playgroud)

输入1.0和2.0之外的值并尝试切换到选项卡2以查看预期行为,由<f:validateDoubleRange>以下各项触发:显示faces-message并且第一个选项卡仍处于活动状态.

将输入留空并尝试切换到选项卡2以查看以下行为<o:validateAll>:验证似乎失败(显示面部消息),但激活了选项卡2.

更新:所描述的行为适用于switchType="ajax"(默认)以及switchType="server".在这两种情况下,选项卡面板都会执行所包含输入的提交,因此从用户的角度来看,选项卡切换似乎与<h:commandButton>提交相同(技术上可能存在差异,我不知道实现选项卡面板的详细信息).

如果我通过定期执行制表开关<h:commandButton><f:setPropertyActionListener>,所述<o:validateAll>的行为相同的方式,其他的验证,即,在制表开关不会由于验证错误执行.

<rich:tabPanel …
Run Code Online (Sandbox Code Playgroud)

validation jsf richfaces omnifaces

5
推荐指数
1
解决办法
157
查看次数

带有 OmniFaces validateAll 的 PrimeFaces PickList 导致 NullPointerException

我真正想要的是两个PrimeFaces<p:pickList>,它们通过OmniFaces 的<o:validateAll>组件进行验证。请注意,验证pickList<o:validateAll>有一个问题,可以按照OmniFaces 问题跟踪器中的问题488中的描述解决该问题。

因此,我的需求的一个非常简单的示例如下所示:

<h:form id="form1">
  <p:messages id="messages">
    <p:autoUpdate/>
  </p:messages>

  <p:pickList id="pick1" value="#{dummy.dualListModel}"
              var="item" itemLabel="#{item}" itemValue="#{item}">
    <p:ajax event="transfer"/>
  </p:pickList>

  <p:pickList id="pick2" value="#{dummy.dualListModel2}"
              var="item" itemLabel="#{item}" itemValue="#{item}">
    <p:ajax event="transfer"/>
  </p:pickList>

  <o:validateAll id="validPicks" components="pick1 pick2"
                 message="all values required!" />

  <h:commandButton id="done" value="Done" action="#{dummy.action1}"/>
</h:form>

<h:form id="theOtherForm">
  <h:commandButton id="otherFormAction" value="Action in other form"
                   action="#{dummy.action2}"/>
</h:form>
Run Code Online (Sandbox Code Playgroud)

后面的虚拟backing-bean 只为这两个dualListModel属性和什么都不做的动作方法提供 getter/setter 。

当我运行此代码并至少保留一个 pickList 为空时,提交Done-button 会导致验证失败作为例外。但是,单击按钮,在其他形式的后验证失败,导致一NullPointerExceptionPickListRenderer …

jsf primefaces omnifaces

5
推荐指数
1
解决办法
377
查看次数

如何对将在JSF输出中本地化的列表进行排序

在我的应用程序中,我有一个键(字符串)列表,用户可以在其中选择其中一个.在用户界面中,将根据当前区域设置输出密钥:

<h:selectOneMenu value="#{bean.selectedKey}">
  <f:selectItems value="#{bean.allKeys}" var="_key" itemLabel="#{msgs[_key]}" />
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)

我的设置使用配置的标准资源包,faces-config.xml如BalusC 在本回答中所述.msgs在上面的示例中是资源包变量的名称.

我现在selectOneMenu想要的是,要按字母顺序排序的项目.当然,顺序取决于使用的区域设置.问题是,我不能/不会在backing-bean中进行排序,因为我不知道JSF页面将如何输出密钥.

这个问题对我来说似乎很通用,所以我想知道解决这类问题的最佳做法是什么.

(当然问题不仅适用于selectOneMenu.任何将在用户界面中输出的列表/集合都会遇到同样的问题.)

sorting jsf localization resourcebundle

4
推荐指数
1
解决办法
3996
查看次数

使用 JDK 17 通过 JSF/EL 访问 ZoneInfo 时出现 IllegalAccessException

在将大型 JEE8 应用程序移植到 Java 17 时,我IllegalAccessException在渲染一个简单的 EL 表达式时偶然发现了一个:#{myWarBean.defaultTZ.rawOffset}。我设法在github 上的 SSCCE中重现了该问题。当您在 Wildfly 应用程序服务器(我使用的是 26.1.1.Final)上运行应用程序时,您会得到以下堆栈跟踪:

SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-1) Error Rendering View[/index.xhtml]: javax.el.ELException: /index.xhtml @23,74 value="raw offset=#{myWarBean.defaultTZ.rawOffset}": java.lang.IllegalAccessException: class javax.el.BeanELResolver cannot access class sun.util.calendar.ZoneInfo (in module java.base) because module java.base does not export sun.util.calendar to unnamed module @6a1cb0de
    at com.sun.jsf-impl@2.3.17.SP01//com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:77)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:181)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.UIOutput.getValue(UIOutput.java:140)
    at com.sun.jsf-impl@2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:198)
    at com.sun.jsf-impl@2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:328)
    at com.sun.jsf-impl@2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:143)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:600)
    at com.sun.jsf-impl@2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:286)
    at com.sun.jsf-impl@2.3.17.SP01//com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:90)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:571)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1648)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1651)
    at javax.faces.api@3.1.0.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1651) …
Run Code Online (Sandbox Code Playgroud)

jsf el java-module java-17

3
推荐指数
1
解决办法
1335
查看次数