【问题标题】:JSF component binding without bean property throwing conversion error没有bean属性的JSF组件绑定抛出转换错误
【发布时间】:2016-09-16 07:24:42
【问题描述】:

在表格的一列中,我尝试将组件值绑定到局部范围的 EL 变量,然后将该变量用作参数:

        <h:column>
            <h:outputLabel value="Enter a quantity to put into the cart" for="qty"/>
            <h:inputText id="qty" binding="#{qty}" converter="javax.faces.Number"/>
        </h:column>
        <h:column>
            <h:commandButton value="Put into cart" type="submit"
                             action="#{shoppingCart.addToCart(product, qty)}"/>
        </h:column>

其中product 是数据表的当前元素(不在购物车中的已过滤或未过滤产品的列表)。

现在,当尝试将产品添加到购物车(例如数量为 12)时,它会引发以下异常:

javax.faces.el.EvaluationException: java.lang.IllegalArgumentException: Cannot convert javax.faces.component.html.HtmlInputText@377c8b02 of type class javax.faces.component.html.HtmlInputText to class java.lang.Integer
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIData.broadcast(UIData.java:1108)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)

我正在使用带有 JSF 2.2.12 版的 Glassfish 4.1.1。

如有任何想法,我将不胜感激

澄清

正如 BalusC 在这个问题 JSF component binding without bean property 和其他人中指出的那样,binding="#{var}" 实际上是有效的 XHTML。这样就不需要支持 bean,并且声明的变量是请求范围的。我发现这个选项更优雅,因此想坚持下去。

【问题讨论】:

  • 为什么您认为不需要支持 bean 是一种优势?事实上,我无法想象您的购物车中没有“产品”类,其成员字段为“数量”或类似字段,因此“支持 bean”已经存在
  • 我已经更正了。它实际上是关于创建一个新的 ShoppingCartItem。很抱歉有模棱两可的问题

标签: jsf jsf-2 el


【解决方案1】:

而不是binding="#{qty}"(它应该用于将您的输入组件绑定到托管bean 中组件的Java 实例),使用:value="#{shoppingCart.quantityAsInteger}",或者如果您正在处理购物车项目列表: value="#{shoppingCartItem.quantityAsInteger}".

除了正确的值绑定之外,这还将使您受益于将数量作为模型的一部分。此外,当value 绑定到Integer 时,无需添加转换器。 JSF 会处理Integer (and some other types) conversion by default

因此,请确保您有一个包含数量的托管 bean 或每个都有数量的购物车项目列表。如果是购物车物品列表,您最终会得到如下内容:

ShoppingCart.java

// You will probably already have something like this for your table
private List<ShoppingCartItem> shoppingCartItems;

ShoppingCartItem.java

// Quantity used for binding (add getter and setter).
private Integer quantity;

private Product product;

XHTML

<h:column>
    <h:outputLabel value="Enter a quantity to put into the cart" for="qty"/>
    <h:inputText id="qty" binding="#{shoppingCartItem.quantity}" />
</h:column>

【讨论】:

  • 谢谢 :) 我不能使用 binding="#{shoppingCartItem.quantity}" 因为目前没有商品。我的意思是一个对象仅在单击 commandButton 后创建,因此我无法在该项目创建之前为其指定一个值。还是我误会了?
  • 对不起,您可以在Product 中添加一个数量整数来添加产品。正如您已经发现的那样,您的问题的核心是您应该使用 value 进行值绑定。
  • 在这种情况下,使用value="#{product.quantity}"action="#{shoppingCart.addToCart(product)}"
【解决方案2】:

尝试在h:inputText 中使用value 属性而不是binding 属性,并在表格组件上使用binding 属性。这样您就可以在操作方法中访问选定(单击)的行:如果表的binding 属性值为#{bean.dataTable},则可以通过getDataTable.getRowData() 之类的方法获取行数据。

【讨论】:

    【解决方案3】:

    虽然声明 EL 变量是有效的 XHTML,但如果使用 binding 属性,组件本身将绑定到变量。使用带有value 属性的EL 变量时不会引发转换错误,如下所示:

            <h:inputText id="qty" value="#{qty}" converter="javax.faces.Number"/>
            ....
            <h:commandButton value="Put into cart" type="submit"
                             action="#{shoppingCart.addToCart(product, qty)}"/>
    

    【讨论】:

    • 我就是这么告诉你的 ;-)
    • @JasperdeVries:不完全......他在这里定义了一个 requestScoped 变量,它不是 bean 中的字段。它仅在请求期间存在。与您的示例略有不同。另请参阅他对问题的“编辑/澄清”
    • 对.. 现在我明白了。我以为是关于编辑购物车的!
    • 我也认为它是关于编辑购物车的。但是以不寻常的方式编辑它,并且“优化”不是优化...
    猜你喜欢
    • 2011-12-31
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多