Avro
  1. Avro
  2. AVRO-1166

IDL return type of map<record> fails in schema processing

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7.1
    • Fix Version/s: 1.7.2
    • Component/s: java
    • Labels:
      None

      Description

      An IDL construct such as ...

      Foo.idl
      protocol MyService {
          record Bar {
              int     count;
              string  message;
          }
      
          map<Bar> getBars();
      }
      

      generates run-time errors because of this code in SpecificData.java

      SpecificData.java lines 189-196
            } else if (Map.class.isAssignableFrom(raw)) {   // map
              java.lang.reflect.Type key = params[0];
              java.lang.reflect.Type value = params[1];
              if (!(type instanceof Class
                    && CharSequence.class.isAssignableFrom((Class)type)))
                throw new AvroTypeException("Map key class not CharSequence: "+key);
              return Schema.createMap(createSchema(value, names));
            } else {
      

      the issue is that CharSequence.class.isAssignableFrom((Class)type)) should really be CharSequence.class.isAssignableFrom((Class)key))

      1. AVRO-1166.patch
        2 kB
        Doug Cutting

        Issue Links

          Activity

          Hide
          Doug Cutting added a comment -

          The bug looks real, but I don't see any code that calls this. For example, SpecificData.getSchema(Bar.class) works without error. Can you please provide a full stack trace, and/or some sample code that causes this to produce the wrong results? Thanks!

          Show
          Doug Cutting added a comment - The bug looks real, but I don't see any code that calls this. For example, SpecificData.getSchema(Bar.class) works without error. Can you please provide a full stack trace, and/or some sample code that causes this to produce the wrong results? Thanks!
          Hide
          Amine R. added a comment -

          Hello Doug,
          Thanks for getting back to us so quickly

          java.lang.RuntimeException: org.apache.avro.AvroTypeException: Map key class not CharSequence: class java.lang.String

          Caused by: org.apache.avro.AvroTypeException: Map key class not CharSequence: class java.lang.String
          at org.apache.avro.specific.SpecificData.createSchema(SpecificData.java:180)
          at org.apache.avro.specific.SpecificData.getSchema(SpecificData.java:140)
          at com.foo.bar.encode.AvroEncoder.encode(AvroEncoder.java:44)
          ... 7 more

          the encode method has this body :

          	
          	 public byte[] encode(Object object, Type type) throws IOException {
                  SpecificDatumWriter<Object> writer = new SpecificDatumWriter<Object>(SpecificData.get().getSchema(type));
                  ByteArrayOutputStream baos = new ByteArrayOutputStream();
                  JsonEncoder encoder =  EncoderFactory.get().jsonEncoder(SpecificData.get().getSchema(type), baos);
          
                  writer.write(object, encoder);
                  encoder.flush();
          
                  return baos.toByteArray();
              }
          
          Show
          Amine R. added a comment - Hello Doug, Thanks for getting back to us so quickly java.lang.RuntimeException: org.apache.avro.AvroTypeException: Map key class not CharSequence: class java.lang.String Caused by: org.apache.avro.AvroTypeException: Map key class not CharSequence: class java.lang.String at org.apache.avro.specific.SpecificData.createSchema(SpecificData.java:180) at org.apache.avro.specific.SpecificData.getSchema(SpecificData.java:140) at com.foo.bar.encode.AvroEncoder.encode(AvroEncoder.java:44) ... 7 more the encode method has this body : public byte [] encode( Object object, Type type) throws IOException { SpecificDatumWriter< Object > writer = new SpecificDatumWriter< Object >(SpecificData.get().getSchema(type)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); JsonEncoder encoder = EncoderFactory.get().jsonEncoder(SpecificData.get().getSchema(type), baos); writer.write(object, encoder); encoder.flush(); return baos.toByteArray(); }
          Hide
          Amine R. added a comment -

          Adding debug information when the org.apache.avro.AvroTypeException: Map key class not CharSequence: class java.lang.String gets thrown:

          
          this = {org.apache.avro.specific.SpecificData@2754}
          type = {sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl@2760}"java.util.Map<java.lang.String, com.foo.bar.MyObject>"
          names = {java.util.LinkedHashMap@2761} size = 0
          ptype = {sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl@2760}"java.util.Map<java.lang.String, com.foo.bar.MyObject>"
          raw = {java.lang.Class@2762}"interface java.util.Map"
          params = {java.lang.reflect.Type[2]@2763}
          key = {java.lang.Class@2764}"class java.lang.String"
          value = {java.lang.Class@2451}"class com.foo.bar.MyObject"
          params[1] = {java.lang.Class@2451}"class com.foo.bar.MyObject"
          
          Show
          Amine R. added a comment - Adding debug information when the org.apache.avro.AvroTypeException: Map key class not CharSequence: class java.lang.String gets thrown: this = {org.apache.avro.specific.SpecificData@2754} type = {sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl@2760} "java.util.Map<java.lang. String , com.foo.bar.MyObject>" names = {java.util.LinkedHashMap@2761} size = 0 ptype = {sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl@2760} "java.util.Map<java.lang. String , com.foo.bar.MyObject>" raw = {java.lang. Class @2762} " interface java.util.Map" params = {java.lang.reflect.Type[2]@2763} key = {java.lang. Class @2764} "class java.lang. String " value = {java.lang. Class @2451} "class com.foo.bar.MyObject" params[1] = {java.lang. Class @2451} "class com.foo.bar.MyObject"
          Hide
          Amine R. added a comment -

          SpecificData.getSchema(Bar.class) would not throw the error, but SpecificData.getSchema(Map<String, Bar>) will.

          Show
          Amine R. added a comment - SpecificData.getSchema(Bar.class) would not throw the error, but SpecificData.getSchema(Map<String, Bar>) will.
          Hide
          Doug Cutting added a comment -

          Here's a patch to fix this that includes a test case.

          Unless there are objections I'll commit this soon.

          Show
          Doug Cutting added a comment - Here's a patch to fix this that includes a test case. Unless there are objections I'll commit this soon.
          Hide
          Doug Cutting added a comment -

          I committed this. Thanks, George.

          Show
          Doug Cutting added a comment - I committed this. Thanks, George.

            People

            • Assignee:
              George Fletcher
              Reporter:
              George Fletcher
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development