You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@avro.apache.org by "Samael Bate (Jira)" <ji...@apache.org> on 2023/06/30 09:55:00 UTC

[jira] [Comment Edited] (AVRO-2918) Schema polymorphism

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

Samael Bate edited comment on AVRO-2918 at 6/30/23 9:54 AM:
------------------------------------------------------------

I'd very much like Avro to support this. As a bit of a workaround I've had some luck using 
{{id "io.github.tunguski.interfacer" version "0.0.7"}} in my gradle build along with the avro gradle-plugin. interfacer allows me to post-process my generated Java sources and add Interfaces to classes that have been generated by avro types.
 
{code:java}
// The interfacer plugin allows us to post-process the generated Java source and apply interfaces defined in the src folder
tasks.register("avroInterfacer", pl.matsuo.interfacer.gradle.InterfacerTask) {
    dependsOn generate
    interfacePackage = 'com.domain.schema.core'
    interfacesDirectory = file('src/main/java')
    scanDirectory = file("build/generated/java")
} {code}
on the records I simply annotate them like {{@java-interface("UserAccount")}}
 
Unfortunately though the interfacer plugin only has one release and is a one person project. Ideally I'd like it if Avro itself could support something like this:
 
{code:java}
@interface("pubnub.core.PubNubMessage") // this interface can be defined elsewhere by me
record PubNubPayloadMessage {
    union {
       null,
       CustomerMessagePayload,
       SupportStaffL1Payload,
       SupportStaffL2Payload
    } payload = null;

    pubnub.core.PubNubMetadata metadata;
} {code}
where each of those payload records are annotated with @interface("pubnub.core.PubNubPayload").
 
today, if I call {{getPayload()}} the return type is {_}Object{_}, which we then have cast to the required payload type. 

Ideally it should be able to use generics so we can generate a PubNubPayloadMessage class that implements {{PubNubMessage<PubNubPayload>}} and have getPayload() return the right type.


was (Author: singingbush):
I'd very much like Avro to support this. As a bit of a workaround I've had some luck using 
{{id "io.github.tunguski.interfacer" version "0.0.7"}} in my gradle build along with the avro gradle-plugin. interfacer allows me to post-process my generated Java sources and add Interfaces to classes that have been generated by avro types.
 
{code:java}
// The interfacer plugin allows us to post-process the generated Java source and apply interfaces defined in the src folder
tasks.register("avroInterfacer", pl.matsuo.interfacer.gradle.InterfacerTask) {
    dependsOn generate
    interfacePackage = 'com.domain.schema.core'
    interfacesDirectory = file('src/main/java')
    scanDirectory = file("build/generated/java")
} {code}
on the records I simply annotate them like {{@java-interface("UserAccount")}}
 
Unfortunately though the interfacer plugin only has one release and is a one person project. Ideally I'd like it if Avro itself could support something like this:
 
{code:java}
@interface("pubnub.core.PubNubMessage") // this interface can be defined elsewhere by me
record PubNubPayloadMessage {
    union {
       null,
       CustomerMessagePayload,
       SupportStaffL1Payload,
       SupportStaffL2Payload
    } payload = null;

    pubnub.core.PubNubMetadata metadata;
} {code}
where each of those payload records are annotated with @interface("pubnub.core.PubNubPayload").
 
today, if I call {{getPayload()}} the return type is _Object_ but with this approach it would be _PubNubPayload_

> Schema polymorphism
> -------------------
>
>                 Key: AVRO-2918
>                 URL: https://issues.apache.org/jira/browse/AVRO-2918
>             Project: Apache Avro
>          Issue Type: New Feature
>          Components: logical types, misc, spec
>            Reporter: Jonathan Rapoport
>            Assignee: Christophe Le Saec
>            Priority: Critical
>              Labels: features, pull-request-available
>   Original Estimate: 96h
>          Time Spent: 10m
>  Remaining Estimate: 95h 50m
>
> Include the option to use named types as base types for a new schema. Allow for MRO generation. Field inheritance. 
> The benefits of this approach include:
>  * Defining a schema as validation for a certain wire, and so allowing the receiver to be certain of the structure of the data (this works today). However, defining an extension of this schema, or certain schemas which can be normalized to the original schema, but contain additional information, will not allow it to be sent over the same wire.
>  * Backwards compatibility through inheritance - you never break the old schema, thus allowing a long integration period, with no need to recode all processes familiar with the schema. The new schema will simply inherit the old one, and only add information.
>  * Allow for full data control through polymorphism, and the ability to replace structures within any supported language. 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)