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