JSF component binding without bean property throwing conversion error

﹥>﹥吖頭↗ 提交于 2019-12-11 05:08:39

问题


In a column of a table I've tried to bind a component value to a local scoped EL variable and later on to use that variable as a paramter:

        <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>

Where product is the current element of the datatable (a list of filtered or unfiltered products that are not in the cart).

Now when trying to add a product to the cart (e.g. with the quantity 12) it throws the following exception:

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)

I'm using Glassfish 4.1.1 with JSF version 2.2.12.

I'd be grateful for any ideas

CLARIFACATION

As pointed out by BalusC in this question JSF component binding without bean property and others, binding="#{var}" is actually valid XHTML. This way no backing bean is needed and the declared variable is request scoped. I find this option more elegant and hence would like to stick with it.


回答1:


Instead of binding="#{qty}" (which should be used to bind your input component to a Java instance of your component in a managed bean), use: value="#{shoppingCart.quantityAsInteger}", or if you are working with a list of shopping cart items: value="#{shoppingCartItem.quantityAsInteger}".

Apart from proper value binding this will also give you the benefit of having the quantity as part of your model. Additionally, when the value is bound to an Integer, there is no need to add a converter. JSF will take care of Integer (and some other types) conversion by default.

So, make sure you have a managed bean containing the quantity or a list of cart items which each have a quantity. In case of a list of cart items, you will end up with something like:

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>



回答2:


Try using value attribute instead of binding attribute in h:inputText and use binding attribute on a table component. That way you can access to the selected (clicked) row in a action method: if binding attribute of a table has value #{bean.dataTable}, you can get row data in a method like getDataTable.getRowData().




回答3:


Though declaring an EL variable is valid XHTML, the component itself is bound to the variable, if using the binding attribute. No conversion errors are thrown when using the EL variable with the value attribute, like that:

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


来源:https://stackoverflow.com/questions/39525911/jsf-component-binding-without-bean-property-throwing-conversion-error

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!