JSF组件绑定没有bean属性抛出转换错误

时间:2016-09-16 07:24:43

标签: jsf jsf-2 el

在表的一列中,我试图将组件值绑定到本地范围的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)

我正在使用Glassfish 4.1.1和JSF 2.2.12版。

我很感激任何想法

CLARIFACATION

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

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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