Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example with external contracts and contractsMode CLASSPATH #107

Open
robeatoz opened this issue Aug 6, 2019 · 6 comments
Open

Example with external contracts and contractsMode CLASSPATH #107

robeatoz opened this issue Aug 6, 2019 · 6 comments

Comments

@robeatoz
Copy link

robeatoz commented Aug 6, 2019

Preamble

My setup contains the following modules:

Module name Corresponding module in the samples Description
my-contracts beer_contracts Module with contracts.
my-producer producer_with_external_contracts Producer of the API.
my-consumer - Consumer of the API.

I wanted to execute the Spring Cloud Contract tests during the build with contractsMode CLASSPATH.
For that reason, I created an aggregator containing these three modules und executed mvn clean test.

In the samples, the beer_contracts module with external contracts does not provide the artifact with the classifier stubs.
I choose another approach for my project.
The module my-contracts does provide the artifact with the classifier stubs.
The modules my-consumer and my-producer do not know each other but the API and the module my-contracts.

Issue

To demonstrate how Spring Cloud Contract works with external contracts, the samples contain already the modules beer_contracts and producer_with_external_contracts.
This works with contractsMode LOCAL but not with contractsMode CLASSPATH.

In my project this has a couple of reasons:

After setting contractsMode to CLASSPATH in my-producer the following problems occur:

  1. No stubs were found on classpath for [com.example:beer-contracts]

    I had to add the dependency of beer-contracts to the plugin dependencies in producer_with_external_contracts like this:

    <plugin>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-contract-maven-plugin</artifactId>
      <version>${spring-cloud-contract.version}</version>
      <extensions>true</extensions>
      <configuration>
          ...
        <contractDependency>
          <groupId>de.demo</groupId>
          <artifactId>my-contracts</artifactId>
          <classifier>stubs</classifier>
        </contractDependency>
        <contractsMode>CLASSPATH</contractsMode>
          ...
      </configuration>
    
      <dependencies>
        <dependency>
          <groupId>de.demo</groupId>
          <artifactId>my-contracts</artifactId>
          <version>0.0.1.BUILD-SNAPSHOT</version>
          <classifier>stubs</classifier>
        </dependency>
      </dependencies>
    </plugin>

    The next error message is the following:

  2. [ERROR] Unresolveable build extension: Plugin org.springframework.cloud:spring-cloud-contract-maven-plugin:2.1.3.BUILD-SNAPSHOT or one of its dependencies could not be resolved

    Normally Maven will resolve the dependencies of modules and plugins during the build.
    The problem here is the <extensions>true</extensions> tag.
    I guess that dependencies of extensions have to be available at the time the build starts and can not be resolved during the build.
    To fix it, I just had to include the spring-cloud-contract-maven-plugin to the extensions and remove the <extensions>true</extensions> tag (or set it to false):

    <build>
      <extensions>
        <extension>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-contract-maven-plugin</artifactId>
          <version>${spring-cloud-contract.version}</version>
        </extension>
      </extensions>
    
      <plugins>
          ...
        <plugin>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-contract-maven-plugin</artifactId>
          <version>${spring-cloud-contract.version}</version>
          <extensions>false</extensions>
          <configuration>
              ...
            <contractsMode>CLASSPATH</contractsMode>
          </configuration>
          <dependencies>
            <dependency>
              <groupId>de.demo</groupId>
              <artifactId>my-contracts</artifactId>
              <version>0.0.1.BUILD-SNAPSHOT</version>
              <classifier>stubs</classifier>
            </dependency>
          </dependencies>
        </plugin>
      </plugins>
    </build>

After these fixes, the build and all Spring Cloud Contract tests run properly.
Now I have the following questions:

  • Is my approach with my-contracts and artifact with classifier stubs used in consumer and producer by Spring Cloud Contracts intended?

  • How would a setup look with given modules beer_contracts and producer_with_external_contracts with contractsMode CLASSPATH?
    Just adapting my fixes does not work.

@marcingrzejszczak
Copy link
Contributor

Hi!

Is my approach with my-contracts and artifact with classifier stubs used in consumer and producer by Spring Cloud Contracts intended?

I don't think we have ever assumed that someone would use the classpath mode with external contracts.

How would a setup look with given modules beer_contracts and producer_with_external_contracts with contractsMode CLASSPATH?

For sure you need to add the dependency to the classpath.

[ERROR] Unresolveable build extension: Plugin org.springframework.cloud:spring-cloud-contract-maven-plugin:2.1.3.BUILD-SNAPSHOT or one of its dependencies could not be resolved

This seems to mean that the snapshot dependency of the plugin couldn't have been found. I don't think you need to disable the extensions to retrieve it. Since you've already downloaded the plugin, can you rollback to point number 1 and try again.

I'm actually surprised that the CLASSPATH thing works anyways ;) But it's good to see that it does

@robeatoz
Copy link
Author

robeatoz commented Aug 6, 2019

Thanks for the fast feedback!

This seems to mean that the snapshot dependency of the plugin couldn't have been found.

I have the same error message with version 2.1.2.RELEASE and <extensions>true</extensions>:

Unresolveable build extension: Plugin org.springframework.cloud:spring-cloud-contract-maven-plugin:2.1.2.RELEASE or one of its dependencies could not be resolved

But this is only relevant for contractsMode CLASSPATH.

Are you interested to provide an example for classpath mode with external contracts or is this scenario too specific?
In that case, I will close the issue :)

@marcingrzejszczak
Copy link
Contributor

I have the same error message with version 2.1.2.RELEASE and true:

wow, I'm surprised!

Are you interested to provide an example for classpath mode with external contracts or is this scenario too specific?

I think that it's specific, but if you're interested, feel free to provide a PR to this repo with a working sample (Maven and Gradle). That way, if anyone is interested, we'll show that there's an option to make this work :)

@robeatoz
Copy link
Author

robeatoz commented Aug 6, 2019

I created a draft for a PR in #108.
To reproduce the error message

[ERROR] Unresolveable build extension: Plugin org.springframework.cloud:spring-cloud-contract-maven-plugin:2.1.3.BUILD-SNAPSHOT or one of its dependencies could not be resolved

you just have to edit the module producer_with_external_contracts_classpath:

Remove

<extensions>
  <extension>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>${spring-cloud-contract.version}</version>
  </extension>
</extensions>

Change

<extensions>false</extensions>

to

<extensions>true</extensions>

@mplain
Copy link

mplain commented Apr 13, 2020

Bumping this.
Same situation, I have a multi-module project with one module containing the actual REST provider, and a separate module containing the contracts (as well as an OpenAPI specification), to be deployed as a separate artifact.
This layout seems logical to me, not all that specific.
It would be nice if the Classpath mode supported multi-module projects.

@awelless
Copy link

awelless commented Oct 25, 2021

+1 to this issue
I have 'producer' and 'producer-api' modules. I import 'producer-api' both to 'producer' and 'consumer' modules, so it seems natural to store 'producer' contracts in 'producer-api' module

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants