如何在Avro Union逻辑类型字段中指定转换器的默认值?

时间:2017-08-09 03:55:28

标签: java maven avro

我有以下Avro架构:

views.py

我使用maven生成Java文件。 Avro配置:

{
   "namespace":"com.example",
   "type":"record",
   "name":"BuggyRecord",
   "fields":[
      {
         "name":"my_mandatory_date",
         "type":{
            "type":"long",
            "logicalType":"timestamp-millis"
         },
         "default":1502250227187
      },
      {
         "name":"my_optional_date",
         "type":[
            {
               "type":"long",
               "logicalType":"timestamp-millis"
            },
            "null"
         ],
         "default":1502250227187
      }
   ]
}

通过 <plugin> <groupId>org.apache.avro</groupId> <artifactId>avro-maven-plugin</artifactId> <version>1.8.2</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>schema</goal> <!--<goal>idl-protocol</goal>--> </goals> <configuration> <sourceDirectory>${project.basedir}/src/main/avro</sourceDirectory> <outputDirectory>${project.basedir}/src/main/java</outputDirectory> <enableDecimalLogicalType>true</enableDecimalLogicalType> <stringType>String</stringType> </configuration> </execution> </executions> </plugin> 代码生成的类在一些基本代码上失败:

mvn compile

错误代码:

@Test
public void Foo(){
    BuggyRecord.Builder buggyRecordBuilder = BuggyRecord.newBuilder();
    buggyRecordBuilder.build();
}

我认为这是由于org.apache.avro.AvroRuntimeException: java.lang.ClassCastException: java.lang.Long cannot be cast to org.joda.time.DateTime at com.example.BuggyRecord$Builder.build(BuggyRecord.java:301) at BuggyRecordTest.Foo(BuggyRecordTest.java:10) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to org.joda.time.DateTime at com.example.BuggyRecord$Builder.build(BuggyRecord.java:298) ... 23 more 没有正确生成:

Converters

是我误用了代码生成器还是错误?

3 个答案:

答案 0 :(得分:0)

  {
     "name":"my_optional_date",
     "type":[ "null", {"type" : "long", "logicalType": "timestamp-millis"}], "default": null
  }

更多解决方法而不是解决方案-将“ null”类型放在首位,将“ default”类型放在首位:null

答案 1 :(得分:0)

我们遇到了一个类似的问题,日期的逻辑类型:

{
  "name": "date_field",
  "type": [
    "null",
    {
      "type": "int",
      "logicalType": "date"
    }
  ],
  "default": null
}

我们需要更新gradle插件0.17.0的最新版本(gradle-avro-plugin)和Apache Avro依赖项(1.9.1)。

同样在gradle构建文件中,我们需要添加

avro {
  dateTimeLogicalType = "JODA"
}

以及对joda-time

的依赖
dependencies {
    compile "joda-time:joda-time:2.10.3"
}

gradle-avro-plugin使用的默认dateTimeLogicalType是JSR310,但这仍然会导致错误(即使我们使用的是Java 8)。

答案 2 :(得分:0)

尝试将avro的版本以avro依赖性升级到1.9.X,并将pom.xml中的avro-maven-plugin升级

    <dependency>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro</artifactId>
        <version>1.9.1</version>
    </dependency>

    <plugin>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro-maven-plugin</artifactId>
        <version>1.9.1</version>
        <executions>
            <execution>
                <phase>generate-sources</phase>
                <goals>
                    <goal>schema</goal>
                    <!--<goal>idl-protocol</goal>-->
                </goals>
                <configuration>
                    <sourceDirectory>${project.basedir}/src/main/avro</sourceDirectory>
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <enableDecimalLogicalType>true</enableDecimalLogicalType>
                    <stringType>String</stringType>
                </configuration>
            </execution>
        </executions>
    </plugin>

还要确保从AVRO模式中删除以前生成的类,并进行mvn编译。