【问题标题】:Apache Avro Maven Plugin generate UUID field instead of StringApache Avro Maven 插件生成 UUID 字段而不是字符串
【发布时间】:2019-11-03 06:31:32
【问题描述】:

鉴于以下 Avro 架构:

{
    "namespace": "ro.dspr.coreentities",
    "type": "record",
    "name": "Organization",
    "fields": [
      {
        "name": "id",
        "type": "string",
        "logicalType": "uuid"
      },
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "description",
        "type": "string"
      }
    ]
}

运行 avro-maven-plugin 1.9.0 目标 schema,我得到:

@org.apache.avro.specific.AvroGenerated
public class Organization extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {

  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"Organization\",\"namespace\":\"ro.dspr.coreentities\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"logicalType\":\"uuid\"},{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"description\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}");

  // truncated 

  @Deprecated public java.lang.String id;
  @Deprecated public java.lang.String name;
  @Deprecated public java.lang.String description;

  // truncated
}

我希望为组织生成的 POJO 具有 id UUID,而不是字符串(我现在拥有的)。

我看过的链接:

我确实看到了 logical type def from Avro 并且有 Conversion class 我实际上正在尝试触发,但我无法连接这些点。

其他

相关的 Maven pom 部件

<plugin>
  <groupId>org.apache.avro</groupId>
  <artifactId>avro-maven-plugin</artifactId>
  <version>${avro.version}</version>
  <configuration>
    <sourceDirectory>${avro-files-path}</sourceDirectory>
    <outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
    <stringType>String</stringType>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>schema</goal>
      </goals>
      <configuration>
        <sourceDirectory>${avro-files-path}</sourceDirectory>
        <outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

额外信息

我实际上尝试使用 Avro 为我的 Kafka 消息提供结构。我也在使用 Confluent Schema Registry 和 Confluent Avro Kafka Serializer。尽管如此,我认为我只会将 id 作为字符串,但如果我尝试将消息作为非 UUID 的东西发送到 Kafka,它稍后会失败。但是,我发现实际上没有任何约束,并且我设法将任何字符串发送到 Kafka。所以,Avro 中的“logicalType”根本没有强制执行。

问题

  1. 如何将 Organization.class#id 生成为 UUID?
  2. 如果在执行此操作时没有 Avro 支持,解决方法是什么(最好重用 org.apache.avro.Conversions.UUIDConversion)?

【问题讨论】:

  • 您是否尝试过“logicalType”:“uuid”,从文档看来它需要小写。
  • 这实际上是我尝试过的第一件事,但没有成功。在 POJO 的 schema 中,logicalType uuid 存在(并且正确识别,因为不能放任何东西,否则会失败)
  • 你找到方法了吗?
  • 嗨。不,但说实话,从那以后我就没有尝试过。

标签: java maven code-generation avro


【解决方案1】:

这是一个功能示例:

架构:

{
  "name": "pk",
  "type": {"type": "string", "logicalType": "uuid"}
},

Maven 配置:

            <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>
                        </goals>
                        <configuration>
                            <sourceDirectory>${project.basedir}/../avro/schemas/commands</sourceDirectory>
                            <outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory>
                            <!-- TODO Enable this string type once we have 1.10.0 release, or 1.9.2-->
                            <!--<stringType>String</stringType>-->
                            <fieldVisibility>PRIVATE</fieldVisibility>
                            <customConversions>org.apache.avro.Conversions$UUIDConversion</customConversions>
                            <imports>
                                <import>${project.basedir}/../avro/schemas/common</import>
                                <import>${project.basedir}/../avro/schemas/commands/account</import>
                                <import>${project.basedir}/../avro/schemas/commands/rec</import>
                            </imports>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

需要注意的重要一点是,在当前版本的插件中 UUIDConversion 和 String 之间存在冲突,因此您需要选择哪个更重要,或者使用具有修复的 1.10.0-SNAPSHOT已合并,但尚未发布。

【讨论】:

  • 即使没有 stringType 和 customConversions,生成的 java 类仍然期望 CharSequence 作为我端设置器的参数。
  • 非常感谢!为了解决 uuid 问题,我整天头疼
  • @singe3 你能解决吗,对我来说它仍然需要 ``` private java.lang.CharSequence id;```。我正在使用 1.10.2 版本的 Maven 插件。预期的类型是什么,你是如何传递 uuid 的?
  • @bestwishes 我目前使用的是 avro-maven-pkugin 版本 1.10.2,但架构不同。我不使用“字符串”类型,因为它使用 UTF-8 编码(每个字符串 uuid 36 个字节)会浪费空间。我使用“bytes”类型(每个 uuid 16 个字节): {"name":"uuid","type":{"type":"bytes","logicalType":"uuid","CustomEncoding":"UUIDAsBytesEncoding "}} 最后,对于解码,我有一个简单的 CustomEncoding (UUIDAsBytesEncoding) 实现,它从/到 byte[] UUID 和一个简单的 Conversion 实现,以在生成的类中生成正确的 UUID 字段。为我工作。
  • @bestwishes 如果您需要针对具体案例的更多信息,我建议您写一个包含所有详细信息的问题,我很乐意查看。这里的评论仅限于为您带来正确的详细答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 2020-07-30
  • 2016-03-25
  • 2020-09-06
  • 2014-09-26
  • 2012-01-30
  • 1970-01-01
相关资源
最近更新 更多