5

I've been using Shade to relocate a dependency from com.package.x to com.package.y; when I build with Maven, it complains due to incompatible types - so I have to change my import statements inside my code to match com.package.y.

Is this really the only way to go about this? Changing the imports is making IntelliJ complain and basically breaks IDE integration. Is there no way Shade can modify the imports?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
whitfin
  • 4,539
  • 6
  • 39
  • 67

2 Answers2

1

This issue can be fixed by seting shadedArtifactAttached to true in configuration tag.

<shadedArtifactAttached>true</shadedArtifactAttached>

Complete example and Reference: https://maven.apache.org/plugins/maven-shade-plugin/examples/attached-artifact.html

I had the same issue and i fixed it by adding the above property. I am sharing my pom.xml of my shaded module just in case if you want to see any other tag values.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.bitguiders.account.management</groupId>
      <artifactId>account-management</artifactId>
      <version>1.0.24-SNAPSHOT</version>
   </parent>
   <artifactId>account-management-metrics-lib</artifactId>
   <name>account-management-metrics-lib</name>
   <description>Bundled client library</description>
   <properties>
      <shaded.package>org.cas.osd.platform.ciam.shaded</shaded.package>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.cas.osd.platform.ciam.account.management</groupId>
         <artifactId>account-management-metrics</artifactId>
         <version>${project.parent.version}</version>
         <scope>compile</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.1</version>
            <executions>
               <execution>
                  <phase>package</phase>
                  <goals>
                     <goal>shade</goal>
                  </goals>
                  <configuration>
                     <shadedArtifactAttached>true</shadedArtifactAttached>
                     <createDependencyReducedPom>true</createDependencyReducedPom>
                     <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
                     <createSourcesJar>true</createSourcesJar>
                     <relocations>
                        <!-- manually hide individual dependencies that a client might conflict with -->
                        <relocation>
                           <pattern>org.</pattern>
                           <shadedPattern>${shaded.package}.org.</shadedPattern>
                           <excludes>
                              <exclude>org.slf4j.**</exclude>
                              <exclude>org.xml.**</exclude>
                              <exclude>org.w3c.**</exclude>
                              <exclude>org.bitguiders.usagemetrics.**</exclude>
                              <exclude>org.bitguiders.**</exclude>
                              <exclude>org.bitguiders.**</exclude>
                              <exclude>org.apache.flume.**</exclude>
                              <exclude>org.apache.http.**</exclude>
                           </excludes>
                        </relocation>
                        <relocation>
                           <pattern>com.</pattern>
                           <shadedPattern>${shaded.package}.com.</shadedPattern>
                           <excludes>
                              <exclude>com.google.common.**</exclude>
                              <exclude>com.sun.xml.bind.xmlDeclaration</exclude>
                           </excludes>
                        </relocation>
                        <relocation>
                           <pattern>javassist</pattern>
                           <shadedPattern>${shaded.package}.javassist</shadedPattern>
                        </relocation>
                        <relocation>
                           <pattern>javax.ws.rs</pattern>
                           <shadedPattern>${shaded.package}.javax.ws.rs</shadedPattern>
                        </relocation>
                        <relocation>
                           <pattern>jersey.repackaged</pattern>
                           <shadedPattern>${shaded.package}.jersey.repackaged</shadedPattern>
                        </relocation>
                        <relocation>
                           <pattern>net.</pattern>
                           <shadedPattern>${shaded.package}.net.</shadedPattern>
                        </relocation>
                     </relocations>
                     <artifactSet>
                        <!-- these external dependencies should be exposed to clients -->
                        <excludes>
                           <exclude>org.slf4j:slf4j-api</exclude>
                           <exclude>org.bitguiders.cpp:cpp-product-usage-ingest-gateway-client</exclude>
                        </excludes>
                     </artifactSet>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>
Waqas Ahmed
  • 1,780
  • 1
  • 14
  • 15
0

The main use case of the shade plugin is to generate an uber-jar while relocating some packages inside of it to prevent conflicts. As a rule you don't want to be developing against an uberjar.

If you actually do want to develop against your shaded jar (or you're solely using shade to relocate an existing jar), then you'll need to list your shaded jar as a in lieu of the original jar, which I would imagine may need you to clean up a cyclic dependency.

Idcmp
  • 659
  • 1
  • 8
  • 19
  • 2
    yeah, I'm trying to bundle jackson with my jar (long story). – whitfin Apr 22 '15 at 20:52
  • Your project should just use jackson normally at com.fasterxml.jackson (or whever it is these days), the shade plugin will take care of pointing all the code in your shaded uberjar at the relocated packages. – Idcmp Apr 22 '15 at 20:55
  • 2
    So you're saying that shade should automatically update the imports? Whenever I run my tests after doing so, it complains about type errors for my package vs com.fasterxml – whitfin Apr 22 '15 at 21:08
  • Perhaps it's due to interdependency between modules? – whitfin Apr 22 '15 at 21:14
  • It sounds like your shaded jar is showing up on the classpath of your tests. As a general rule, I don't like for the exported shaded jar to be the same jar that has tests/etc/etc as it offers a tiny bit of abstraction in case I change my internal package structure. That's really the optimal thing to do, but I appreciate you may not be at that point; have you tried playing with the shadedArtifactAttached property; setting it to true? – Idcmp Apr 22 '15 at 21:47
  • @ldcmp I'm not entirely what I did incorrectly to start with; but I went back to what I had originally and started fresh, following your instruction. All good :) – whitfin Apr 23 '15 at 01:13