Uploaded image for project: 'Undertow'
  1. Undertow
  2. UNDERTOW-1000

Web Socket EncodingFactory does not resolve correct type

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 2.0.0.Beta1, 1.4.11.Final
    • 1.4.10.Final
    • Core
    • None
    • Hide

      Create 2 decoders:

      A generic super type, e.g.:

      public abstract class JsonDecoder<T> implements Decoder.Binary<T> {
      
          private final Class<? extends T> type;
          private final ObjectMapper objectMapper;
      
          public JsonDecoder(Class<? extends T> type) {
              this(type, new ObjectMapper());
          }
      
          public JsonDecoder(Class<? extends T> type, ObjectMapper objectMapper) {
              this.type = type;
              this.objectMapper = objectMapper;
          }
      
          @Override
          public T decode(ByteBuffer bytes) throws DecodeException {
              try {
                  return objectMapper.readValue(bytes.array(), type);
              } catch (IOException e) {
                  throw new DecodeException(bytes, String.format("Could not parse input string to a %s. Expected a Json string.", type), e);
              }
          }
      
          @Override
          public boolean willDecode(ByteBuffer bytes) {
              return true;
          }
      
          @Override
          public void init(EndpointConfig config) {
      
          }
      
          @Override
          public void destroy() {
      
          }
      }
      

      And an implementation, e.g.:

      public class MessageArrayDecoder extends JsonDecoder<Message[]> {
      
          public MessageArrayDecoder() {
              super(Message[].class);
          }
      }
      

      If MessageArrayDecoder is registered as decoder the decoder type is not resolved as Message[] but Object.

      Again, this is not the case if the abstract decoder extends from Decoder.Text<T>.

      Show
      Create 2 decoders: A generic super type, e.g.: public abstract class JsonDecoder<T> implements Decoder.Binary<T> { private final Class <? extends T> type; private final ObjectMapper objectMapper; public JsonDecoder( Class <? extends T> type) { this (type, new ObjectMapper()); } public JsonDecoder( Class <? extends T> type, ObjectMapper objectMapper) { this .type = type; this .objectMapper = objectMapper; } @Override public T decode(ByteBuffer bytes) throws DecodeException { try { return objectMapper.readValue(bytes.array(), type); } catch (IOException e) { throw new DecodeException(bytes, String .format( "Could not parse input string to a %s. Expected a Json string." , type), e); } } @Override public boolean willDecode(ByteBuffer bytes) { return true ; } @Override public void init(EndpointConfig config) { } @Override public void destroy() { } } And an implementation, e.g.: public class MessageArrayDecoder extends JsonDecoder<Message[]> { public MessageArrayDecoder() { super (Message[].class); } } If MessageArrayDecoder is registered as decoder the decoder type is not resolved as Message[] but Object. Again, this is not the case if the abstract decoder extends from Decoder.Text<T>.
    • User Experience
    • Workaround Exists
    • Hide

      Adding the following override to the implementation in the reproduce section can be used as work-around:

      @Override
          public Message[] decode(ByteBuffer bytes) throws DecodeException {
              return super.decode(bytes);
          }
      
      Show
      Adding the following override to the implementation in the reproduce section can be used as work-around: @Override public Message[] decode(ByteBuffer bytes) throws DecodeException { return super .decode(bytes); }
    • Low

      When registering a custom Decoder to decode binary web socket messages the value type is sometimes resolved incorrectly. This is not the case if the Decoder is a Text Decoder.

      The issue is only there if the decoder extends from a generic decoder class that leaves the value type generic: i.e.

      @Override public T decode(ByteBuffer bytes) { ... }
      

      The decoders (and encoders) are resolved in the following method of EncodingFactory:

      public static EncodingFactory createFactory(classIntrospecter, decoders, encoders) { ... }
      

      On line 184 the type for text decoders is resolved via:

      final Class<?> type = resolveReturnType(method, decoder);

      However for binary decoders (and all Encoders) the type is resolved via:

      final Class<?> type = method.getReturnType();

      It seems this issue used to also be there for text decoders but was resolved by adding the resolveReturnType() method. However, the person that added that method seems to have forgotten to also change the part that targets binary decoders.

            sdouglas1@redhat.com Stuart Douglas
            imapickle Rene de Waele (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: