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

Cherry Development commented on AVRO-2621:
------------------------------------------

Great question, and yes, you pretty much have it figured out. In my example I 
have a separate maven module/library (avromoneyutils) from my application 
module which contains the MoneyConversion and MoneyLogicalTypeFactory classes 
in it.

So, in my application I will have:
{code:java}
<dependencies>
  <dependency><artifactId>avromoneyutils</artifactId>…</dependency>
<dependencies>
…
<build><plugins><plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.10.0-SNAPSHOT</version>
<dependencies>
    <dependency>
        <artifactId>avromoneyutils</artifactId>
        …
    </dependency>
</dependencies>
…<!-- execution configuration here -->
</plugin>…</plugins></build>

{code}
So ya, by default a maven plugin in the generate-sources phase is not going to 
have access to the classes of the module that it's executing (because those 
classes haven't been compiled yet), but avromoneyutils is a separate module 
which has already been compiled, so if you add it as a explicit dependency of 
the plugin, it can load the MoneyConversion and MoneyLogicalTypeFactory classes 
while it runs. avromoneyutils is also included as a regular dependency of the 
application module.

I like the idea of ServiceLoader, but presumably we would also expect that at 
runtime any LogicalTypeFactories and Conversions would automatically be loaded 
into the avro runtime, not just for the purposes of the code generation. That 
would be a much larger change to avro than just the change to the maven plugin 
that I'm proposing here. Since my change only affects the plugin's execution 
when generating sources, you still need to tell Avro about the logical type at 
runtime, such as:
{code:java}
SpecificData.get().addLogicalTypeConversion(new MoneyConversion());{code}
Other potential methods of doing this could be with annotation processing, but 
again, this is beyond the scope of what I'm proposing.

> Practical CustomConversions with SpecificCompiler and Maven
> -----------------------------------------------------------
>
>                 Key: AVRO-2621
>                 URL: https://issues.apache.org/jira/browse/AVRO-2621
>             Project: Apache Avro
>          Issue Type: Improvement
>          Components: java
>            Reporter: Cherry Development
>            Priority: Major
>              Labels: maven
>
> So, as seen in AVRO-2498 we now have the ability in 1.9, at least using the 
> Maven tools, to have generated classes with a field of type UUID. For some 
> background, the secret sauce to get this working is:
>  * Set the logicalType of the field to 'uuid' and type to 'string'
>  * In the maven plugin configuration, add an item to <customConversions> with 
> the value org.apache.avro.Conversions$UUIDConversion
> I attempted this with a custom type of my own (in this case, joda Money) 
> first by implementing a CustomConversion<Money> class that created a new 
> LogicalType called "money". This did not work, though, because although the 
> maven mojo correctly added the CustomConversion to the SpecificCompiler, when 
> the compiler parses the schema and sees the logicalType of type "money", it 
> attempts to look up the LogicalType from LogicalTypes the LogicalType is not 
> registered and it ignores it, which causes the field within the Schema to not 
> have a logicalType. Without a logicalType, the compiler does not consider it 
> a "UsedConversionClass" (see SpecificCompiler.getUsedConversionClass()) and 
> they velocity template doesn't write the class with the custom field type.
> Trying to be clever, I attempted to work around this by putting a static 
> initializer in my CustomConversion class which called 
> LogicalTypes.register(). Unfortunately for me, the maven plugin doesn't load 
> any of the classes specified in <customConversions> until AFTER it has parsed 
> a schema.
> Obviously, putting a static initializer inside of a CustomConversion should 
> not be part of a solution to this issue, but I propose a very simple solution:
>  * Add a logicalTypes property to AbstractAvroMojo, with items of a new type, 
> LocalTypeDefinition. That type will have a name and a logicalTypeFactory.
>  * Upon startup of the mojo, iterate through each item and call 
> LogicalTypes.register() on each, passing the indicated name and a new 
> instance of the indicated logicalTypeFactory class.
>  * At this point, the existing logic will treat the new custom type the same 
> as "uuid" is treated and will generate SpecificRecord classes with fields of 
> that type.
> I could implement this pretty trivially, if there's an appetite for it. This 
> would seem to be 100% backwards compatible.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to