Search code examples
javaavro

Avro schema file references in a Avro schema


I have nearly 100 avsc files and most of these avsc files refer to another asvc file usually as their type. To give an example

Item.avsc in ./com/example/common

{
    "namespace":"com.example.common",
    "name":"Item",
    "type":"record",
    "fields":[
        {
            "name":"itemId",
            "type":"com.example.common.ItemId"
        },
        {
            "name":"features",
            "type":"com.example.common.Features"
        }
    ]
}

ItemId.avsc in ./com/example/common

{
    "namespace":"com.example.common",
    "name":"ItemId",
    "type":"record",
    "fields":[
        {
            "name":"id",
            "type":"int"
        }
    ]
}

Features.avsc in ./com/example/common

{
    "namespace":"com.example.common",
    "name":"Features",
    "type":"record",
    "fields":[
        {
            "name":"Range",
            "type":{
                "type":"array",
                "items":"com.example.common.Range"
            }
        }
    ]
}

When I want to parse the schema of Item.avsc it raises:

Schema schema = new Schema.Parser().parse(new File(".\\com\\example\\common\\Item.avsc"));

Exception in thread "main" org.apache.avro.SchemaParseException: "com.example.common.ItemId" is not a defined name. The type of the "itemId" field must be a defined name or a {"type": ...} expression.

I found a workaround to this problem by using a single instance of a parser to parse the ItemId.avsc and Features.avsc first, then the Item.avsc, like below:

Parser parser = new Parser();
parser.parse(new File(".\\com\\example\\common\\ItemId.avsc"));
parser.parse(new File(".\\com\\example\\common\\Features.avsc"));
parser.parse(new File(".\\com\\example\\common\\Range.avsc"));
parser.parse(new File(".\\com\\example\\common\\Item.avsc"));

But I have nearly 100 avsc files that most of them references multiple avsc files and I need to parse each one like this while considering their dependency rank. Is there a better solution to this?


Solution

  • Iterate through your packages, and parse them over a loop.

    Schema.Parser parser = new Schema.Parser();
    URI uri = Test.class.getResource("package/name/here").toURI();
    Path myPath = Paths.get(uri);
    try (Stream<Path> paths = Files.walk(myPath)) {
         paths.filter(Files::isRegularFile)
              .filter(path -> path.toString().endsWith(".avsc"))
              .map(path -> new File(path.toUri()))
              .forEach(file -> {
                  try {
                     parser.parse(file);
                  } catch (IOException e) {}
              });
    }