You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avro.apache.org by "Nandor Kollar (JIRA)" <ji...@apache.org> on 2017/12/05 15:59:00 UTC

[jira] [Commented] (AVRO-2108) @Stringable annotation should be processed before creating the schema

    [ https://issues.apache.org/jira/browse/AVRO-2108?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16278778#comment-16278778 ] 

Nandor Kollar commented on AVRO-2108:
-------------------------------------

[~FaisalFeroz] are you referring to a case like this:
{code}
  public static class Super<T> {
    @Stringable
    T f;
  }

  public static class B extends Super<String> {
  }

  @Test public void testStringable() throws Exception {
    B datum = new B();
    datum.f = "42";

    Schema schema = ReflectData.get().getSchema(B.class);
    ReflectDatumWriter<Object> writer = new ReflectDatumWriter<>(schema);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    writer.write(datum, EncoderFactory.get().directBinaryEncoder(out, null));
    byte[] data = out.toByteArray();

    ReflectDatumReader<Object> reader = new ReflectDatumReader<Object>(schema);
    Object decoded = reader.read(null,
      DecoderFactory.get().binaryDecoder(data, null));
  }
{code}

If so, your proposed patch would only fix the writing case, but will fail when reading data using ReflectDatumReader. Stringable classes require a constructor with a single String parameter, and since in runtime generic type information is not present, Avro will try to call java.lang.Object.<init>(java.lang.String), and fail. {{GenericDatumReader#newInstanceFromString}} should find the subclass's single parameter constructor in this case. In addition, I don't see any solution to solve the problem of reading of Super instances, since the generic type information is lost in runtime, thus Avro can't find the single parameter constructor of an unknown type.

> @Stringable annotation should be processed before creating the schema
> ---------------------------------------------------------------------
>
>                 Key: AVRO-2108
>                 URL: https://issues.apache.org/jira/browse/AVRO-2108
>             Project: Avro
>          Issue Type: Bug
>          Components: java
>    Affects Versions: 1.8.2
>            Reporter: Faisal Feroz
>
> In {{org.apache.avro.reflect.ReflectData::createFieldSchema}} the following code is processing Stringable after explicitly creating a schema
> {code:java}
> Schema schema = createSchema(field.getGenericType(), names);
> if (field.isAnnotationPresent(Stringable.class)) {      // Stringable
>   schema = Schema.create(Schema.Type.STRING);
> }
> {code}
> https://github.com/apache/avro/blob/3af404efb31a1dc2fd720384ef9a3f7326c2d303/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java#L748
> The above code has a side effect when @Stringable annotation is placed over a Generic Type like {{ID}} which results in Unknown Type {{ID}} since the schema is created first which causes the error. 
> Changing the code to following would fix this. Also it would also act as a micro optimization of the code as the generated schema is overwritten if stringable annotation is preset
> {code:java}
> Schema schema = null;
> if (field.isAnnotationPresent(Stringable.class)) {      // Stringable
>   schema = Schema.create(Schema.Type.STRING);
> } else {
>   schema = createSchema(field.getGenericType(), names);
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)