Search code examples
mavenmulti-modulespring-cloud-contract

Spring Cloud Contract not deploying to Artifactory in Maven multi module projects


I have a multi module project in which each module deploys fine to Artifactory until I add spring-cloud-contract-maven-plugin to one of the modules (the service, as it is a producer API).

The project has this structure:

parent
- common (shared DTOs)
- client
- service

We want to remove the client and the common in the future and have Feign clients in the consumers for reducing the coupling, and have a basic project without inner modules, but for now we have to keep this structure.

I first noticed that the stubs were not pushed to Artifactory, so my initial workaround was to add this to the Jenkins pipeline

sh './mvnw clean deploy -U --projects=xxx-service'

It deploys the service and the stubs, but I noticed that none of the modules gets deployed when this command is executed:

sh './mvnw clean deploy -U'

This is the end of the output:

[INFO] Installing /xxx/xxx-service/target/xxx-service-1.7.0-SNAPSHOT.jar to /xxx/.m2/repository/xxx/xxx-service/1.7.0-SNAPSHOT/xxx-service-1.7.0-SNAPSHOT.jar
[INFO] Installing /xxx/xxx-service/pom.xml to /xxx/.m2/repository/xxx/xxx-service/1.7.0-SNAPSHOT/xxx-service-1.7.0-SNAPSHOT.pom
[INFO] Installing /xxx/xxx-service/target/xxx-service-1.7.0-SNAPSHOT-stubs.jar to /xxx/.m2/repository/xxx/xxx-service/1.7.0-SNAPSHOT/xxx-service-1.7.0-SNAPSHOT-stubs.jar
[INFO] 
[INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ xxx-service ---
[INFO] Deploying xxx:xxx-service:1.7.0-SNAPSHOT at end

I have tried to move all the Maven configuration to the parent POM file and keep the contracts and the base test classes in the service module. I have looked to this page that explains how to configure the plugin and I have seen that I can use contractsDirectory to specify the directory of the contract files, gmavenplus-plugin to specify the directory of the generated tests and packageWithBaseClasses to specify the package of the base classes. However I don't see any way to specify the directory of the base classes. I cannot move the base test classes to the parent because they use some classes of the service module for generating the mocks.

Is there any way of doing it or I have to create a separate project for the contracts?

Thanks in advance


Solution

  • Cause of the problem:

    I had this in a parent project extended by my API:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>${maven-deploy-plugin.version}</version>
            <configuration>
                <deployAtEnd>true</deployAtEnd>
            </configuration>
        </plugin>
    

    Why is this a problem:

    maven-deploy-plugin seems to conflict with multi module projects with plugins that use extensions like spring-cloud-contract-maven-plugin. There is a known issue documented here, look to the answer of Jerome that is also here.

    Solution 1:

    Remove the deployAtEnd option from the previous block so it would be:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>${maven-deploy-plugin.version}</version>
        </plugin>
    

    Solution 2:

    Configure the plugin in all the modules although they don't need it. For doing so:

    • Add an empty "contracts" folder under src/test/resources on all the modules

    • Add this to the pom file of the service module:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                <version>${spring-cloud-contract.version}</version>
                <extensions>true</extensions>
                <configuration
                    <baseClassForTests>com.xxx.BaseContractTest</baseClassForTests>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    • Add this to the pom file of the other modules:
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                <version>${spring-cloud-contract.version}</version>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>