I configured jackson so that it gives me a smiple string representation if java.time.LocalDate
and java.time.LocalDateTime
. This works find in the serialization process, e.g when I get data on the REST api.
It doesn't work the other way round though. When I try to send data to the server and the JSON should be parsed to java objects this exception is thrown:
javax.ws.rs.client.ResponseProcessingException: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.LocalDateTime: no String-argument constructor/factory method to deserialize from String value ('2018-04-19T14:10:30.903')
After a few hours of research I managed to get it to work, but only with the attributes I annotated with @JsonDeserialize(using = LocalDateDeserializer.class)
or @JsonDeserialize(using = LocalDateTimeDeserializer.class)
respectively.
In my opinion it would be ideal, if I could define these mappings in one central place.
ObjectMapper configuration:
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
@Override
public ObjectMapper getContext(Class<?> aClass) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return mapper;
}
}
I tried to add custom deserializers to the JavaTimeModule, but without success:
JavaTimeModule dateTimeModule = new JavaTimeModule();
dateTimeModule.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE);
dateTimeModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
mapper.registerModule(dateTimeModule);
Long story short: Is there a way to define the mapping globally, so that I do not need these annotations on every field. Thanks!
EDIT:
Alright: I tested it with postman and without the annotations and it worked as expected. However, when I run the unit test (JerseyTest) it throws the mentioned exception. I register the ObjectMapperContextResolver
to the test application, but probably I am missing something.
Sorry about not mentioning that I was in the unit tests.
TestClass:
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import javax.ws.rs.core.Application;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
public class PocRestTest extends JerseyTest {
private static PocService mockedPocService;
@Override
protected Application configure() {
mockedPocService = Mockito.mock(PocService.class);
ResourceConfig config = new ResourceConfig();
config.register(new PocRest(mockedPocService));
config.register(ObjectMapperContextResolver.class);
return config;
}
private Poc dto;
@Before
public void init() {
dto = new Poc();
dto.setId(1);
dto.setName("hi rest");
dto.setDate(LocalDate.now());
dto.setDateTime(LocalDateTime.now());
doReturn(dto).when(mockedPocService).getPocById(1);
}
@Test
public void test() {
Poc response = target("poc/1").request().get(Poc.class);
assertEquals(dto.getId(), response.getId());
assertEquals(dto.getName(), response.getName());
assertEquals(dto.getDate(), response.getDate());
assertEquals(dto.getDateTime(), response.getDateTime());
verify(mockedPocService).getPocById(1);
verifyNoMoreInteractions(mockedPocService);
}
}