Maven 从依赖 jar 导入 avro 定义

Maven import avro definition from dependant jar

我有两个使用 avro-maven-plugin 进行代码生成的 Maven 项目。我面临的问题 是这些项目之一有一个 avro 对象,它使用对另一个 avro 对象的引用 第二个maven项目。尽管我将第二个项目生成的 jar 作为 maven 依赖项包含在内,但我无法找到为第二个项目生成代码的方法。

本质上考虑我的第二个项目有一个如下所示的 avro 定义的情况

{
  "namespace": "my.second.project.avro",
  "name": "listNode",
  "type": "record",
  "fields":[
        {
            "name":"eventList",
            "type":{
                "type": "array",  
                "items": "my.first.project.AvroDefinition.avsc"
            }
         }
    ] 
}

在此定义中,它指的是 AvroDefinition.avsc,它包含在依赖项 jar 之一中, 但我找不到任何方法来提取 AvroDefinition.avsc 并将其用于代码生成 第二个项目。 顺便说一下,avro-maven-plugin 的设置如下:

   <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>protocol</goal>
                    <goal>idl-protocol</goal>
                </goals>
                <configuration>
                    <imports>
                        <import>${project.basedir}/src/main/avro/include/</import>
                    </imports>
                    <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>                        
                    <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
                    <stringType>String</stringType>
                </configuration>
            </execution>
        </executions>
    </plugin>

我得到的错误如下:

Execution default of goal org.apache.avro:avro-maven-plugin:1.9.1:schema failed: 
Undefined name: "my.first.project.AvroDefinition.avsc"

无论如何,我希望我可以使用 maven 远程资源插件,但我无法让它工作,所以我的问题是这怎么可能?如何从依赖 jar 导入 avro 定义以生成我的代码?

我终于找到了解决方案,不过更多的是解决方法,使用两个 Maven 插件 (maven-resources-plugin) 和 (maven-remote-resources-plugin)。

本质上第一个插件(maven-resources-plugin)只是用来将avsc文件复制到项目的资源目录所以如果你已经在指定目录中有文件你可以省略这一步

实际工作是通过 (maven-remote-resources-plugin) 完成的,它需要在 src/main/resources 目录中找到要包含在 jar 中的文件(顺便说一句,由于某种原因我无法使用插件上的选项)(因此是上面的步骤)

<plugin>
   <artifactId>maven-remote-resources-plugin</artifactId>
   <version>1.6.0</version>
   <executions>
     <execution>
       <goals>
         <goal>bundle</goal>
       </goals>
     </execution>
   </executions>
   <configuration>
     <includes>
        <include>**/*.avsc</include>
     </includes>
   </configuration>
</plugin>

这样做可以确保 avsc 文件包含在 jar 中,然后在你的第二个 project/module 中你需要从插件中执行这个目标(见下文)以提取 avsc 文件并生成代码

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-remote-resources-plugin</artifactId>
    <version>1.6.0</version>
    <configuration>
      <resourceBundles>
        <resourceBundle>{groupId}:{artifactId}:{version}</resourceBundle>
      </resourceBundles>
    </configuration>
    <executions>
      <execution>
        <phase>generate-sources</phase>
        <goals>
          <goal>process</goal>
        </goals>
      </execution>
    </executions>
</plugin>

注意两件事,首先在 resourceBundles 选项中包含依赖 jar,其次将执行阶段设置为 generate-sources 而不是默认的 generate-resources 否则它将无法工作,因为 avro-maven-plugin 可以在 generate-sources 生命周期上执行,到那时它应该有 avsc 文件。

作为最后的说明,您还应该在 avro-maven-plugin 的导入部分包含以下行

<import>${project.build.directory}/maven-shared-archive-resources/</import>

这基本上是默认情况下从 maven-remote-resources-plugin 导出 avsc 文件的目录

基于已接受的答案,我仅使用 maven-remote-resources-plugin 就可以让它工作。打开 Maven 调试日志后,我注意到没有远程资源包被导入,即使它们正在创建。这是由于每个依赖 JAR 中的空 remote-resources.xml 文件。

另一个 post 为我指明了正确的方向,Maven remote resource plugin issue

我需要添加

<includes>
    <include>**/*.avsc</include>
</includes>

到每个依赖中的maven-remote-resource-plugin配置pom.xml

在主项目的 pom.xml 中,我需要显式导入每个远程模式,以避免 NullPointerException。我将其添加到 pom.xml

中 Avro 插件的配置中
<imports>
    <import>${project.build.directory}/maven-shared-archive-resources/MyAvroSchema.avsc</import>
</imports>

这是另一种方法 - 从 jar 文件中提取模式并使用模式生成 java 类

添加 maven 依赖插件以拉取 avro jar 并将架构文件解压到所需位置

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>com.company.events.schema</groupId>
                        <artifactId>avro</artifactId>
                        <version>${avro.version}</version>
                        <outputDirectory>${project.build.outputDirectory}/avro</outputDirectory>
                        <type>jar</type>
                        <includes>**/common-header.avsc,**/label*.avsc</includes>
                    </artifactItem>
                </artifactItems>
            </configuration>
            <executions>
                <execution>
                    <id>unpack</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>unpack</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

然后添加maven-avro-plugin生成代码

         <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>
                    </goals>
                    <configuration>
                        <imports>${project.build.outputDirectory}/avro/common-header.avsc</imports>
                        <sourceDirectory>${project.build.outputDirectory}/avro</sourceDirectory>
                        <outputDirectory>${project.build.directory}/generated-sources/avro</outputDirectory>
                        <fieldVisibility>PRIVATE</fieldVisibility>
                        <includes>
                            <include>**/*.avsc</include>
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>