Maven doesn't find imported class from another module but Intellij does
Asked Answered
S

4

11

I have multi-module maven project. The acceptance-tests module has dependency from api module in pom.xml (Replacing real company name by xxx to keep confidentiality). I am trying to import some classes from api module in my acceptance-tests.

Here is my pom.xml dependency of acceptance-tests module:

        <dependency>
            <artifactId>xxx-api</artifactId>
            <groupId>com.xxx</groupId>
            <version>${xxx.api.version}</version>
        </dependency>

The api module separately is being installed and packaged (mvn install, mvn package) by maven without any issue. The jar file is being created in my local .m2.

However, when I try to compile the acceptance-tests module, I get a compilation error saying that the the classes cannot be imported because the package is not found.

Here is the actual error:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project xxx-acceptance-tests: Compilation failure: Compilation failure: 
[ERROR] /Users/andranik_chorokhyan/mydisk/Projects/XXX/automation/xxx-project-test-automation/xxx-acceptance-tests/src/main/java/com/xxx/xxx/utilities/api/ApiPayloadUtils.java:[17,38] package com.xxx.domain.dto does not exist
[ERROR] /Users/andranik_chorokhyan/mydisk/Projects/XXX/automation/xxx-project-test-automation/xxx-acceptance-tests/src/main/java/com/xxx/xxx/utilities/api/ApiPayloadUtils.java:[18,38] package com.xxx.domain.dto does not exist
[ERROR]   symbol:   class MappingData
[ERROR]   location: class com.xxx.utilities.api.ApiPayloadUtils

One more interesting fact is that there is no error visible in Intellij IDEA. No red underline, no compilation error, no problem with navigating to the appropriate imported file. And in reality, the com.xxx.domain.dto package does exist and the MappingData class as well.

I removed whole xxx directory from my local .m2 repository and executed mvn clean dependency:resolve command. It succeeded as well.

Does anybody know what's the problem here and how it can be solved? Thanks in advance!

Shah answered 21/4, 2020 at 10:16 Comment(9)
Look at mvn dependency:list. See which version is on the list. Open that version and see if the package indeed is in that jar.Vazquez
Yes, it is. The api module dependency version's jar exists in my .m2 repoShah
So have you opened the jar and looked whether it contains the *.class file that you are looking for?Vazquez
Yes, I did. I have opened the BOOT-INF/classes directory and found the appropriate class file by the expected package pathShah
The class should not be in a subdirectory. Note that you should not construct dependencies to executable jars like those from Spring Boot.Vazquez
Ah so you have a spring boot app package as a dependency which does not work...so it's not an reusable API it's an applicationGodgiven
Yes, but technically it's a jar, right? Why I can't have a dependency from it?Shah
Because it puts the classes under BOOT-INF and not into the main directory.Vazquez
Hm, got it. So, even if that's a module in my project, I am not able to use it's classes in another module. But why the IntelliJ Idea does not catch the error?Shah
S
8

Finally I have found the solution. Thanks JF Meier and khmarbaise for hints.

It appeared Maven doesn't allow dependency from executable jar. This was my case. My api module was an executable Spring Boot application and not reusable library.

So, the solution was the following:

  1. It was necessary to find the Application.java file in api module.
  2. Add maven-jar-plugin with exclusion of the Application.java file and specification of some classifier
  3. Making dependency in acceptance-tests module from the above specified classifier instead of standard jar

Plugin specification in api module below:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                        <configuration>
                            <classifier>qa</classifier>
                            <excludes>
                                <exclude>**/Application*</exclude>
                            </excludes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Dependency in acceptance-tests module below:

        <dependency>
            <artifactId>xxx-api</artifactId>
            <groupId>com.xxx</groupId>
            <version>${api.version}</version>
            <classifier>qa</classifier>
        </dependency>
Shah answered 22/4, 2020 at 8:56 Comment(1)
You shouldn't add the jar plugin just to exclude it. If you don't want an executable jar then dont import the plugin the builds it.Wooster
B
13

I was also getting symbol not found errors while compiling with maven, and the solution is for spring boot 2 you need to configure plugin as below, classifier exec

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <classifier>exec</classifier>
        </configuration>
    </plugin>

If you are working with spring boot 1

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
            <execution>
                <goals>
                    <goal>repackage</goal>
                </goals>
                <configuration>
                    <classifier>exec</classifier>
                </configuration>
            </execution>
        </executions>
    </plugin>
Bolshevist answered 10/11, 2020 at 9:26 Comment(0)
S
8

Finally I have found the solution. Thanks JF Meier and khmarbaise for hints.

It appeared Maven doesn't allow dependency from executable jar. This was my case. My api module was an executable Spring Boot application and not reusable library.

So, the solution was the following:

  1. It was necessary to find the Application.java file in api module.
  2. Add maven-jar-plugin with exclusion of the Application.java file and specification of some classifier
  3. Making dependency in acceptance-tests module from the above specified classifier instead of standard jar

Plugin specification in api module below:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                        <configuration>
                            <classifier>qa</classifier>
                            <excludes>
                                <exclude>**/Application*</exclude>
                            </excludes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Dependency in acceptance-tests module below:

        <dependency>
            <artifactId>xxx-api</artifactId>
            <groupId>com.xxx</groupId>
            <version>${api.version}</version>
            <classifier>qa</classifier>
        </dependency>
Shah answered 22/4, 2020 at 8:56 Comment(1)
You shouldn't add the jar plugin just to exclude it. If you don't want an executable jar then dont import the plugin the builds it.Wooster
D
3

The spring-boot-maven-plugin when you install/deploy repackages your project and places it into a local/remote repository, this jar file cannot be used as a library, according to the documentation you should configure the plugin to install/deploy only the original jar file.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>repackage</id>
            <goals>
                <goal>repackage</goal>
            </goals>
            <configuration>
                <attach>false</attach>
            </configuration>
        </execution>
    </executions>
</plugin>
Divot answered 6/12, 2023 at 14:10 Comment(0)
Z
1

Spring-boot-maven-plugin should be removed from the pom.xml inside the library, because there is no need to build an executable jar for a Library project.

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

see more details in multi-module

Zeena answered 29/11, 2023 at 7:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.