Je peux faire,
{
"type": "record",
"name": "Foo",
"fields": [
{"name": "bar", "type": {
"type": "record",
"name": "Bar",
"fields": [ ]
}}
]
}
et cela fonctionne bien, mais en supposant que je veuille diviser le schéma en deux fichiers tels que:
{
"type": "record",
"name": "Foo",
"fields": [
{"name": "bar", "type": "Bar"}
]
}
{
"type": "record",
"name": "Bar",
"fields": [ ]
}
Avro a-t-il la capacité de le faire?
Oui c'est possible.
C'est ce que j'ai fait dans mon projet Java en définissant les fichiers de schéma courants dans avro-maven-plugin Exemple:
search_result.avro:
{"namespace": "com.myorg.other",
"type": "record",
"name": "SearchResult",
"fields": [
{"name": "type", "type": "SearchResultType"},
{"name": "keyWord", "type": "string"},
{"name": "searchEngine", "type": "string"},
{"name": "position", "type": "int"},
{"name": "userAction", "type": "UserAction"}
]
}
search_suggest.avro:
{"namespace": "com.myorg.other",
"type": "record",
"name": "SearchSuggest",
"fields": [
{"name": "suggest", "type": "string"},
{"name": "request", "type": "string"},
{"name": "searchEngine", "type": "string"},
{"name": "position", "type": "int"},
{"name": "userAction", "type": "UserAction"},
{"name": "timestamp", "type": "long"}
]
}
user_action.avro:
{"namespace": "com.myorg.other",
"type": "enum",
"name": "UserAction",
"symbols": ["S", "V", "C"]
}
search_result_type.avro
{"namespace": "com.myorg.other",
"type": "enum",
"name": "SearchResultType",
"symbols": ["O", "S", "A"]
}
configuration du plugin avro-maven:
<plugin>
<groupId>org.Apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.7.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/main/resources/avro</sourceDirectory>
<outputDirectory>${project.basedir}/src/main/Java/</outputDirectory>
<includes>
<include>**/*.avro</include>
</includes>
<imports>
<import>${project.basedir}/src/main/resources/avro/user_action.avro</import>
<import>${project.basedir}/src/main/resources/avro/search_result_type.avro</import>
</imports>
</configuration>
</execution>
</executions>
</plugin>
Vous pouvez également définir plusieurs schémas à l'intérieur d'un fichier:
schemas.avsc:
[
{
"type": "record",
"name": "Bar",
"fields": [ ]
},
{
"type": "record",
"name": "Foo",
"fields": [
{"name": "bar", "type": "Bar"}
]
}
]
Si vous voulez réutiliser les schémas à plusieurs endroits, ce n'est pas super Nice mais cela améliore beaucoup la lisibilité et la maintenabilité à mon avis.
Je suppose que votre motivation est (comme la mienne) de structurer votre définition de schéma et d’éviter les erreurs de copier-coller.
Pour cela, vous pouvez également utiliser Avro IDL . Cela permet de définir des schémas avro à un niveau supérieur. La réutilisation de types est possible dans le même fichier et aussi dans plusieurs fichiers .
Pour générer les fichiers .avsc, exécutez
$ Java -jar avro-tools-1.7.7.jar idl2schemata my-protocol.avdl
Les fichiers .avsc obtenus ressembleront beaucoup à votre exemple initial, mais comme ils sont générés à partir du fichier .avdl, vous ne vous perdrez pas au format json.
L'ordre des importations dans pom.xml est important. Vous devez d'abord importer les sous-types avant de traiter les autres.
<imports>
<import>${project.basedir}/src/main/resources/avro/Bar.avro</import>
<import>${project.basedir}/src/main/resources/avro/Foo.avro</import>
</imports>
Cela débloquerait le codegen d'émettre l'erreur undefined name: Bar.avro
.
Vous devez importer le fichier avsc dans le plugin avro-maven où vous avez écrit le schéma d'objet que vous souhaitez réutiliser
<plugin>
<groupId>org.Apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>${avro.maven.plugin.version}</version>
<configuration>
<stringType>String</stringType>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>src/main/Java/com/xyz/avro</sourceDirectory> // Avro directory
<imports>
<import>src/main/Java/com/xyz/avro/file.avsc</import> // Import here
</imports>
</configuration>
</execution>
</executions>
D'après ce que j'ai pu comprendre jusqu'à présent, non.
Il existe un bon article sur quelqu'un qui a codé sa propre méthode pour le faire ici: