Spring MVC with JPA databinding
hibernate, java, jpa, spring
Solution
Spring automatically binds simple object types like String and Number, but for complex objects like `java.util.Date` or your own defined types, you will need to use what is called a `PropertyEditors` or `Converters`, both could solve your problem.
Spring already has a predefiend `PropertyEditors` and `Converters` like @NumberFormat and @DateTimeFormat
You can use them directly on your fields like this
public class Child {
@DateTimeFormat(pattern="dd/MM/yyyy")
private Date birthday;
@DateTimeFormat(iso=ISO.DATE)
private Date graduationDay;
@NumberFormat(style = Style.CURRENCY)
private Integer myNumber1;
@NumberFormat(pattern = "###,###")
private Double myNumber2;
}
Spring also allows you to define your own type converters which you must use it combined with Spring `ConversionService`
For example if you have a `Color` class like this
public class Color {
private String colorString;
public Color(String color){
this.colorString = color;
}
}
You would define the color converter for example like this
public class StringToColor implements Converter<String, Color> {
public Color convert(String source) {
if(source.equal("red") {
return new Color("red");
}
if(source.equal("green") {
return new Color("green");
}
if(source.equal("blue") {
return new Color("blue");
}
// etc
return null;
}
}
To check more about converters check this, also check this to know the difference between `Converters` and `PropertyEditors`
Problem
My problem is with having Spring bind the data I get from a form to a JPA entity. The wierd part is, it works just fine if I do not look at the BindingResults. The BindingResults says there were binding errors when an empty string is passed in for the field graduation, but I know it does bind them correctly because when I don't check Hibernate updates the database perfectly. Is there a way to not have to write logic to circumnavigate the wrongly fired binding errors? ``` @Entity @Table(name="child") public class Child { @Id @Column(name="id") private Integer childId; @ManyToOne(fetch=FetchType.EAGER ) @JoinColumn(name="house", referencedColumnName="house") private House house; @NotNull() @Past() @Column(name="birthday") private Date birthday; @Column(name="graduation_date") private Date graduationDay; } ``` I have tried the following lines in a property editor to no avail ``` SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy"); registry.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); ``` Here is the method signature for the controller method Handling the request ``` @Controller @SessionAttributes(value="child") @RequestMapping(value="child") public class ChildModController { @RequestMapping(value="save-child.do", params="update", method = RequestMethod.POST) public @ResponseBody Map<String,?> updateChild( HttpServletRequest request, @Valid @ModelAttribute(value="child")Child child, BindingResult results) } ``` This is what I get from the BindingResult class as a message ``` 09:01:36.006 [http-thread-pool-28081(5)] INFO simple - Found fieldError: graduationDay, Failed to convert property value of type java.lang.String to required type java.util.Date for property graduationDay; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @javax.persistence.Column java.util.Date for value '; nested exception is java.lang.IllegalArgumentException ```