使用maven-shade-plugin和maven-bundle-plugin技术相关联的问题

15

我正在使用maven-shade-plugin在打包阶段重新定位一些包。同时,我还在使用maven-bundle-plugin生成清单。问题是bundle插件在shade插件之前运行(在process-classes阶段),并且在生成的清单导出时不包括任何经过shade处理的包。

我该如何让这两个插件相互配合,以便我的重新定位的包像其他任何包一样被bundle插件处理?

--

根据请求,以下是我的POM中Shade和bundle部分:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <filters>
        <filter>
          <artifact>cglib:cglib</artifact>
          <includes>
            <include>net/sf/cglib/core/**</include>
            <include>net/sf/cglib/proxy/**</include>
          </includes>
        </filter>
      </filters>
      <relocations>
        <relocation>
          <pattern>net.sf.cglib</pattern>
          <shadedPattern>org.modelmapper.internal.cglib</shadedPattern>
        </relocation>
        <relocation>
          <pattern>org.objectweb.asm</pattern>
          <shadedPattern>org.modelmapper.internal.asm</shadedPattern>
        </relocation>
      </relocations>
    </configuration>
  </plugin>

  <plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.3.7</version>
    <executions>
      <execution>
        <id>bundle-manifest</id>
        <phase>process-classes</phase>
        <goals>
          <goal>manifest</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <instructions>
        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
        <Export-Package>
          org.modelmapper,
          org.modelmapper.builder,
          org.modelmapper.config,
          org.modelmapper.convention,
          org.modelmapper.spi
        </Export-Package>
        <Private-Package>
          org.modelmapper.internal.**
        </Private-Package>
        <Import-Package>
          *
        </Import-Package>
        <Include-Resource>
          {maven-resources},
          {maven-dependencies}
        </Include-Resource>
      </instructions>
    </configuration>
  </plugin>

取自此处


@vikingsteve - 是的,OSGI。你指的是哪些标签? - Jonathan
如果您删除与_process-classes_和_package_绑定的执行,然后从命令行运行mvn compile shade:shade bundle:manifest package,那么清单是否正确生成? - Anthony Accioly
1
@Jonathan 我的意思是建议将OSGi标签添加到你的问题中,看起来已经完成了 :) - vikingsteve
@AnthonyAccioly 从插件中删除执行操作会导致类似于“无法在项目modelmapper上执行目标org.apache.maven.plugins:maven-shade-plugin:2.1:shade(default-cli),无法创建阴影工件,项目主要工件不存在。”的错误...这取决于我执行的目标。是的,我正在使用mvn 3.0.3。 - Jonathan
奇怪,你的打包类型是什么?JAR (<packaging>jar</packaging>) 还是 Bundle?尝试将这两个插件绑定到 package 阶段(确保 Maven Bundle 在插件列表中出现在 Maven Shade 之后)。它是否正确打包了 Bundle 并添加了所需的元数据? - Anthony Accioly
显示剩余5条评论
4个回答

7
另一种选择是完全放弃maven bundle插件,使用Maven Shade插件ManifestResourceTransformer将所需的OSGI元数据添加到清单中。
请查看xbean-asm-shaded/pom.xml以获取示例。
<transformers>
  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    <manifestEntries>
      <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
      <Export-Package>
        org.apache.xbean.asm;org.modelmapper.builder; ...
      </Export-Package>
      <Import-Package>*</Import-Package>
      <Private-Package>org.modelmapper.internal ...</Private-Package>
   </manifestEntries>
</transformer>

2
解决方案非常简单。您仍然可以同时使用maven-bundle-plugin和maven-shade-plugin。您只需要记住顺序。如果您使用bundle打包,则maven bundle插件将在package阶段之前执行maven-shade。但这并不是那么错误的。
以下是步骤:
- 使用Private-Package: pkg.name.before.shading - 使maven-shade-plugin具有一个 null:null - 这将防止shade插件创建空jar - 使用maven-shade-plugin重定位 - 从pkg.name.before.shading到other.pkg。
您可以在FasterXML jackson-module-paranamer中看到此技巧的运作。

这个方案在你想要导出阴影包本身时就无法完美运作了。这里提出的解决方案只会包括来自src/main/java的包。 - Andy Tolbert

0

有一个非常棒的transformer实现了来自Hazelcast的这个功能 - HazelcastManifestTransformer (ver 3.9)。它的作用是巧妙地合并Import-PackageExport-Package属性,使用户能够排除扩展/减少默认合并结果。

如何在您的pom.xml中使用它:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.1.0</version>
  <dependencies>
    <dependency>
      <groupId>com.hazelcast</groupId>
      <artifactId>hazelcast-build-utils</artifactId>
      <version>3.9</version>
    </dependency>
  </dependencies>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <transformers>
          <transformer implementation="com.hazelcast.buildutils.HazelcastManifestTransformer">
            <mainClass>...</mainClass>
            <!-- the tag below is required due to a missing null-check it seems -->
            <overrideInstructions></overrideInstructions>
      </configuration>
    </executions>
</plugin>

重写指令(Export/Import-Package)是逗号分隔的包名称,每当我们想要从列表中排除那些特定的包时,就会在前面加上感叹号。

希望这可以帮助您!我知道这是一个旧问题,但似乎Hazelcast的转换器并没有得到太多的宣传。


0

我假设在compile阶段完成后,您想要:

  1. 使用shade插件重定位一些类
  2. 使用bundle插件创建清单
  3. 使用jar插件打包所有内容

问题是bundle插件在shade插件之前运行

bundle插件绑定到process-classes阶段,该阶段beforepackage阶段,而shade插件则绑定到package阶段。

建议将shade插件也绑定到process-classes阶段。更改shade插件配置如下:

<phase>process-classes</phase>

由于pom文件中shade插件的定义在bundle插件定义之前,所以在process-classes阶段,shade插件将先于bundle插件运行。


1
很遗憾,这不起作用。它会出现类似于以下内容的错误:Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:2.1:shade (default) on project modelmapper: Failed to create shaded artifact, project main artifact does not exist. - Jonathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接