Spring MVC: Handling Joda Data Types as JSON

PROBLEM

Let’s assume we have the following bean that contains Joda’s LocalDate and LocalDateTime objects:-

public class MyBean {
    private LocalDate date;
    private LocalDateTime dateTime;

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public LocalDateTime getDateTime() {
        return dateTime;
    }

    public void setDateTime(LocalDateTime dateTime) {
        this.dateTime = dateTime;
    }
}

This simple Spring MVC rest controller creates this bean and returns the JSON data back to the client:-

@RequestMapping(value = "/joda", method = RequestMethod.GET)
public ResponseEntity joda() {
    MyBean myBean = new MyBean();
    myBean.setDate(LocalDate.now());
    myBean.setDateTime(LocalDateTime.now());

    return new ResponseEntity<mybean>(myBean, HttpStatus.OK);
}

By default, the generated JSON looks like this:-

{
   "date":
   [
       2015,
       3,
       28
   ],
   "dateTime":
   [
       2015,
       3,
       28,
       18,
       12,
       58,
       992
   ]
}

How do we nicely format these values and still retain the correct data types (LocalDate and LocalDateTime) in MyBean instead of writing our custom formatter and store the values as String?

SOLUTION

First, add a dependency for jackson-datatype-joda.

<dependency>
    <groupid>com.fasterxml.jackson.core</groupid>
    <artifactid>jackson-core</artifactid>
    <version>2.5.1</version>
</dependency>
<dependency>
    <groupid>com.fasterxml.jackson.core</groupid>
    <artifactid>jackson-databind</artifactid>
    <version>2.5.1</version>
</dependency>
<dependency>
    <groupid>com.fasterxml.jackson.core</groupid>
    <artifactid>jackson-annotations</artifactid>
    <version>2.5.1</version>
</dependency>
<dependency>
    <groupid>com.fasterxml.jackson.datatype</groupid>
    <artifactid>jackson-datatype-joda</artifactid>
    <version>2.5.1</version>
</dependency>

Next, instruct MappingJackson2HttpMessageConverter to accept a custom ObjectMapper.

<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" p:indentoutput="true" p:simpledateformat="yyyy-MM-dd'T'HH:mm:ss.SSSZ">
</bean>

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" p:targetobject-ref="objectMapper" p:targetmethod="registerModule">
    <property name="arguments">
        <list>
            <bean class="com.fasterxml.jackson.datatype.joda.JodaModule">
        </bean></list>
    </property>
</bean>

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <bean class="org.springframework.http.converter.ResourceHttpMessageConverter">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="objectMapper">
        </property></bean>
    </bean></bean></mvc:message-converters>
</mvc:annotation-driven>

The generated JSON output now looks like this:-

{
   "date": "2015-03-28",
   "dateTime": "2015-03-28T18:11:16.348"
}

Jadira Usertype: Under JDK 6 it may not be possible to handle DST transitions correctly

PROBLEM

When saving a Hibernate entity that contains Joda Time object, Jadira UserType throws the following warning:-

[WARN ] [JavaTimeZoneWorkaroundHelper] [&lt;clinit&gt;:40] - Under JDK 6 it may not be possible 
to handle DST transitions correctly
[ERROR] [JavaTimeZoneWorkaroundHelper] [&lt;clinit&gt;:42] - Running under a Zone that uses 
daylight saving time. To avoid incorrect datetimes being stored during DST transition, 
either update to JDK 7 or use a Timezone for the JDK without Daylight Saving Time

This warning occurs when using this version:-

&lt;dependency&gt;
    &lt;groupId&gt;org.jadira.usertype&lt;/groupId&gt;
    &lt;artifactId&gt;usertype.core&lt;/artifactId&gt;
    &lt;version&gt;3.0.0.GA&lt;/version&gt;
&lt;/dependency&gt;

SOLUTION

Upgrade Jadira Usertype to the latest version, and the problem goes away:-

&lt;dependency&gt;
    &lt;groupId&gt;org.jadira.usertype&lt;/groupId&gt;
    &lt;artifactId&gt;usertype.core&lt;/artifactId&gt;
    &lt;version&gt;3.1.0.CR10&lt;/version&gt;
&lt;/dependency&gt;

Hibernate + Joda Time: Auto Registering Type

OVERVIEW

Jadira Usertype is required when using Joda Time with Hibernate 4. The Joda Time objects are annotated accordingly in the Hibernate entity, and they looks something like this:-

@Entity
@Table(name = &quot;person&quot;)
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = &quot;personId&quot;)
    private Long id;

    @Column
    private String name;
	
    @Column
    @Type(type = &quot;org.jadira.usertype.dateandtime.joda.PersistentLocalDate&quot;)
    private LocalDate birthDate;

    @Column
    @Type(type = &quot;org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime&quot;)
    private LocalDateTime createdDatetime;
	
    // getters and setters
}

PROBLEM

This solution works, but it is rather tedious because I can never remember the actual @Type to write, thus I always end up copying and pasting it from past project code.

Further, that additional annotations clutter up my otherwise beautiful code.

SOLUTION

Jadira Usertype provides a clean way to auto register these Joda Time object types.

In the Hibernate configuration, add the following line:-

&lt;bean id=&quot;sessionFactory&quot; class=&quot;org.springframework.orm.hibernate4.LocalSessionFactoryBean&quot;&gt;
    &lt;property name=&quot;dataSource&quot; ref=&quot;dataSource&quot;/&gt;

    &lt;property name=&quot;hibernateProperties&quot;&gt;
        &lt;props&gt;
            &lt;prop key=&quot;hibernate.dialect&quot;&gt;org.hibernate.dialect.SQLServerDialect&lt;/prop&gt;
            &lt;prop key=&quot;hibernate.show_sql&quot;&gt;false&lt;/prop&gt;
            &lt;prop key=&quot;jadira.usertype.autoRegisterUserTypes&quot;&gt;true&lt;/prop&gt;
        &lt;/props&gt;
    &lt;/property&gt;
    &lt;property name=&quot;packagesToScan&quot;&gt;
        &lt;list&gt;
            &lt;value&gt;com.choonchernlim.project.entity&lt;/value&gt;
        &lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;

Now all @Type annotations can be safely removed from the Hibernate entity:-

@Entity
@Table(name = &quot;person&quot;)
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = &quot;personId&quot;)
    private Long id;

    @Column
    private String name;
	
    @Column
    private LocalDate birthDate;

    @Column
    private LocalDateTime createdDatetime;
	
    // getters and setters
}