Spring-cloud-contract: StubRunner with repoRoot and workOffline=false is still looking for stubs in local repository

Created on 31 May 2017  路  7Comments  路  Source: spring-cloud/spring-cloud-contract

Hey guys,

for my scenario I need to work with remote repositories to retrieve the stubs. There is a case that didn't work out as I expected and I wanted to discuss that here.

So, there is the workOffline Flag and the URL repoRoot.
If workOffline is true and no repoRoot is defined, the stubs will be searched in the local maven repository.
If workOffline is true and a repoRoot is defined, there will be an error.
If workOffline is false and no repoRootis defined, the classpath will be scanned.

The last case is if workOffline is false and a repoRoot is defined. My expectation was that the stubs will be searched in this repository and there will be an error if they are not found there.
What really happens is that the stubs will be searched in the defined repository, but as a fallback will also be searched in the local repository.

So, to reproduce it, just use the samples and change the paramters. Since I use the JUnit rule mechanism, I changed BeerControllerWithJUnitTest that way:

@Rule public StubRunnerRule rule = new StubRunnerRule()
            .repoRoot("http://artifactory.example.com")
            .downloadStub("com.example","beer-api-producer")
            .workOffline(false);

As I said, when the stub is in the local maven repository, this code just runs. If there is no stub in the local repository, I get this error message, which additionally confirms that the local repository is used:

java.lang.IllegalArgumentException: For groupId [com.example] artifactId [beer-api-producer] and classifier [stubs] the version was not resolved! The following exceptions took place [org.eclipse.aether.transfer.MetadataNotFoundException: Could not find metadata com.example:beer-api-producer/maven-metadata.xml in local (/Users/xxxx/.m2/localRepository), org.eclipse.aether.transfer.MetadataNotFoundException: Could not find metadata com.example:beer-api-producer/maven-metadata.xml in remote0 (http://artifactory.example.com)]

What I really want to do is to ensure that only the most recent stubs are used, both on our build server and on local developer machines. That's the reason why this fallback kinda bothers me. On the build server, it feels not right if there was no stub in the given remote repository, so I expect an error.

Maybe I'm too anxious because there is a lot of magic happening. Would be great to get some feedback about my thoughts. :)

Cheers, Gonzo

bug

All 7 comments

As far as I see this behaviour is not documented: https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_stub_downloading

If you provide the stubrunner.repositoryRoot or stubrunner.workOffline flag will be set to true then Stub Runner will connect to the given server and download the required jars. It will then unpack the JAR to a temporary folder and reference those files in further contract processing.

So if this behaviour is correct, it should at least be mentioned there, I guess.

Yeah that looks bad. I'll take another look in the code why we are doing the fallback (cc @mariuszs - do you remember any particular reason?) and if there's no concrete reason then it should be fixed as you mentioned. Thanks a lot for checking it out.

if (!workOffline) {
  session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
}

Local repository is always used, but when workOffline flag is disabled, then we are always asking remote repository for changes.

This is why your error look like: Could not find metadata com.example:beer-api-producer/maven-metadata.xml in remote0 (http://artifactory.example.com)]

@Gonzo17 go ahead and check out latest snapshots. Now you should start getting an IllegalStateException

@marcingrzejszczak Yeah that works, thanks!
One last question to this. If the artifact is found in both remote and local repository, it will take the artifact from the remote? Or does it take from the local repository then? And how does it decide if one artifact is newer than the other?

It picks from the remote first and if it finds it then that version will be used regardless of what you have locally.

Alright, thank you very much! Case closed :)

Was this page helpful?
0 / 5 - 0 ratings