Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-3456

Jackson Providers may use the wrong cached reader/writer if two endpoints have the same return type

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • None
    • Providers
    • None

      If two methods in a resource have the same return type, the incorrect reader or writer might be cached and used. The cache is based on the return type and the annotations on the type. However, if executing from a Client for example, then different providers may be registered that are not used.

      Example Resource
      @Path("/status")
      public class PortalStatusRest {
      
          @Path("/jsr310")
          @GET
          @Produces(MediaType.APPLICATION_JSON)
          public Response jsr310Response() {
              JSR310Response response = new JSR310Response();
              response.setServerTime(ZonedDateTime.now());
              return Response.ok(response).build();
          }
      
          @Path("/time")
          @GET
          @Produces(MediaType.APPLICATION_JSON)
          public Response trigger() {
              try (Client client = ClientBuilder.newBuilder().build()) {
                  JSR310Response response = client.target("http://localhost:8080/web-app/rest/status/jsr310")
                          .request()
                          .get()
                          .readEntity(JSR310Response.class);
                  return Response.ok(response).build();
              }
          }
      
          @Path("/time/register/1")
          @GET
          @Produces(MediaType.APPLICATION_JSON)
          public Response triggerRegistered1() {
              try (Client client = ClientBuilder.newBuilder().register(JacksonDatatypeJacksonProducer.class).build()) {
                  JSR310Response response = client.target("http://localhost:8080/web-app/rest/status/jsr310")
                          .request()
                          .get()
                          .readEntity(JSR310Response.class);
                  return Response.ok(response).build();
              }
          }
      
          public static class JSR310Response {
      
              private ZonedDateTime serverTime;
      
              public ZonedDateTime getServerTime() {
                  return serverTime;
              }
      
              public void setServerTime(ZonedDateTime serverTime) {
                  this.serverTime = serverTime;
              }
          }
      }
      

      if you invoke the path status/time first, then when you execute status/time/register/1 the wrong writer is resolved and a failure occurs. The JacksonDatatypeJacksonProducer is not used, which it should be in this case.

      JacksonDatatypeJacksonProducer.java
      @Provider
      @Produces(MediaType.APPLICATION_JSON)
      public class JacksonDatatypeJacksonProducer implements ContextResolver<ObjectMapper> {
      
          private final ObjectMapper json;
      
          public JacksonDatatypeJacksonProducer() {
              this.json = JsonMapper.builder()
                      .findAndAddModules()
                      .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                      .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
                      .build();
          }
      
          @Override
          public ObjectMapper getContext(final Class<?> type) {
              return json;
          }
      }
      

            rhn-engineering-ema Jim Ma
            jperkins-rhn James Perkins
            Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: