0

I'm creating a form using JSF/Primefaces to allow a user to input data. I have defined a generic class Input to allow access to the data (as different fields have different types). However, when I try and retrieve data from an object declared as Input<Double> I get the exception java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double

I'm somewhat confused as to why this is happening as the value stored in Input should be a Double? If someone could point me in the right direction as to what's causing this I would be very grateful.

FormBean.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;
    }
}

Input.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;
    }
}

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

The error occurs at the line 13 in the submit() method in FormBean.java: System.out.println(formatDouble(amount.getValue()));

If there's any additional information needed please let me know. Thanks!

EDIT: Added Stacktrace:

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
Lucy Stevens
  • 185
  • 2
  • 9
  • in which line does the error occur? – Tom K Jun 12 '17 at 11:42
  • The error occurs at the line 13 in the submit() method in FormBean.java: `System.out.println(formatDouble(amount.getValue()));` – Lucy Stevens Jun 12 '17 at 11:46
  • what output do you get when you remove the double cast in `else return String.format("%.2f", (double)d);` ? – Tom K Jun 12 '17 at 12:07
  • I get the exact same error if I remove the double cast. – Lucy Stevens Jun 12 '17 at 12:11
  • Which of https://stackoverflow.com/questions/14521882/java-infering-wrong-type-of-a-typed-hashset or https://stackoverflow.com/questions/14521882/java-infering-wrong-type-of-a-typed-hashset is the best duplicate? The latter I assume – Kukeltje Jun 12 '17 at 13:31
  • @Kukeltje Thanks for posting that link, adding a a converter with the value `javax.faces.Double` solved the issue. Is it worth submitting that as an answer for future reference and then marking as duplicate? – Lucy Stevens Jun 12 '17 at 13:54

1 Answers1

0

I think the problem cannot be found in that peaces of code. At the point where you expect the exception the bean just access the bean attribute the first time. JSF is trying to call Input.setValue(Double double) but the value that is comming out of your jsf control is a string. So i think here the exception is thrown.

To be sure plz post the stacktrace of the exception.

The solution for that problem would be to configure a value converter for your control.

http://download.oracle.com/otn_hosted_doc/jdeveloper/j2ee101302/jsf_apps/eventvalidate/sf_avc_converters.html

Another solution would be to store the raw value as string in your input class and convert it into the target type when calling a method to get the converted value (not the getter-method)

maimArt
  • 389
  • 1
  • 11
  • I've posted the stacktrace and it seems that the error occurs only on that line when the `submit()` method tries to pass `amount.getValue()` to the `formatDouble()` method which accepts a Double. I've had a look at the PrimeFaces documentation and `` does return a Double. – Lucy Stevens Jun 12 '17 at 12:21