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

Scott Carey commented on AVRO-336:
----------------------------------

{quote}I suspect the fix is, in your code, to pass the appropriate array schema 
to GenericArray's constructor.{quote}

Ok, I hadn't looked at the Schema class factories until now.  
The classes generated by the SpecificAPI contain their own schema in a $SCHEMA 
static member.  But no Array objects are generated, so there are no schemas of 
arrays available that way.
It seems odd for a user of the specific API to do anything but use the schemas 
in the generated classes.  In fact, it seems a little odd to even have to do 
that.  In my mind, the idea of the Specific API is to generate classes that do 
all the Avro details for you, with a schema or protocol file as input.

So, I changed my test where I set :
{code}    data.treatments = new GenericData.Array<Variable>(0, 
Variable.SCHEMA$);{code}
to:
{code}    data.treatments = new GenericData.Array<Variable>(0, 
Schema.createArray(Variable.SCHEMA$));{code}

And that works.   

Also, the patch works, detecting the error when the array is created.

The fact that it successfully serialized and deserialized before tricked me 
into thinking things were ok.  I suppose I wasn't strictly checking the 
deserialized data to make sure it was an array, and it is empty in my test 
anyway.  Anything that prevents invalid data from being 'successfully' 
serialized by mistake is a good thing.


It took me a while to figure out how to set an Array at all with the Specific 
API (and I was wrong).  Perhaps there should be a SpecificArray class or 
factory, or the generated classes could contain a setter?  
I thought about making an inner class of of SpecificData with this signature 
but was not sure how to pass the schema around correctly without something ugly 
with reflection:
{code}
   public static class Array<T extends SpecificRecord> extends 
GenericData.Array<T>{code}

Maybe, a user could just do 
{code}
new SpecificData.Array<ElementType>(java.util.Array<ElementType> 
elements);{code}
and the constructor handles the rest.  

Even better, a factory and/or setter on the generated class would feel the most 
'natural' -- then a user deals only with generated classes, and never imports 
o.a.avro.generic when dealing with the specific api.
As a user learning the Specific API, I feel like it doesn't encapsulate its 
implementation enough.  Details like it being built on top of the Generic API 
are exposed, and schemas are exposed.

> Equals() on SpecificRecord fails (java)
> ---------------------------------------
>
>                 Key: AVRO-336
>                 URL: https://issues.apache.org/jira/browse/AVRO-336
>             Project: Avro
>          Issue Type: Bug
>          Components: java
>    Affects Versions: 1.3.0
>            Reporter: Scott Carey
>            Assignee: Doug Cutting
>             Fix For: 1.3.0
>
>         Attachments: AVRO-336.patch
>
>
> rev 899520, trunk.
> Calling equals() on an object generated by the SpecificAPI fails.
> The object is a record with several fields, one is an array.  This object can 
> serialize and deserialize, binary and json.  But equals() fails, as well as 
> hashCode() in some cases.
> It fails in Schema.java, line 217.
> {code}
>   /** If this is an array, returns its element type. */
>   public Schema getElementType() {
>     throw new AvroRuntimeException("Not an array: "+this);
>   }
> {code}
> This looks unimplemented.
> The stack trace is:
> {noformat}
> Exception in thread "main" org.apache.avro.AvroRuntimeException: Not an 
> array: 
> {"type":"record","name":"Variable","namespace":"com.rr.avro","fields":[{"name":"variableId","type":"int"},{"name":"selectedValue","type":"string"}]}
>       at org.apache.avro.Schema.getElementType(Schema.java:217)
>       at org.apache.avro.generic.GenericData.compare(GenericData.java:468)
>       at org.apache.avro.specific.SpecificData.compare(SpecificData.java:250)
>       at org.apache.avro.specific.SpecificData.compare(SpecificData.java:242)
>       at 
> org.apache.avro.specific.SpecificRecordBase.compareTo(SpecificRecordBase.java:45)
>       at 
> org.apache.avro.specific.SpecificRecordBase.equals(SpecificRecordBase.java:35)
> {noformat}
> That record is the element type of the array, so I think this is just due to 
> the implementation being incomplete.
> The specific compiler could also generate equals() methods (which would be 
> more efficient than traversing the schema).  I wonder if eclipse's "generate 
> hashcode and equals" code is usable.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to