我正在使用JSF/Primefaces创建一个表单来允许用户输入数据。我定义了一个泛型类Input
以允许访问数据(因为不同的字段具有不同的类型(。但是,当我尝试从声明为 Input<Double>
的对象中检索数据时,我收到异常 java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
我有点困惑为什么会发生这种情况,因为存储在Input
中的值应该是双精度值?如果有人能指出我正确的方向,导致这种情况的原因,我将不胜感激。
憨豆.java
@ManagedBean(name="form", eager=true)
@SessionScoped
public class FormBean {
private Input<String> name = new Input<>();
private Input<Date> date = new Input<>();
private Input<Double> hours = new Input<>();
private Input<Double> amount = new Input<>();
public void submit(){
System.out.println(name.getValue());
System.out.println(parseDate(date.getValue(),"dd/MM/yy"));
System.out.println(formatDouble(hours.getValue()));
System.out.println(formatDouble(amount.getValue()));
}
public static String parseDate(Date date, String format){
if(date == null) return "";
DateFormat df = new SimpleDateFormat(format);
return df.format(date);
}
public static String formatDouble(Double d){
if(d==null) return "";
else return String.format("%.2f", (double)d);
}
//-------------------GETTERS AND SETTERS----------------------------
public Input<String> getName() {
return name;
}
public Input<Date> getDate() {
return date;
}
public Input<Double> getHours() {
return hours;
}
public Input<Double> getAmount() {
return amount;
}
}
输入.java
public class Input<T> {
private T value;
private String styleClass = "inputdefault";
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public String getStyleClass() {
return styleClass;
}
public void setStyleClass(String styleClass) {
this.styleClass = styleClass;
}
}
形式.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<ui:define name="title">Form</ui:define>
</h:head>
<h:body>
<h:form id="form">
<p:panelGrid id="formGrid" style="text-align:center;margin:20px;" columns="2" layout="grid">
<h:outputText class="output" value="Name"/>
<p:inputText id="name" class="#{form.name.styleClass}" value="#{form.name.value}"/>
<h:outputText class="output" value="Date:"/>
<p:calendar class="#{form.date.styleClass}" value="#{form.date.value}" pattern="dd/MM/yy"/>
<h:outputText class="output" value="Hours:"/>
<p:inputNumber id="hours" class="#{form.hours.styleClass}" value="#{form.hours.value}" decimalPlaces="2"/>
<h:outputText class="output" value="Amount:"/>
<p:inputNumber class="#{form.amount.styleClass}" value="#{form.amount.value}" decimalPlaces="2"/>
</p:panelGrid>
<p:commandButton value="Submit" update="@form" action="#{form.submit}" class="left"/>
</h:form>
</h:body>
</html>
错误发生在 FormBean 中 submit()
方法的第 13 行.java:System.out.println(formatDouble(amount.getValue()));
如果需要任何其他信息,请告诉我。谢谢!
编辑:添加了堆栈跟踪:
Jun 12, 2017 1:10:55 PM com.sun.faces.lifecycle.InvokeApplicationPhase execute
WARNING: #{form.submit}: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
javax.faces.FacesException: #{form.submit}: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
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.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: javax.faces.el.EvaluationException: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
... 26 more
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
at FormBean.submit(FormBean.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
... 27 more
Jun 12, 2017 1:10:55 PM com.sun.faces.context.AjaxExceptionHandlerImpl handlePartialResponseError
SEVERE: javax.faces.el.EvaluationException: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
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.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.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
at FormBean.submit(FormBean.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
... 27 more
我认为问题无法在代码的和平中找到。在您预期异常时,Bean 只是第一次访问 Bean 属性。JSF 正在尝试调用 Input.setValue(Double double(,但从 jsf 控件中产生的值是一个字符串。所以我认为这里抛出了例外。
为了确保安全,请发布异常的堆栈跟踪。
该问题的解决方案是为控件配置值转换器。
http://download.oracle.com/otn_hosted_doc/jdeveloper/j2ee101302/jsf_apps/eventvalidate/sf_avc_converters.html
另一种解决方案是将原始值存储为输入类中的字符串,并在调用方法以获取转换后的值(而不是 getter-method(时将其转换为目标类型