[ 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.