Rest Services – date fields management

advertisement
1.1 Rest Services – Date/Time definition in ISO 8601 format with JDK 1.7
For date and time fields, the REST services with Resteasy (JBoss 7.1.1) accept the ISO
8601 format in input as well as timestamp (long) format.
ISO 8601
Timestamp
: 2014-02-25T12:45:07.000+0000
: 1393332307000
Still the output format is always « Timestamp » although the ISO 8601 format should be
returned as it was the case before with the Jersey library.
This behavior is the same for the two types : types java.util.Date and java.util.Calendar.
With the Resteasy version (2.3.2-Final) provided by default with JBoss 7.1.1, it’s not possible
to change that default behavior.
All the tests we’ve done couldn’t allow to change the default configuration, and neither create
json serializers customized for a specific field.
Tests done with last Resteasy version (3.0.6-Final) allowed both solution to work and return
ISO-8601 formatted fields.
Solution 1
Create a Java class allowing to configure the Resteasy provider so all dates are written in
ISO format instead of timestamp.
This apply to all fields :
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
Solution 2
Extend the default serializer for a specific type by creating a Java class in which the wanted
behavior can be defined.
public class JsonISO8601CalendarSerializer extends JsonSerializer<Calendar> {
…
And then define an annotation on the field to customize at the EI class level.
@JsonSerialize(using=JsonISO8601CalendarSerializer.class)
private Calendar testCalendarTimestamp;
With this solution, an annotation must be specified on each field to be customized, so we can
define a specific behavior only for some fields.
Detail about each solution is described in following chapters.
1.1.1 Recommendations
With JDK 1.7, it is recommended to use java.util.Calendar class in the EI classes and to
solution 1 allowing to change the Resteasy behavior so the Rest services return ISO 8601
formatted.
The class allowing to configure the ISO 8601 format has been added to xcomponent 1.1 :

xcomponent-ejb version 1.1.0.0-SNAPSHOT (or superior)
o
ch.xpertline.component.service.restricted.technical.JsonJacksonISO8601Date
Provider
Dates will so be returned in ISO 8601 format for all projects using xcomponent-ejb as a
dependency.
1.1.2 Done tests
Definition of the following entity :
@Id
@Basic(optional = false)
@Column(name = "id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@Column(name = "timeStamp")
@Temporal(TemporalType.TIMESTAMP)
private Date timeStamp;
@Size(max = 1024)
@Column(name = "testString")
private String testString;
@Column(name = "testDate")
@Temporal(TemporalType.DATE)
private Date testDate;
@Column(name = "testTime")
@Temporal(TemporalType.TIME)
private Date testTime;
@Column(name = "testCalendarTimestamp")
@Temporal(TemporalType.TIMESTAMP)
private Calendar testCalendarTimestamp;
@Column(name = "testCalendarDate")
@Temporal(TemporalType.DATE)
private Calendar testCalendarDate;
Definition of the EI data class for the Rest services:
private Integer id;
private Date timeStamp;
(Champ timestamp created by the server)
private String testString;
private Date testDate;
private Date testTime;
private Calendar testCalendarTimestamp;
private Calendar testCalendarDate;
1.1.2.1 Resteasy 2.3.2-Final
None of the 2 solutions work with 2.3.2 version
OK -> Data given as input to the Rest service when creating the record (ISO format) :
OK -> Data given as input to the Rest service when creating the record (Timestamp format) :
Output data returned by the Rest service when reading the record (timestamp format) :
Output data returned by the Rest service when reading the record (timestamp format) :
1.1.2.2 Solution 1 - Resteasy 3.0.6-Final – Class allowing to configure the default behavior
for all the fields
Provider class definition allowing to configure the default behavior for all the fields :
package ch.xpertline.xtst.rest.restricted;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
/**
* JSON Jackson JAXB Date Provider for json conversions as ISO-8601 format
* @author tifxb
*/
@Provider
public class JsonJacksonDateProvider implements ContextResolver<ObjectMapper> {
private ObjectMapper objectMapper = null;
public JsonJacksonDateProvider() {
objectMapper = new ObjectMapper() ;
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS,
false);
}
@Override
public ObjectMapper getContext(Class<?> arg0) {
return objectMapper;
}
}
Addition of following dependencies with provided scope in the pom.xml file :
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.6.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.6.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.0.6.Final</version>
<scope>provided</scope>
</dependency>
Output data returned by the Rest service when reading the record (ISO format) :
1.1.2.3 Solution 2 - Resteasy 3.0.6-Final – Class allowing to configure specific field behavior
Creation of a JsonISO8601DateSerializer class:
package ch.xpertline.xtst.services.restricted.technical;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
/**
* JSON ISO 8601 Date Serializer
* @author tifxb
*/
public class JsonISO8601DateSerializer extends JsonSerializer<Date> {
private static final String DEFAULT_ISO8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
private static final SimpleDateFormat formatter = new
SimpleDateFormat(DEFAULT_ISO8601_FORMAT);
@Override
public void serialize(Date date, JsonGenerator jgen, SerializerProvider provider) throws
IOException, JsonProcessingException {
jgen.writeString(formatter.format(date));
}
}
Addition of following dependencies with provided scope in the pom.xml file :
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.6.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.6.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.0.6.Final</version>
<scope>provided</scope>
</dependency>
Addition of annotation on the wanted field in the EI class :
@JsonSerialize(using=JsonISO8601DateSerializer.class)
private Date testDate;
Output data returned by the Rest service when reading the record (ISO format) :
Download