Search code examples
javajsonspring-bootresteasyjackson-databind

ObjectMapper different behaviour in Resteasy Client with proxy


I'm doing a quite usual task to integrate a remote JSON service in a spring application, what it seems to happen is that the ObjectMapper set into a ResteasyJackson2Provider behave differently from the same ObjectMapper used "manually":

@Service
public class MyService {

    @Autowired
    ObjectMapper objectMapper;

    public MyItem getItemById(Long itemId) {
        MyServiceClient client = getMyServiceClient("http://localhost:8888/myservice");

        //Not Working
        MyItem item = client.getItem(itemId);
            
        //Working 
        String itemJson = client.getItemJson(itemId);
        MyItem itemFromJson = objectMapper.readValue(itemJson, MyItem.class);
        
        return item;
    }

    private MyServiceClient getMyServiceClient(String serviceUrl) {
        ResteasyJackson2Provider resteasyJacksonProvider = new ResteasyJackson2Provider();
        resteasyJacksonProvider.setMapper(objectMapper);
        ResteasyClient client = new ResteasyClientBuilder().register(resteasyJacksonProvider).build();
        ResteasyWebTarget target = client
                .target(UriBuilder.fromPath(serviceUrl));
        MyServiceClient proxy = target.proxy(MyServiceClient.class);
        return proxy;
    }

}

When delegating the deserialisation to the proxy i get this error:

java.lang.reflect.InaccessibleObjectException: Unable to make field private final int java.time.LocalDate.year accessible: module java.base does not "opens java.time" to unnamed module @13e39c73

And from unit tests I made, this error happens when not including " .registerModule(new JavaTimeModule());" in object mapper.

But when I manually call the objectMapper.readValue() this does not happens, and the object is correctly deserialised.

here the code of the proxy interface methods:

@Path("/api")
public interface MyServiceClient {

    @GET
    @Path("/items/{id}")
    MyItem getItem(@PathParam("id") Long id);

    @GET
    @Path("/items/{id}")
    String getItemJson(@PathParam("id") Long id);
}

Solution

  • After other tests I did today, the problem is not the objectmapper itself, but is related to the resteasyJacksonProvider and its registration into the client builder.

    Since, still don't know why, there's already a module registered of same class in the ResteasyClientBuilder, that second registration is being ignored.

    So the instance used for data reading is an empty default mapper.