'Getting IntelliJ to import shaded dependencies in a multi-module maven project

I have two modules, Component and Application. The Component module is shaded due to a dependency conflict (google protocol buffers) later in the build process.

<!-- snip from Component's pom.xml -->
<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-shade-plugin</artifactId>
     <version>2.3</version>
     <configuration>
         <relocations>
             <relocation>
                 <pattern>com.google.protobuf</pattern>                                
                 <shadedPattern>my.package.protocols.shaded.com.google.protobuf</shadedPattern>
             </relocation>
         </relocations>
     </configuration>
     <executions>
         <execution>
             <phase>package</phase>
             <goals>
                 <goal>shade</goal>
             </goals>
         </execution>
    </executions>
</plugin> 

The Application depends on the Component module. However, source files in the Application cannot reference the shaded library that the Component depends on. This is critical for interacting with the Component.

     <-- snip from Application's pom.xml -->   
     <dependency>
          <groupId>my-group</groupId>
          <artifactId>component</artifactId>
          <version>${project.version}</version>
     </dependency>

Even though the import can't be found by IntelliJ, the Maven build works fine. What am I missing/doing-wrong?



Solution 1:[1]

Too bad, after opening a ticket with JetBrains, this problem has been previously reported and is currently not supported in IntelliJ.

Solution 2:[2]

build-helper-maven-plugin seems to add the shaded jar into IntelliJ project:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
      <execution>
        <id>compile</id>
        <phase>package</phase>
        <goals>
          <goal>attach-artifact</goal>
        </goals>
        <configuration>
          <artifacts>
            <artifact>
              <file>${basedir}/target/<YOUR JAR NAME>-SNAPSHOT.jar</file>
              <type>jar</type>
              <classifier>optional</classifier>
            </artifact>
          </artifacts> 
        </configuration>
      </execution>
    </executions>
  </plugin>

For details, see https://www.mojohaus.org/build-helper-maven-plugin/attach-artifact-mojo.html.

Solution 3:[3]

I fixed the similar problem by shading also a source jar and unpacking it to the source directory:

<build>

    <sourceDirectory>${project.build.directory}/shaded-sources</sourceDirectory>

    <plugins>
      <plugin>
        <artifactId>maven-source-plugin</artifactId>
        <configuration>
          <skipSource>true</skipSource>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <createSourcesJar>true</createSourcesJar>
              <shadeSourcesContent>true</shadeSourcesContent>
              <createDependencyReducedPom>false</createDependencyReducedPom>
              <artifactSet>
                <includes>
                  <include>com.google.guava:*</include>
                </includes>
              </artifactSet>
              <relocations>
                <relocation>
                  <pattern>com.google.common</pattern>
                  <shadedPattern>org.apache.drill.shaded.com.google.common</shadedPattern>
                </relocation>
              </relocations>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>unpack</id>
            <phase>package</phase>
            <goals>
              <goal>unpack</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>org.apache.drill.contrib</groupId>
                  <artifactId>guava-shaded</artifactId>
                  <version>${project.version}</version>
                  <type>jar</type>
                  <outputDirectory>${project.build.directory}/classes</outputDirectory>
                  <includes>**/**</includes>
                </artifactItem>
                <artifactItem>
                  <groupId>org.apache.drill.contrib</groupId>
                  <artifactId>guava-shaded</artifactId>
                  <version>${project.version}</version>
                  <type>jar</type>
                  <classifier>sources</classifier>
                  <overWrite>true</overWrite>
                  <outputDirectory>${project.build.directory}/shaded-sources</outputDirectory>
                  <includes>**/**</includes>
                </artifactItem>
              </artifactItems>
            </configuration>
          </execution>
        </executions>
      </plugin>
</build>

Solution 4:[4]

A better workaround seems to be: Right-click on shard project "component" -> pom.xml in the project view in IntelliJ, choose "Maven" -> "Ignore Projects". Then do a "Maven" -> "Reimport" on the project pom.xml.

Solution 5:[5]

One more solution I'm using in the current project.

It works the same way for both shaded modules or custom bundles.

<!--
  - Make sure 'module-a' is built BEFORE this module
  -->
<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>module-a</artifactId>
    <version>${project.version}</version>
    <scope>test</scope><!-- or runtime -->
</dependency>

<!--
  - IDEA does NOT support custom bundles in multi-module projects.
  - Using system scope to link correct JAR file explicitly.
 -->
<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>module-a</artifactId>
    <version>FAKE-VERSION</version>
    <classifier>FAKE-CLASSIFIER</classifier>
    <scope>system</scope>
    <systemPath>${project.basedir}/../module-a/target/module-a-${project.version}.jar</systemPath>
</dependency>

Solution 6:[6]

As a complement to TimP's answer:

  • By attach additional artifact using build-helper-maven-plugin, the Idea is able to recognized it and work fine as an transitive dependency(other modules dependent on the artifact recognize relocated symbols as well).

    enter image description here

  • If you don't want to package the additional artifact, simply add skipAttach to the execution configuration(The shaded artifact still recognized by IDEA):

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <executions>
    <execution>
           <id>attach-shade-jar</id>
           <phase>package</phase>
           <goals>
              <goal>attach-artifact</goal>
           </goals>
           <configuration>
               <artifacts>
                  <artifact>   
  <file>${project.build.directory}/${project.build.finalName}.jar</file>
                      <type>jar</type>
                      <classifier>shaded</classifier>
                  </artifact>
               </artifacts>
               <skipAttach>true</skipAttach>
          </configuration>
      </execution>
   </executions>
</plugin>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jane Wayne
Solution 2 TimP
Solution 3 Vova Vysotskyi
Solution 4 lemonzone2010
Solution 5 ursa
Solution 6 bob