Data Binding
So, the Spring framework is a wonderful help for programmers, but sometimes it needs a bit of help. It does a good job of trying to match fields on a webpage to Java objects (aka Java Beans), but sometimes when the “mapping” is complex, Spring needs our help.
Consider this situation:
You've got two fields here that aren't out of the ordinary username
and password
, these would both be represented as String
s on the server side. But! We have a dateOfBirth
field here that should be interpreted as a Date
object on the server side (as opposed to a String
). Unfortunately, Spring isn't smart enough to translate text into a Date
object so it's going to need some help.
@InitBinder to the Rescue
Spring provides a mechanism that will allow you to specify your own custom binding of objects. So for the scenario that we have found ourselves in above, we'll need to specify how we would like Spring to bind this “Date of Birth” text to an actual Date
object. Let's take a look at that code:
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.WebDataBinder; import java.text.ParseException; import java.text.SimpleDateFormat; @InitBinder protected class myInitBinderMethod (WebDataBinder binder) { binder.registerCustomEditor(Date.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { try { Calendar calendar = Calendar.getInstance(); SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy"); Date dateObj = format.parse(text); setValue(dateObj); } catch (ParseException e1) { // handle error parsing text } } }); }
There's a fair bit going on here, so let's break it down.
@InitBinder
– This is what we use to tell Spring that this method should be used to implement our custom binding for our fields. Without this line of code, Spring would just ignore this method and it would never get called.
WebDataBinder binder
– Once you've labelled a method as the @InitBinder
method, you must then pass in the WebDataBinder
object. This will get populated by Spring automatically, and it's the object that you'll use to make the custom binding happen. If you don't understand what this means, then be sure to listen to the podcast by clicking the “Play” button at the top of this post.
setAsText(String text)
– This is a method that belongs to the PropertyEditorSupport
object and we are overriding it here. We override it because we want to tell it exactly how we want to bind this dateOfBirth
field from our webpage. Spring will automatically populate the text
variable with the text from the webpage, so if we were to type in “07/01/2000” as the date, that's exactly the String that will be passed to the text
variable.
setValue(dateObj)
– Once we have taken our text and converted it into a Date
object, we'll need to be sure and SET (or assign) that object for Spring to use and bind to our command object. I haven't shown you any code that relates to a command object, but in the example I'm talking about in the podcast, I mention that there's a User
command object that we would use. Once Spring finishes running through this code, the User
s dateOfBirth
property will be set with the Date
object that we just created!
Magic!