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

ParamConverter are not applied to HeaderParam in jax-rs clients

    Details

    • Type: Bug
    • Status: Resolved (View Workflow)
    • Priority: Minor
    • Resolution: Done
    • Affects Version/s: 4.4.2.Final
    • Fix Version/s: 4.5.5.Final
    • Component/s: jaxrs
    • Labels:
      None
    • Steps to Reproduce:
      Hide

      Some simple pojo:

      public class MyClass {
          public MyClass() { }
          @Override
          public String toString() {
              return "badValue";
          }
      }
      

      A ParamConverterProvider for such class:

      @Provider
      public class MyClassProvider implements ParamConverterProvider {
          public static class MyClassConverter implements ParamConverter<MyClass> {
              @Override
              public MyClass fromString(String value) {
                  final MyClass result = new MyClass();
                  return result;
              }
              @Override
              public String toString(MyClass value) {
                  return "paramConverter";
              }
          }
      
          public MyClassProvider () {
          }
      
          @Override
          public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
              final ParamConverter<T> result;
              if (rawType.isAssignableFrom(MyClass .class)) {
                  result = (ParamConverter<T>)new MyClassConverter();
              } else {
                  result = null;
              }
              return result;
          }
      }
      

      An interface using such class in a HeaderParam:

          @Path("/test")
          public interface TestService {
              @GET
              void test(@HeaderParam("test-header") MyClass someValue);
          }
      

      When using a client:

      public static void main(String[] args) {
          MyClass header = new MyClass();
          header.setValue("someValue");
          TestService service = RestClientBuilder.newBuilder().build(TestService .class);
          service.test(header);
      }
      

      sent message has header "test-header" with value "badValue" instead of "paramConverter".

      When using CookieParam, value "paramConverter" is returned in cookie "test-header".

      Show
      Some simple pojo: public class MyClass { public MyClass() { } @Override public String toString() { return "badValue" ; } } A ParamConverterProvider for such class: @Provider public class MyClassProvider implements ParamConverterProvider { public static class MyClassConverter implements ParamConverter<MyClass> { @Override public MyClass fromString( String value) { final MyClass result = new MyClass(); return result; } @Override public String toString(MyClass value) { return "paramConverter" ; } } public MyClassProvider () { } @Override public <T> ParamConverter<T> getConverter( Class <T> rawType, Type genericType, Annotation[] annotations) { final ParamConverter<T> result; if (rawType.isAssignableFrom(MyClass .class)) { result = (ParamConverter<T>) new MyClassConverter(); } else { result = null ; } return result; } } An interface using such class in a HeaderParam: @Path( "/test" ) public interface TestService { @GET void test(@HeaderParam( "test-header" ) MyClass someValue); } When using a client: public static void main( String [] args) { MyClass header = new MyClass(); header.setValue( "someValue" ); TestService service = RestClientBuilder.newBuilder().build(TestService .class); service.test(header); } sent message has header "test-header" with value "badValue" instead of "paramConverter". When using CookieParam, value "paramConverter" is returned in cookie "test-header".

      Description

      Resteasy client doesn't apply ParamConverter when serializing HeaderParam values.

      JAX-RS: Java™ API for RESTful Web Services (Version 2.1), section 3.2 (Fields and Bean Properties):

      When a resource class is instantiated, the values of fields and bean properties annotated with one the following annotations are set according to the semantics of the annotation:
      @MatrixParam Extracts the value of a URI matrix parameter.
      @QueryParam Extracts the value of a URI query parameter.
      @PathParam Extracts the value of a URI template parameter.
      @CookieParam Extracts the value of a cookie.
      @HeaderParam Extracts the value of a header.
      @Context Injects an instance of a supported resource, see chapters 10 and 11 for more details.
      Because injection occurs at object creation time, use of these annotations (with the exception of @Context) on resource class fields and bean properties is only supported for the default per-request resource class lifecycle. An implementation SHOULD warn if resource classes with other lifecycles use these annotations on resource class fields or bean properties.
      A JAX-RS implementation is only required to set the annotated field and bean property values of instances created by its runtime. Objects returned by sub-resource locators (see Section 3.4.1) are expected to be initialized by their creator.
      Valid parameter types for each of the above annotations are listed in the corresponding Javadoc, however in general (excluding @Context) the following types are supported:

      1. Types for which a ParamConverter is available via a registered ParamConverterProvider. See Javadoc for these classes for more information.
      2. Primitive types.
      3. Types that have a constructor that accepts a single String argument.
      4. Types that have a static method named valueOf or fromString with a single String argument
        that return an instance of the type. If both methods are present then valueOf MUST be used unless
        the type is an enum in which case fromString MUST be used1.
      5. List<T>, Set<T>, or SortedSet<T>, where T satisfies 1, 3 or 4 above.

      Point 1 is not being applied with HeaderParam when single value is used. Class org.jboss.resteasy.client.jaxrs.internal.proxy.processors.AbstractCollectionProcessor<T> (in resteasy-client artifact) is processing in a valid way Collections and Arrays, but with single values is delegating such processing to final classes. FormParamProcessor (for example) is doing in the right way (lines 52-53), but HeaderParamProcessor is using directly toString result of the object (line 30).

        Gliffy Diagrams

          Attachments

            Activity

              People

              • Assignee:
                rsearls r searls
                Reporter:
                Dawuid David Santos
              • Votes:
                1 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: