Repository: avro Updated Branches: refs/heads/master ba11ddab1 -> ff5099c85
AVRO-2114: Make missing value exceptions in nested structures easier to read. This closes #263 Project: http://git-wip-us.apache.org/repos/asf/avro/repo Commit: http://git-wip-us.apache.org/repos/asf/avro/commit/ff5099c8 Tree: http://git-wip-us.apache.org/repos/asf/avro/tree/ff5099c8 Diff: http://git-wip-us.apache.org/repos/asf/avro/diff/ff5099c8 Branch: refs/heads/master Commit: ff5099c85ddb668af8a80560d706a8914f717356 Parents: ba11dda Author: Niels Basjes <[email protected]> Authored: Tue Dec 12 13:09:40 2017 +0100 Committer: Niels Basjes <[email protected]> Committed: Fri Dec 15 21:13:53 2017 +0100 ---------------------------------------------------------------------- CHANGES.txt | 3 + .../apache/avro/AvroMissingFieldException.java | 46 ++++ .../org/apache/avro/generic/GenericData.java | 5 +- .../org/apache/avro/FooBarSpecificRecord.java | 248 +++++++++++++++---- .../specific/templates/java/classic/record.vm | 9 +- .../avro/specific/TestSpecificBuilderTree.java | 12 +- .../avro/examples/baseball/Player.java | 2 + .../tools/src/test/compiler/output/Player.java | 2 + 8 files changed, 278 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 1d22b4d..d23a5bb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -96,6 +96,9 @@ Trunk (not yet released) AVRO-2080: Fix Javadoc Warnings in Generated Records (Bridger Howell via Niels Basjes) + AVRO-2114: Make missing value exceptions in nested structures easier to read. + (Niels Basjes) + BUG FIXES AVRO-1741: Python3: Fix error when codec is not in the header. http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/avro/src/main/java/org/apache/avro/AvroMissingFieldException.java ---------------------------------------------------------------------- diff --git a/lang/java/avro/src/main/java/org/apache/avro/AvroMissingFieldException.java b/lang/java/avro/src/main/java/org/apache/avro/AvroMissingFieldException.java new file mode 100644 index 0000000..2ef12b2 --- /dev/null +++ b/lang/java/avro/src/main/java/org/apache/avro/AvroMissingFieldException.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.avro; + +import org.apache.avro.Schema.Field; + +import java.util.ArrayList; +import java.util.List; + +/** Avro exception in case of missing fields. */ +public class AvroMissingFieldException extends AvroRuntimeException { + private List<Field> chainOfFields = new ArrayList<>(8); + public AvroMissingFieldException(String message, Field field) { + super(message); + chainOfFields.add(field); + } + + public void addParentField(Field field) { + chainOfFields.add(field); + } + + @Override + public String toString() { + String result = ""; + for (Field field: chainOfFields) { + result = " --> " + field.name() + result; + } + return "Path in schema:" + result; + } +} http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java ---------------------------------------------------------------------- diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java index 9a51e40..b8dfcc6 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java +++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java @@ -31,6 +31,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.apache.avro.AvroMissingFieldException; import org.apache.avro.AvroRuntimeException; import org.apache.avro.AvroTypeException; import org.apache.avro.Conversion; @@ -995,8 +996,8 @@ public class GenericData { public Object getDefaultValue(Field field) { JsonNode json = field.defaultValue(); if (json == null) - throw new AvroRuntimeException("Field " + field - + " not set and has no default value"); + throw new AvroMissingFieldException("Field " + field + + " not set and has no default value", field); if (json.isNull() && (field.schema().getType() == Type.NULL || (field.schema().getType() == Type.UNION http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java ---------------------------------------------------------------------- diff --git a/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java b/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java index bab3620..e273786 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java +++ b/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java @@ -1,4 +1,4 @@ -/** +/* * Autogenerated by Avro * * DO NOT EDIT DIRECTLY @@ -20,12 +20,63 @@ * limitations under the License. */ package org.apache.avro; -@SuppressWarnings("all") + +import org.apache.avro.specific.SpecificData; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + @org.apache.avro.specific.AvroGenerated public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { private static final long serialVersionUID = 1031933828916876443L; public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"FooBarSpecificRecord\",\"namespace\":\"org.apache.avro\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"nicknames\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}},{\"name\":\"relatedids\",\"type\":{\"type\":\"array\",\"items\":\"int\"}},{\"name\":\"typeEnum\",\"type\":[\"null\",{\"type\":\"enum\",\"name\":\"TypeEnum\",\"symbols\":[\"a\",\"b\",\"c\"]}],\"default\":null}]}"); public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<FooBarSpecificRecord> ENCODER = + new BinaryMessageEncoder<FooBarSpecificRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<FooBarSpecificRecord> DECODER = + new BinaryMessageDecoder<FooBarSpecificRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<FooBarSpecificRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<FooBarSpecificRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<FooBarSpecificRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this FooBarSpecificRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a FooBarSpecificRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a FooBarSpecificRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static FooBarSpecificRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + @Deprecated public int id; @Deprecated public java.lang.String name; @Deprecated public java.util.List<java.lang.String> nicknames; @@ -41,6 +92,11 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** * All-args constructor. + * @param id The new value for id + * @param name The new value for name + * @param nicknames The new value for nicknames + * @param relatedids The new value for relatedids + * @param typeEnum The new value for typeEnum */ public FooBarSpecificRecord(java.lang.Integer id, java.lang.String name, java.util.List<java.lang.String> nicknames, java.util.List<java.lang.Integer> relatedids, org.apache.avro.TypeEnum typeEnum) { this.id = id; @@ -62,6 +118,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor default: throw new org.apache.avro.AvroRuntimeException("Bad index"); } } + // Used by DatumReader. Applications should not call. @SuppressWarnings(value="unchecked") public void put(int field$, java.lang.Object value$) { @@ -77,6 +134,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** * Gets the value of the 'id' field. + * @return The value of the 'id' field. */ public java.lang.Integer getId() { return id; @@ -92,6 +150,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** * Gets the value of the 'name' field. + * @return The value of the 'name' field. */ public java.lang.String getName() { return name; @@ -107,6 +166,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** * Gets the value of the 'nicknames' field. + * @return The value of the 'nicknames' field. */ public java.util.List<java.lang.String> getNicknames() { return nicknames; @@ -122,6 +182,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** * Gets the value of the 'relatedids' field. + * @return The value of the 'relatedids' field. */ public java.util.List<java.lang.Integer> getRelatedids() { return relatedids; @@ -137,6 +198,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** * Gets the value of the 'typeEnum' field. + * @return The value of the 'typeEnum' field. */ public org.apache.avro.TypeEnum getTypeEnum() { return typeEnum; @@ -150,19 +212,38 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor this.typeEnum = value; } - /** Creates a new FooBarSpecificRecord RecordBuilder */ + /** + * Creates a new FooBarSpecificRecord RecordBuilder. + * @return A new FooBarSpecificRecord RecordBuilder + */ public static org.apache.avro.FooBarSpecificRecord.Builder newBuilder() { return new org.apache.avro.FooBarSpecificRecord.Builder(); } - /** Creates a new FooBarSpecificRecord RecordBuilder by copying an existing Builder */ + /** + * Creates a new FooBarSpecificRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new FooBarSpecificRecord RecordBuilder + */ public static org.apache.avro.FooBarSpecificRecord.Builder newBuilder(org.apache.avro.FooBarSpecificRecord.Builder other) { - return new org.apache.avro.FooBarSpecificRecord.Builder(other); + if (other == null) { + return new org.apache.avro.FooBarSpecificRecord.Builder(); + } else { + return new org.apache.avro.FooBarSpecificRecord.Builder(other); + } } - /** Creates a new FooBarSpecificRecord RecordBuilder by copying an existing FooBarSpecificRecord instance */ + /** + * Creates a new FooBarSpecificRecord RecordBuilder by copying an existing FooBarSpecificRecord instance. + * @param other The existing instance to copy. + * @return A new FooBarSpecificRecord RecordBuilder + */ public static org.apache.avro.FooBarSpecificRecord.Builder newBuilder(org.apache.avro.FooBarSpecificRecord other) { - return new org.apache.avro.FooBarSpecificRecord.Builder(other); + if (other == null) { + return new org.apache.avro.FooBarSpecificRecord.Builder(); + } else { + return new org.apache.avro.FooBarSpecificRecord.Builder(other); + } } /** @@ -179,37 +260,43 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor /** Creates a new Builder */ private Builder() { - super(org.apache.avro.FooBarSpecificRecord.SCHEMA$); + super(SCHEMA$); } - /** Creates a Builder by copying an existing Builder */ + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ private Builder(org.apache.avro.FooBarSpecificRecord.Builder other) { super(other); if (isValidValue(fields()[0], other.id)) { this.id = data().deepCopy(fields()[0].schema(), other.id); - fieldSetFlags()[0] = true; + fieldSetFlags()[0] = other.fieldSetFlags()[0]; } if (isValidValue(fields()[1], other.name)) { this.name = data().deepCopy(fields()[1].schema(), other.name); - fieldSetFlags()[1] = true; + fieldSetFlags()[1] = other.fieldSetFlags()[1]; } if (isValidValue(fields()[2], other.nicknames)) { this.nicknames = data().deepCopy(fields()[2].schema(), other.nicknames); - fieldSetFlags()[2] = true; + fieldSetFlags()[2] = other.fieldSetFlags()[2]; } if (isValidValue(fields()[3], other.relatedids)) { this.relatedids = data().deepCopy(fields()[3].schema(), other.relatedids); - fieldSetFlags()[3] = true; + fieldSetFlags()[3] = other.fieldSetFlags()[3]; } if (isValidValue(fields()[4], other.typeEnum)) { this.typeEnum = data().deepCopy(fields()[4].schema(), other.typeEnum); - fieldSetFlags()[4] = true; + fieldSetFlags()[4] = other.fieldSetFlags()[4]; } } - /** Creates a Builder by copying an existing FooBarSpecificRecord instance */ + /** + * Creates a Builder by copying an existing FooBarSpecificRecord instance + * @param other The existing instance to copy. + */ private Builder(org.apache.avro.FooBarSpecificRecord other) { - super(org.apache.avro.FooBarSpecificRecord.SCHEMA$); + super(SCHEMA$); if (isValidValue(fields()[0], other.id)) { this.id = data().deepCopy(fields()[0].schema(), other.id); fieldSetFlags()[0] = true; @@ -232,12 +319,19 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor } } - /** Gets the value of the 'id' field */ + /** + * Gets the value of the 'id' field. + * @return The value. + */ public java.lang.Integer getId() { return id; } - /** Sets the value of the 'id' field */ + /** + * Sets the value of the 'id' field. + * @param value The value of 'id'. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder setId(int value) { validate(fields()[0], value); this.id = value; @@ -245,23 +339,37 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor return this; } - /** Checks whether the 'id' field has been set */ + /** + * Checks whether the 'id' field has been set. + * @return True if the 'id' field has been set, false otherwise. + */ public boolean hasId() { return fieldSetFlags()[0]; } - /** Clears the value of the 'id' field */ + + /** + * Clears the value of the 'id' field. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder clearId() { fieldSetFlags()[0] = false; return this; } - /** Gets the value of the 'name' field */ + /** + * Gets the value of the 'name' field. + * @return The value. + */ public java.lang.String getName() { return name; } - /** Sets the value of the 'name' field */ + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder setName(java.lang.String value) { validate(fields()[1], value); this.name = value; @@ -269,24 +377,38 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor return this; } - /** Checks whether the 'name' field has been set */ + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ public boolean hasName() { return fieldSetFlags()[1]; } - /** Clears the value of the 'name' field */ + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder clearName() { name = null; fieldSetFlags()[1] = false; return this; } - /** Gets the value of the 'nicknames' field */ + /** + * Gets the value of the 'nicknames' field. + * @return The value. + */ public java.util.List<java.lang.String> getNicknames() { return nicknames; } - /** Sets the value of the 'nicknames' field */ + /** + * Sets the value of the 'nicknames' field. + * @param value The value of 'nicknames'. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder setNicknames(java.util.List<java.lang.String> value) { validate(fields()[2], value); this.nicknames = value; @@ -294,24 +416,38 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor return this; } - /** Checks whether the 'nicknames' field has been set */ + /** + * Checks whether the 'nicknames' field has been set. + * @return True if the 'nicknames' field has been set, false otherwise. + */ public boolean hasNicknames() { return fieldSetFlags()[2]; } - /** Clears the value of the 'nicknames' field */ + + /** + * Clears the value of the 'nicknames' field. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder clearNicknames() { nicknames = null; fieldSetFlags()[2] = false; return this; } - /** Gets the value of the 'relatedids' field */ + /** + * Gets the value of the 'relatedids' field. + * @return The value. + */ public java.util.List<java.lang.Integer> getRelatedids() { return relatedids; } - /** Sets the value of the 'relatedids' field */ + /** + * Sets the value of the 'relatedids' field. + * @param value The value of 'relatedids'. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder setRelatedids(java.util.List<java.lang.Integer> value) { validate(fields()[3], value); this.relatedids = value; @@ -319,24 +455,38 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor return this; } - /** Checks whether the 'relatedids' field has been set */ + /** + * Checks whether the 'relatedids' field has been set. + * @return True if the 'relatedids' field has been set, false otherwise. + */ public boolean hasRelatedids() { return fieldSetFlags()[3]; } - /** Clears the value of the 'relatedids' field */ + + /** + * Clears the value of the 'relatedids' field. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder clearRelatedids() { relatedids = null; fieldSetFlags()[3] = false; return this; } - /** Gets the value of the 'typeEnum' field */ + /** + * Gets the value of the 'typeEnum' field. + * @return The value. + */ public org.apache.avro.TypeEnum getTypeEnum() { return typeEnum; } - /** Sets the value of the 'typeEnum' field */ + /** + * Sets the value of the 'typeEnum' field. + * @param value The value of 'typeEnum'. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder setTypeEnum(org.apache.avro.TypeEnum value) { validate(fields()[4], value); this.typeEnum = value; @@ -344,12 +494,19 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor return this; } - /** Checks whether the 'typeEnum' field has been set */ + /** + * Checks whether the 'typeEnum' field has been set. + * @return True if the 'typeEnum' field has been set, false otherwise. + */ public boolean hasTypeEnum() { return fieldSetFlags()[4]; } - /** Clears the value of the 'typeEnum' field */ + + /** + * Clears the value of the 'typeEnum' field. + * @return This builder. + */ public org.apache.avro.FooBarSpecificRecord.Builder clearTypeEnum() { typeEnum = null; fieldSetFlags()[4] = false; @@ -357,6 +514,7 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor } @Override + @SuppressWarnings("unchecked") public FooBarSpecificRecord build() { try { FooBarSpecificRecord record = new FooBarSpecificRecord(); @@ -366,26 +524,30 @@ public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecor record.relatedids = fieldSetFlags()[3] ? this.relatedids : (java.util.List<java.lang.Integer>) defaultValue(fields()[3]); record.typeEnum = fieldSetFlags()[4] ? this.typeEnum : (org.apache.avro.TypeEnum) defaultValue(fields()[4]); return record; - } catch (Exception e) { + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { throw new org.apache.avro.AvroRuntimeException(e); } } } - private static final org.apache.avro.io.DatumWriter - WRITER$ = new org.apache.avro.specific.SpecificDatumWriter<FooBarSpecificRecord>(SCHEMA$); + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<FooBarSpecificRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<FooBarSpecificRecord>)MODEL$.createDatumWriter(SCHEMA$); @Override public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException { - WRITER$.write(this, org.apache.avro.specific.SpecificData.getEncoder(out)); + WRITER$.write(this, SpecificData.getEncoder(out)); } - private static final org.apache.avro.io.DatumReader - READER$ = new org.apache.avro.specific.SpecificDatumReader<FooBarSpecificRecord>(SCHEMA$); + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<FooBarSpecificRecord> + READER$ = (org.apache.avro.io.DatumReader<FooBarSpecificRecord>)MODEL$.createDatumReader(SCHEMA$); @Override public void readExternal(java.io.ObjectInput in) throws java.io.IOException { - READER$.read(this, org.apache.avro.specific.SpecificData.getDecoder(in)); + READER$.read(this, SpecificData.getDecoder(in)); } } http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm ---------------------------------------------------------------------- diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm index 1e314f3..de7fd1c 100644 --- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm +++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm @@ -442,7 +442,12 @@ public class ${this.mangle($schema.getName())}#if ($schema.isError()) extends or #foreach ($field in $schema.getFields()) #if (${this.hasBuilder($field.schema())}) if (${this.mangle($field.name(), $schema.isError())}Builder != null) { - record.${this.mangle($field.name(), $schema.isError())} = this.${this.mangle($field.name(), $schema.isError())}Builder.build(); + try { + record.${this.mangle($field.name(), $schema.isError())} = this.${this.mangle($field.name(), $schema.isError())}Builder.build(); + } catch (org.apache.avro.AvroMissingFieldException e) { + e.addParentField(record.getSchema().getField("${this.mangle($field.name(), $schema.isError())}")); + throw e; + } } else { #if ($this.hasLogicalTypeField($schema)) record.${this.mangle($field.name(), $schema.isError())} = fieldSetFlags()[$field.pos()] ? this.${this.mangle($field.name(), $schema.isError())} : #if(${this.javaType($field.schema())} != "java.lang.Object")(${this.javaType($field.schema())})#{end} defaultValue(fields()[$field.pos()], record.getConversion($field.pos())); @@ -459,6 +464,8 @@ public class ${this.mangle($schema.getName())}#if ($schema.isError()) extends or #end #end return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; } catch (java.lang.Exception e) { throw new org.apache.avro.AvroRuntimeException(e); } http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/ipc/src/test/java/org/apache/avro/specific/TestSpecificBuilderTree.java ---------------------------------------------------------------------- diff --git a/lang/java/ipc/src/test/java/org/apache/avro/specific/TestSpecificBuilderTree.java b/lang/java/ipc/src/test/java/org/apache/avro/specific/TestSpecificBuilderTree.java index 6a69833..1a0a486 100644 --- a/lang/java/ipc/src/test/java/org/apache/avro/specific/TestSpecificBuilderTree.java +++ b/lang/java/ipc/src/test/java/org/apache/avro/specific/TestSpecificBuilderTree.java @@ -17,6 +17,7 @@ */ package org.apache.avro.specific; +import org.apache.avro.AvroMissingFieldException; import org.apache.avro.test.http.*; import org.apache.avro.test.nullable.Nullable; import org.apache.avro.test.nullable.RecordWithNullables; @@ -71,10 +72,15 @@ public class TestSpecificBuilderTree { return requestBuilder; } - @Test(expected = org.apache.avro.AvroRuntimeException.class) + @Test(expected = AvroMissingFieldException.class) public void failOnIncompleteTree() { - Request.Builder requestBuilder = createPartialBuilder(); - Request request = requestBuilder.build(); + try { + createPartialBuilder().build(); + } catch (AvroMissingFieldException amfe) { + assertEquals("Field networkAddress type:STRING pos:1 not set and has no default value", amfe.getMessage()); + assertEquals("Path in schema: --> connection --> networkAddress", amfe.toString()); + throw amfe; + } fail("Should NEVER get here"); } http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java ---------------------------------------------------------------------- diff --git a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java index 55fabe0..569f427 100644 --- a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java +++ b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java @@ -446,6 +446,8 @@ public class Player extends org.apache.avro.specific.SpecificRecordBase implemen record.last_name = fieldSetFlags()[2] ? this.last_name : (java.lang.String) defaultValue(fields()[2]); record.position = fieldSetFlags()[3] ? this.position : (java.util.List<avro.examples.baseball.Position>) defaultValue(fields()[3]); return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; } catch (java.lang.Exception e) { throw new org.apache.avro.AvroRuntimeException(e); } http://git-wip-us.apache.org/repos/asf/avro/blob/ff5099c8/lang/java/tools/src/test/compiler/output/Player.java ---------------------------------------------------------------------- diff --git a/lang/java/tools/src/test/compiler/output/Player.java b/lang/java/tools/src/test/compiler/output/Player.java index 53ac1af..5bbb3b0 100644 --- a/lang/java/tools/src/test/compiler/output/Player.java +++ b/lang/java/tools/src/test/compiler/output/Player.java @@ -446,6 +446,8 @@ public class Player extends org.apache.avro.specific.SpecificRecordBase implemen record.last_name = fieldSetFlags()[2] ? this.last_name : (java.lang.CharSequence) defaultValue(fields()[2]); record.position = fieldSetFlags()[3] ? this.position : (java.util.List<avro.examples.baseball.Position>) defaultValue(fields()[3]); return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; } catch (java.lang.Exception e) { throw new org.apache.avro.AvroRuntimeException(e); }
