Uploaded image for project: 'Spring Data Commons'
  1. Spring Data Commons
  2. DATACMNS-517

DataBinding fails when nested entity implements Serializable

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Minor
    • Resolution: Cannot Reproduce
    • Affects Version/s: 1.5.2, 1.7.2 (Codd SR2), 1.8 GA (Dijkstra)
    • Fix Version/s: None
    • Component/s: Core
    • Sprint:
      48 - Dijkstra GA, 49 - Dijkstra SR1, 50 - Evans M1, 51 - Dijkstra SR2

      Description

      Input:
      http://localhost/foo?name=MyFoo&bar.name=MyBar

      Expected result:

      {
        "name" : "MyFoo",
        "bar" : {
          "name" : "MyBar"
        }
      }
      

      Actual result:

      Field error in object 'foo' on field 'bar': rejected value [org.sample.core.Bar@0]; codes [typeMismatch.foo.bar,typeMismatch.bar,typeMismatch.org.sample.core.Bar,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [foo.bar,bar]; arguments []; default message [bar]]; default message [Failed to convert property value of type 'org.sample.core.Bar' to required type 'org.sample.core.Bar' for property 'bar'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type org.sample.core.Bar to type @javax.persistence.ManyToOne org.sample.core.Bar for value 'org.sample.core.Bar@0'; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Provided id of the wrong type for class org.sample.core.Bar. Expected: class java.lang.Long, got class org.sample.core.Bar; nested exception is java.lang.IllegalArgumentException: Provided id of the wrong type for class org.sample.core.Bar. Expected: class java.lang.Long, got class org.sample.core.Bar]
      org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
      Field error in object 'foo' on field 'bar': rejected value [org.sample.core.Bar@0]; codes [typeMismatch.foo.bar,typeMismatch.bar,typeMismatch.org.sample.core.Bar,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [foo.bar,bar]; arguments []; default message [bar]]; default message [Failed to convert property value of type 'org.sample.core.Bar' to required type 'org.sample.core.Bar' for property 'bar'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type org.sample.core.Bar to type @javax.persistence.ManyToOne org.sample.core.Bar for value 'org.sample.core.Bar@0'; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Provided id of the wrong type for class org.sample.core.Bar. Expected: class java.lang.Long, got class org.sample.core.Bar; nested exception is java.lang.IllegalArgumentException: Provided id of the wrong type for class org.sample.core.Bar. Expected: class java.lang.Long, got class org.sample.core.Bar]
      	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:112) ~[spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE]
      

      The players:

      Foo.java
      @Entity public class Foo implements Serializable {
      	@Id	@GeneratedValue(strategy = GenerationType.AUTO)
      	private Long id;
      	private String name;
      	@ManyToOne	private Bar bar;
      
      	public Long getId() { return id; 	}
      	public void setId(Long id) { this.id = id; }
      	public Bar getBar() { return bar; }
      	public void setBar(Bar bar) { this.bar = bar; }
      	public String getName() {	 return name; }
      	public void setName(String name) { this.name = name;}
      }
      
      Bar.java
      @Entity public class Bar *implements Serializable* {
      	@Id @GeneratedValue(strategy = GenerationType.AUTO)
      	private Long id;
      	private String name;
      	public Long getId() { return id; 	}
      	public void setId(Long id) { this.id = id; }
      	public String getName() { return name; }
      	public void setName(String name) { this.name = name; }
      }
      
      SampleController.java
      @Controller @RequestMapping("/") public class SampleController {
          @ResponseBody
          @RequestMapping(value = "/foo", method = RequestMethod.GET)
          public Foo searchFoo(Foo foo) {
              return foo;
          }
      }
      

      The victim:
      If you remove the "implements Serializable" from Bar you get the correct expected behavior.

      Final comments:
      In this particular case, I don't wan the DomainClassConverter to kick in, as explained in reference documentation section 1.4. I just want vanilla data binding, but for some reason the DomainClassConverter gets confused.
      For example, If I remove spring data's magic by removing the @EnableSpringDataWebSupport annotation in my setup, conversion works as expected.

        Attachments

          Activity

            People

            Assignee:
            thomasd Thomas Darimont
            Reporter:
            krause Pablo Krause
            Last updater:
            Oliver Drotbohm
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: