Problem using JAX-RS and java.time.LocalDate (java8).
I want to pass an object like this into a JAX-RS method using JSON:
Person {
java.time.LocalDate birthDay;
}
The exception I get is:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, classjava.time.LocalDate]: can not instantiate from JSON object (need to add/enable type information?) at [Source:io.undertow.servlet.spec.ServletInputStreamImpl@21cca2c1; line: 2, column: 3]
How can I create some kind of an interceptor that maps json-dates to java.time.LocalDate? I have tried implemented a MessageBodyReader, but if the LocalDate is a field in another class, I have to write a MessageBodyReader for each class holding a LocalDate (as far as I've understood).
(Java EE7 (only using the javaee-api and don't want any third party dependencies), JAX-RS, Java 8, Wildfly 8.2)
Any suggestions?
Other date fields, such as day-of-year, day-of-week and week-of-year, can also be accessed. For example, the value "2nd October 2007" can be stored in a LocalDate . This class does not store or represent a time or time-zone. Instead, it is a description of the date, as used for birthdays.
now() now() method of a LocalDate class used to obtain the current date from the system clock in the default time-zone. This method will return LocalDate based on system clock with default time-zone to obtain the current date. Syntax: public static LocalDate now()
Return value: This method returns LocalTime which is the parsed local date-time.
Normally I'd say to write a Serializer/Deserializer for Jackson, but since you don't want any other dependencies, you can use a JAXB solutions. Jackson (with Resteasy) comes with support for JAXB annotations. So what we can do is just write an XmlAdapter to convert from the String to the LocalDate. An example would be something like
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
@Override
public LocalDate unmarshal(String dateString) throws Exception {
return LocalDate.parse(dateString, DateTimeFormatter.ISO_DATE);
}
@Override
public String marshal(LocalDate localDate) throws Exception {
return DateTimeFormatter.ISO_DATE.format(localDate);
}
}
You can choose any formatting you want, I just used the DateTimeFormatter.ISO_DATE, which will basically look for this format (2011-12-03).
Then all you need to do is annotate the field for getter of the type
public class Person {
private LocalDate birthDate;
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getBirthDate() { return birthDate; }
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
}
If you don't want to clutter your model classes with this annotation, then you can simply declare the annotation at the package level.
In a package-info.java file in the same package as the model class(es), add this
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(type = LocalDate.class,
value = LocalDateAdapter.class)
})
package thepackage.of.the.models;
import java.time.LocalDate;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
@Path("/date")
public class DateResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response postPerson(Person person) {
return Response.ok(DateTimeFormatter.ISO_DATE.format(
person.getBirthDate())).build();
}
}
@Test
public void testResteasy() throws Exception {
WebTarget target = client.target(
TestPortProvider.generateURL(BASE_URI)).path("date");
String person = "{\"birthDate\":\"2015-01-04\"}";
Response response = target.request().post(Entity.json(person));
System.out.println(response.readEntity(String.class));
response.close();
}
Result : 2015-01-04
Also for Jackson (I know the OP said without dependencies, but this is for others), you can use the jackson-datatype-jsr310 module. See full solution here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With