OpenJPA and Date JSON serialization


Following the trends, you can try to push your entities to the front layer of your application without any in between conversion. A common sample is to return an entity in a JAX-RS bean.

For instance:

@Path("user")
public class UserResource {
    @PersistenceContext EntityManager em;

    @Path("{id}")
    public User findById(@PathParam("id") String id) {
        return em.find(User.class, id);
    }
}

Now suppose User has a java.util.Date field and you are using OpenJPA as JPA provider. You may have missed it but OpenJPA is using proxying for dates. It is smooth while you don’t do any reflection on it because it is a subclass of Date. It looks like a Date but it has several additional fields.

If you serialize your user directly (I used Apache Johnzon) you’ll get something like that:

{"created":{"date":16,"hours":0,"seconds":0,"month":4,"timezoneOffset":-120,"year":115,"minutes":0,"time":1431727200000,"day":6},...}

You don’t get the default serialization of your JSON provider/mapper (often a version of ISO8601 format).

Why is it important? First, because debugging it is not that trivial (how would you think to look here?). Then the biggest issue is: if you use javascript on client side then all date integration is just broken because javascript will consider it as an object and not a date.

What are the solutions?

You can use last Apache Johnzon SNAPSHOT. Since JOHNZON-47 this issue is fixed for java.util.Date.

If you don’t want to use the SNAPSHOT or don’t use Johnzon, you have two cases but the idea is the same: copy the date from the getTime() value.

If you use a framework supportting converters (whatever the name used in your framework), you can register a custom converter doing :

public String toString(final Date instance) {
    Date dateToConvert = new Date(instance.getTime());
    return delegate.toString(date);
}

If you use a layered application you can do it in your converters/mappers. But don’t forget it,
as this solution will lead to the exact same issue:

myDto.setDate(myEntity.getDate());

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s