title: Spring ClassCastException with Generic Form Bean Class
body: <p>I'm trying to use a generic class as a Spring form backing bean, but end up with a ClassCastException when the Spring framework attempts to cast the Object into the actual type.</p>
  
  <p>On submission of the form, the following error occurs when attempting to call a method on the SrvRecord object (line 105, marked with comment):</p>
  
  <pre><code>java.lang.ClassCastException: java.lang.Object cannot be cast to com.[...].portal.entity.SrvRecord
          at com.[...].portal.controller.SrvController.add(SrvController.java:105)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
          at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
          at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
          at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
          at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
          at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
          at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
          at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
          at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
          at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
          at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
          at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
          at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:440)
          at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
          at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
          at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
          at org.mortbay.jetty.Server.handle(Server.java:326)
          at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
          at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
          at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
          at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
          at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
          at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
          at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
  </code></pre>
  
  <p>Form Bean:</p>
  
  <pre><code>public class RecordBean&lt;T&gt;
  {
  
      private T original;
      private T modified;
  
      public RecordBean()
      {
          super();
      }
  
      public RecordBean(T original)
      {
          this.original = original;
          this.modified = original;
      }
  
      public T getOriginal()
      {
          return original;
      }
  
      public void setOriginal(T original)
      {
          this.original = original;
      }
  
      public T getModified()
      {
          return modified;
      }
  
      public void setModified(T modified)
      {
          this.modified = modified;
      }
  
  }
  </code></pre>
  
  <p>Controller methods:</p>
  
  <pre><code>@RequestMapping(value = "new", method = RequestMethod.GET)
  public String add(Model model)
  {
      SrvRecord srvRecord = getSrvRecord();
  
      RecordBean&lt;SrvRecord&gt; record = new RecordBean&lt;SrvRecord&gt;(srvRecord);
      model.addAttribute("record", record);
  
      return "generic/new";
  }
  
  @RequestMapping(value = "new", method = RequestMethod.POST)
  public String add(Model model, @ModelAttribute("record") RecordBean&lt;SrvRecord&gt; record)
  {
      // Call a method on the SrvRecord object
      doSomething(record.getModified().getZone().getName());  // line 105
      doSomething(record.getOriginal().getZone().getName());
  
      // ...
  }
  </code></pre>
  
  <p>View:</p>
  
  <pre><code>&lt;c:url value="/edit" var="formUrl" /&gt;
  &lt;form:form commandName="record" action="${formUrl}"&gt;
      &lt;form:input type="hidden" path="original.zone" /&gt;
      &lt;form:input type="hidden" path="original.name" /&gt;    
      &lt;!-- ... --&gt;
  
      &lt;form:input path="modified.zone" /&gt;&lt;br /&gt;
      &lt;form:input path="modified.name" /&gt;&lt;br /&gt;
      &lt;!-- ... --&gt;
  &lt;/form:form&gt;
  </code></pre>
  
  <p>Any thoughts or suggestions would be great. Being able to work with the generic form bean will eliminate a large amount of unnecessary code from the baseline.</p>
  
  <p>Just for reference, the Spring version being used is 3.0.6.RELEASE.</p>
  
  <p>Thanks,
  Beau</p>