diff --git a/pom.xml b/pom.xml index 06b02c18a4..8caa639c84 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,8 @@ 2.17.0 1.0.2.RELEASE 1.4.0.RELEASE + 2.17 + 1.2.0.BUILD-SNAPSHOT @@ -310,6 +312,55 @@ + + checkstyle + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + + org.springframework.cloud + spring-cloud-build-tools + ${spring-cloud-build.version} + + + + + validate + validate + + checkstyle.xml + LICENSE.txt + true + true + + + check + + + + + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + checkstyle.xml + LICENSE.txt + + + + + diff --git a/spring-cloud-contract-dependencies/pom.xml b/spring-cloud-contract-dependencies/pom.xml index 62aed5dc72..89f696c3d0 100644 --- a/spring-cloud-contract-dependencies/pom.xml +++ b/spring-cloud-contract-dependencies/pom.xml @@ -20,6 +20,7 @@ 1.0.2.RELEASE 1.0.3.BUILD-SNAPSHOT 1.1.5.BUILD-SNAPSHOT + 1.0.3.BUILD-SNAPSHOT @@ -173,6 +174,13 @@ pom import + + org.springframework.cloud + spring-cloud-consul-dependencies + ${spring-cloud-consul.version} + pom + import + diff --git a/spring-cloud-contract-spec/src/main/groovy/repackaged/nl/flotsam/xeger/Xeger.java b/spring-cloud-contract-spec/src/main/groovy/repackaged/nl/flotsam/xeger/Xeger.java index 10b3987643..a963fac9c2 100644 --- a/spring-cloud-contract-spec/src/main/groovy/repackaged/nl/flotsam/xeger/Xeger.java +++ b/spring-cloud-contract-spec/src/main/groovy/repackaged/nl/flotsam/xeger/Xeger.java @@ -2,22 +2,21 @@ * Copyright 2009 Wilfred Springer * Copyright 2012 Jason Pell * Copyright 2013 Antonio García-Domínguez - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + *

* The class is bundled together with our code because it has not been * released to any central repository. - * */ package repackaged.nl.flotsam.xeger; @@ -35,67 +34,68 @@ import dk.brics.automaton.Transition; */ public class Xeger { - private final Automaton automaton; - private Random random; + private final Automaton automaton; + private Random random; - /** - * Constructs a new instance, accepting the regular expression and the randomizer. - * - * @param regex The regular expression. (Not null.) - * @param random The object that will randomize the way the String is generated. (Not null.) - * @throws IllegalArgumentException If the regular expression is invalid. - */ - public Xeger(String regex, Random random) { - assert regex != null; - assert random != null; - this.automaton = new RegExp(regex).toAutomaton(); - this.random = random; - } + /** + * Constructs a new instance, accepting the regular expression and the randomizer. + * + * @param regex The regular expression. (Not null.) + * @param random The object that will randomize the way the String is generated. (Not null.) + * @throws IllegalArgumentException If the regular expression is invalid. + */ + public Xeger(String regex, Random random) { + assert regex != null; + assert random != null; + this.automaton = new RegExp(regex).toAutomaton(); + this.random = random; + } - /** - * As {@link Xeger#Xeger(String, java.util.Random)}, creating a {@link java.util.Random} instance - * implicityly. - * - * @param regex as string - */ - public Xeger(String regex) { - this(regex, new Random()); - } + /** + * As {@link Xeger#Xeger(String, java.util.Random)}, creating a {@link java.util.Random} instance + * implicityly. + * + * @param regex as string + */ + public Xeger(String regex) { + this(regex, new Random()); + } - /** - * Generates a random String that is guaranteed to match the regular expression passed to the constructor. - * @return generated regexp - */ - public String generate() { - StringBuilder builder = new StringBuilder(); - generate(builder, automaton.getInitialState()); - return builder.toString(); - } + /** + * Generates a random String that is guaranteed to match the regular expression passed to the constructor. + * @return generated regexp + */ + public String generate() { + StringBuilder builder = new StringBuilder(); + generate(builder, this.automaton.getInitialState()); + return builder.toString(); + } - private void generate(StringBuilder builder, State state) { - List transitions = state.getSortedTransitions(false); - if (transitions.size() == 0) { - assert state.isAccept(); - return; - } - int nroptions = state.isAccept() ? transitions.size() : transitions.size() - 1; - int option = Xeger.getRandomInt(0, nroptions, random); - if (state.isAccept() && option == 0) { // 0 is considered stop - return; - } - // Moving on to next transition - Transition transition = transitions.get(option - (state.isAccept() ? 1 : 0)); - appendChoice(builder, transition); - generate(builder, transition.getDest()); - } + private void generate(StringBuilder builder, State state) { + List transitions = state.getSortedTransitions(false); + if (transitions.size() == 0) { + assert state.isAccept(); + return; + } + int nroptions = state.isAccept() ? transitions.size() : transitions.size() - 1; + int option = Xeger.getRandomInt(0, nroptions, this.random); + if (state.isAccept() && option == 0) { // 0 is considered stop + return; + } + // Moving on to next transition + Transition transition = transitions.get(option - (state.isAccept() ? 1 : 0)); + appendChoice(builder, transition); + generate(builder, transition.getDest()); + } - private void appendChoice(StringBuilder builder, Transition transition) { - char c = (char) Xeger.getRandomInt(transition.getMin(), transition.getMax(), random); - builder.append(c); - } + private void appendChoice(StringBuilder builder, Transition transition) { + char c = (char) Xeger + .getRandomInt(transition.getMin(), transition.getMax(), this.random); + builder.append(c); + } public Random getRandom() { - return random; + return this.random; } public void setRandom(Random random) { @@ -112,7 +112,7 @@ public class Xeger { */ static int getRandomInt(int min, int max, Random random) { // Use random.nextInt as it guarantees a uniform distribution - int maxForRandom=max-min+1; + int maxForRandom = max - min + 1; return random.nextInt(maxForRandom) + min; } } \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/README.adoc b/spring-cloud-contract-stub-runner/README.adoc index 1a46275561..ab3906ba65 100644 --- a/spring-cloud-contract-stub-runner/README.adoc +++ b/spring-cloud-contract-stub-runner/README.adoc @@ -236,4 +236,41 @@ For Messaging [source,groovy,indent=0] ---- include::src/test/groovy/org/springframework/cloud/contract/stubrunner/server/StubRunnerBootSpec.groovy[tags=boot_usage] ----- \ No newline at end of file +---- + +==== Stub Runner Boot with Service Discovery + +One of the possibilities of using Stub Runner Boot is to use it as a feed of stubs for "smoke-tests". What does it mean? + Let's assume that you don't want to deploy 50 microservice to a test environment in order + to check if your application is working fine. You've already executed a suite of tests during the build process + but you would also like to ensure that the packaging of your application is fine. What you can do + is to deploy your application to an environment, start it and run a couple of tests on it to see if + it's working fine. We can call those tests smoke-tests since their idea is to check only a handful + of testing scenarios. + +The problem with this approach is such that if you're doing microservices most likely you're + using a service discovery tool. Stub Runner Boot allows you to solve this issue by starting the + required stubs and register them in a service discovery tool. Let's take a look at an example of + such a setup with Eureka. Let's assume that Eureka was already running. + +[source,java,indent=0] +---- +include::src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootEurekaExample.java[tags=stubrunnereureka] +---- + +As you can see we want to start a Stub Runner Boot server `@EnableStubRunnerServer`, enable Eureka client `@EnableEurekaClient` +and we want to have the stub runner feature turned on `@AutoConfigureStubRunner`. + +Now let's assume that we want to start this application so that the stubs get automatically registered. + We can do it by running the app `java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar` where + `${SYSTEM_PROPS}` would contain the following list of properties + +[source,bash,indent=0] +---- +include::src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootEurekaExample.java[tags=stubrunnereureka_args] +---- + +That way your deployed application can send requests to started WireMock servers via the service +discovery. Most likely points 1-3 could be set by default in `application.yml` cause they are not +likely to change. That way you can provide only the list of stubs to download whenever you start +the Stub Runner Boot. \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/pom.xml b/spring-cloud-contract-stub-runner/pom.xml index 4272130ae1..ca0aaf79b1 100644 --- a/spring-cloud-contract-stub-runner/pom.xml +++ b/spring-cloud-contract-stub-runner/pom.xml @@ -95,6 +95,11 @@ junit junit + + com.sun.jersey + jersey-client + true + cglib cglib @@ -128,13 +133,23 @@ org.springframework.cloud spring-cloud-starter-zookeeper-discovery - test + true org.apache.curator curator-test test + + org.springframework.cloud + spring-cloud-starter-eureka + true + + + org.springframework.cloud + spring-cloud-starter-consul-discovery + true + diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java index 47d42bf6fa..7a7429ccda 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java @@ -85,7 +85,7 @@ public class AetherStubDownloader implements StubDownloader { } private boolean remoteReposMissing() { - return remoteRepos == null || remoteRepos.isEmpty(); + return this.remoteRepos == null || this.remoteRepos.isEmpty(); } /** @@ -121,16 +121,16 @@ public class AetherStubDownloader implements StubDownloader { if (!StringUtils.hasText(resolvedVersion)) { log.warn("Stub for group [" + stubsGroup + "] module [" + stubsModule + "] and classifier [" + classifier + "] not found in " - + remoteRepos); + + this.remoteRepos); return null; } Artifact artifact = new DefaultArtifact(stubsGroup, stubsModule, classifier, ARTIFACT_EXTENSION, resolvedVersion); - ArtifactRequest request = new ArtifactRequest(artifact, remoteRepos, null); + ArtifactRequest request = new ArtifactRequest(artifact, this.remoteRepos, null); log.info("Resolving artifact [" + artifact - + "] using remote repositories " + remoteRepos); + + "] using remote repositories " + this.remoteRepos); try { - ArtifactResult result = repositorySystem.resolveArtifact(session, request); + ArtifactResult result = this.repositorySystem.resolveArtifact(this.session, request); log.info("Resolved artifact [" + artifact + "] to " + result.getArtifact().getFile()); File temporaryFile = unpackStubJarToATemporaryFolder( @@ -142,7 +142,7 @@ public class AetherStubDownloader implements StubDownloader { log.warn( "Exception occurred while trying to download a stub for group [" + stubsGroup + "] module [" + stubsModule - + "] and classifier [" + classifier + "] in " + remoteRepos, + + "] and classifier [" + classifier + "] in " + this.remoteRepos, e); return null; } @@ -187,7 +187,7 @@ public class AetherStubDownloader implements StubDownloader { remoteRepos, null); VersionRangeResult rangeResult; try { - rangeResult = repositorySystem.resolveVersionRange(session, + rangeResult = this.repositorySystem.resolveVersionRange(this.session, versionRangeRequest); if (log.isDebugEnabled()) { log.debug("Resolved version range is [" + rangeResult + "]"); @@ -210,7 +210,7 @@ public class AetherStubDownloader implements StubDownloader { VersionRequest versionRequest = new VersionRequest(artifact, remoteRepos, null); VersionResult versionResult; try { - versionResult = repositorySystem.resolveVersion(session, versionRequest); + versionResult = this.repositorySystem.resolveVersion(this.session, versionRequest); } catch (VersionResolutionException e) { throw new IllegalStateException("Cannot resolve version", e); diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerExecutor.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerExecutor.java index 8494234b2f..c5d075a7d9 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerExecutor.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerExecutor.java @@ -60,13 +60,23 @@ class StubRunnerExecutor implements StubFinder { public RunningStubs runStubs(StubRunnerOptions stubRunnerOptions, StubRepository repository, StubConfiguration stubConfiguration) { + if (this.stubServer != null) { + if (log.isDebugEnabled()) { + log.debug("Returning cached version of stubs [" + stubConfiguration.toColonSeparatedDependencyNotation() + "]"); + } + return runningStubs(); + } startStubServers(stubRunnerOptions, stubConfiguration, repository); - RunningStubs runningCollaborators = new RunningStubs(Collections - .singletonMap(stubServer.getStubConfiguration(), stubServer.getPort())); + RunningStubs runningCollaborators = runningStubs(); log.info("All stubs are now running " + runningCollaborators.toString()); return runningCollaborators; } + private RunningStubs runningStubs() { + return new RunningStubs(Collections + .singletonMap(stubServer.getStubConfiguration(), stubServer.getPort())); + } + public void shutdown() { if (stubServer != null) { stubServer.stop(); diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java index 8affbff49f..d3eb767ab4 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java @@ -61,8 +61,10 @@ public class StubRunnerOptions { */ final Map stubIdsToPortMapping; - public StubRunnerOptions(Integer minPortValue, Integer maxPortValue, String stubRepositoryRoot, - boolean workOffline, String stubsClassifier, Collection dependencies, Map stubIdsToPortMapping) { + public StubRunnerOptions(Integer minPortValue, Integer maxPortValue, + String stubRepositoryRoot, boolean workOffline, String stubsClassifier, + Collection dependencies, + Map stubIdsToPortMapping) { this.minPortValue = minPortValue; this.maxPortValue = maxPortValue; this.stubRepositoryRoot = stubRepositoryRoot; diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunning.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunning.java index 55534b874c..60c578316b 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunning.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunning.java @@ -19,8 +19,10 @@ package org.springframework.cloud.contract.stubrunner; import java.io.Closeable; public interface StubRunning extends Closeable, StubFinder { + /** - * Runs the stubs and returns the {@link RunningStubs} + * Runs the stubs and returns the {@link RunningStubs}. If the stubs were + * already started then a cached version will be returned. */ RunningStubs runStubs(); diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/HttpStubsController.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/HttpStubsController.java index 38335ca5ee..76f89bef3f 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/HttpStubsController.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/HttpStubsController.java @@ -21,6 +21,7 @@ import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.contract.stubrunner.StubRunning; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,7 +31,7 @@ import org.springframework.web.bind.annotation.RestController; * @author Marcin Grzejszczak */ @RestController -@RequestMapping("/stubs") +@RequestMapping(value = "/stubs", produces = MediaType.APPLICATION_JSON_VALUE) public class HttpStubsController { private final StubRunning stubRunning; diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/TriggerController.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/TriggerController.java index 42d0e8f091..08b310412e 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/TriggerController.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/server/TriggerController.java @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.contract.stubrunner.StubFinder; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -36,7 +37,7 @@ import org.springframework.web.bind.annotation.RestController; * @author Marcin Grzejszczak */ @RestController -@RequestMapping("/triggers") +@RequestMapping(value = "/triggers", produces = MediaType.APPLICATION_JSON_VALUE) public class TriggerController { private static final Logger log = LoggerFactory.getLogger(TriggerController.class); diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ConditionalOnStubbedDiscoveryDisabled.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ConditionalOnStubbedDiscoveryDisabled.java new file mode 100644 index 0000000000..290b7c3d94 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ConditionalOnStubbedDiscoveryDisabled.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +/** + * Conditional that checks if the user turned off the stubbed discovery mode + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Documented +@ConditionalOnProperty(value = "stubrunner.cloud.stubbed.discovery.enabled", havingValue = "false") +public @interface ConditionalOnStubbedDiscoveryDisabled { +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ConditionalOnStubbedDiscoveryEnabled.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ConditionalOnStubbedDiscoveryEnabled.java new file mode 100644 index 0000000000..3d0b81392b --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ConditionalOnStubbedDiscoveryEnabled.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +/** + * Conditional that checks if the user turned on the stubbed discovery mode. + * The feature is turned on by default. + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Documented +@ConditionalOnProperty(value = "stubrunner.cloud.stubbed.discovery.enabled", havingValue = "true", matchIfMissing = true) +public @interface ConditionalOnStubbedDiscoveryEnabled { +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperProperties.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperProperties.java index 6706ae5497..3e1739b6fc 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperProperties.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperProperties.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.Map; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.contract.stubrunner.StubConfiguration; +import org.springframework.cloud.contract.stubrunner.util.StringUtils; /** * Maps Ivy based ids to service Ids. You might want to name the service you're calling @@ -29,7 +31,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * Just provide in your properties file for example: * * stubrunner.idsToServiceIds: - * ivyNotation: someValueInsideYourCode * fraudDetectionServer: someNameThatShouldMapFraudDetectionServer * * @author Marcin Grzejszczak @@ -59,7 +60,17 @@ public class StubMapperProperties { } public String fromIvyNotationToId(String ivyNotation) { - return idsToServiceIds.get(ivyNotation); + StubConfiguration stubConfiguration = new StubConfiguration(ivyNotation); + String id = idsToServiceIds.get(ivyNotation); + if (StringUtils.hasText(id)) { + return id; + } + String groupAndArtifact = idsToServiceIds.get(stubConfiguration.getGroupId() + + ":" + stubConfiguration.getArtifactId()); + if (StringUtils.hasText(groupAndArtifact)) { + return groupAndArtifact; + } + return idsToServiceIds.get(stubConfiguration.getArtifactId()); } public String fromServiceIdToIvyNotation(String serviceId) { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java index 928197f402..702218f88e 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java @@ -16,16 +16,19 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud; +import java.lang.invoke.MethodHandles; import java.net.URI; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClient; - import org.springframework.cloud.contract.stubrunner.RunningStubs; import org.springframework.cloud.contract.stubrunner.StubFinder; import org.springframework.cloud.contract.stubrunner.util.StringUtils; @@ -40,6 +43,8 @@ import org.springframework.cloud.contract.stubrunner.util.StringUtils; */ class StubRunnerDiscoveryClient implements DiscoveryClient { + private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + private final DiscoveryClient delegate; private final StubFinder stubFinder; private final StubMapperProperties stubMapperProperties; @@ -48,6 +53,9 @@ class StubRunnerDiscoveryClient implements DiscoveryClient { StubMapperProperties stubMapperProperties, String springAppName) { this.delegate = delegate instanceof StubRunnerDiscoveryClient ? noOpDiscoveryClient(springAppName) : delegate; + if (log.isDebugEnabled()) { + log.debug("Will delegate calls to discovery service [" + this.delegate + "] if a stub is not found"); + } this.stubFinder = stubFinder; this.stubMapperProperties = stubMapperProperties; } @@ -55,6 +63,9 @@ class StubRunnerDiscoveryClient implements DiscoveryClient { public StubRunnerDiscoveryClient(StubFinder stubFinder, StubMapperProperties stubMapperProperties, String springAppName) { this.delegate = noOpDiscoveryClient(springAppName); + if (log.isDebugEnabled()) { + log.debug("Will delegate calls to discovery service [" + this.delegate + "] if a stub is not found"); + } this.stubFinder = stubFinder; this.stubMapperProperties = stubMapperProperties; } @@ -65,12 +76,26 @@ class StubRunnerDiscoveryClient implements DiscoveryClient { @Override public String description() { - return delegate.description(); + try { + return this.delegate.description(); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.debug("Failed to fetch description from delegate", e); + } + } + return ""; } @Override public ServiceInstance getLocalServiceInstance() { - return delegate.getLocalServiceInstance(); + try { + return this.delegate.getLocalServiceInstance(); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.debug("Failed to get local service instance from delegate", e); + } + } + return null; } @Override @@ -78,14 +103,27 @@ class StubRunnerDiscoveryClient implements DiscoveryClient { String ivyNotation = stubMapperProperties.fromServiceIdToIvyNotation(serviceId); String serviceToFind = StringUtils.hasText(ivyNotation) ? ivyNotation : serviceId; URL stubUrl = stubFinder.findStubUrl(serviceToFind); + log.info("Resolved from ivy [" + ivyNotation + "] service to find [" + serviceToFind + "]. " + + "Found stub is available under URL [" + stubUrl + "]"); if (stubUrl == null) { - return delegate.getInstances(serviceId); + return getInstancesFromDelegate(serviceId); } return Collections.singletonList( new StubRunnerServiceInstance(serviceId, stubUrl.getHost(), stubUrl.getPort(), toUri(stubUrl)) ); } + private List getInstancesFromDelegate(String serviceId) { + try { + return this.delegate.getInstances(serviceId); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.debug("Failed to fetch instances from delegate", e); + } + return new ArrayList<>(); + } + } + private URI toUri(URL url) { try { return url.toURI(); @@ -96,9 +134,20 @@ class StubRunnerDiscoveryClient implements DiscoveryClient { @Override public List getServices() { - List services = delegate.getServices(); - RunningStubs runningStubs = stubFinder.findAllRunningStubs(); + List services = getServicesFromDelegate(); + RunningStubs runningStubs = this.stubFinder.findAllRunningStubs(); services.addAll(runningStubs.getAllServicesNames()); return services; } + + private List getServicesFromDelegate() { + try { + return this.delegate.getServices(); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.debug("Failed to fetch services from delegate", e); + } + } + return new ArrayList<>(); + } } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java index 7d5e9491fa..b6909cd324 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java @@ -43,6 +43,7 @@ public class StubRunnerSpringCloudAutoConfiguration { @Bean @ConditionalOnBean(DiscoveryClient.class) @Primary + @ConditionalOnStubbedDiscoveryEnabled public DiscoveryClient stubRunnerDiscoveryClientWrapper(DiscoveryClient discoveryClient, StubFinder stubFinder, StubMapperProperties stubMapperProperties, @@ -51,7 +52,9 @@ public class StubRunnerSpringCloudAutoConfiguration { } @Bean + @Primary @ConditionalOnMissingBean(DiscoveryClient.class) + @ConditionalOnStubbedDiscoveryEnabled public DiscoveryClient stubRunnerDiscoveryClient(StubFinder stubFinder, StubMapperProperties stubMapperProperties, @Value("${spring.application.name:unknown}") String springAppName) { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubsRegistrar.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubsRegistrar.java new file mode 100644 index 0000000000..0a344e4355 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubsRegistrar.java @@ -0,0 +1,12 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud; + +/** + * Contract for registering stubs in a Service Discovery. + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +public interface StubsRegistrar extends AutoCloseable { + void registerStubs(); +} \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/ConsulStubsRegistrar.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/ConsulStubsRegistrar.java new file mode 100644 index 0000000000..a0e0665c7f --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/ConsulStubsRegistrar.java @@ -0,0 +1,86 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud.consul; + +import java.lang.invoke.MethodHandles; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.cloud.contract.stubrunner.StubConfiguration; +import org.springframework.cloud.contract.stubrunner.StubRunning; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubsRegistrar; +import org.springframework.util.StringUtils; + +import com.ecwid.consul.v1.ConsulClient; +import com.ecwid.consul.v1.agent.model.NewService; + +/** + * Registers all stubs in Zookeeper Service Discovery + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +public class ConsulStubsRegistrar implements StubsRegistrar { + + private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + + private final StubRunning stubRunning; + private final ConsulClient consulClient; + private final StubMapperProperties stubMapperProperties; + private final List services = new LinkedList<>(); + + public ConsulStubsRegistrar(StubRunning stubRunning, ConsulClient consulClient, + StubMapperProperties stubMapperProperties) { + this.stubRunning = stubRunning; + this.consulClient = consulClient; + this.stubMapperProperties = stubMapperProperties; + } + + @Override public void registerStubs() { + Map activeStubs = this.stubRunning.runStubs() + .validNamesAndPorts(); + for (Map.Entry entry : activeStubs.entrySet()) { + NewService newService = newService(entry.getKey(), entry.getValue()); + this.services.add(newService); + try { + this.consulClient.agentServiceRegister(newService); + if (log.isDebugEnabled()) { + log.debug("Successfully registered stub [" + entry.getKey().toColonSeparatedDependencyNotation() + + "] in Service Discovery"); + } + } + catch (Exception e) { + log.warn("Exception occurred while trying to register a stub [" + entry.getKey().toColonSeparatedDependencyNotation() + + "] in Service Discovery", e); + } + } + } + + protected NewService newService(StubConfiguration stubConfiguration, Integer port) { + NewService newService = new NewService(); + newService.setAddress("localhost"); + newService.setId(stubConfiguration.getArtifactId()); + newService.setName(name(stubConfiguration)); + newService.setPort(port); + return newService; + } + + protected String name(StubConfiguration stubConfiguration) { + String resolvedName = this.stubMapperProperties.fromIvyNotationToId( + stubConfiguration.toColonSeparatedDependencyNotation()); + if (StringUtils.hasText(resolvedName)) { + return resolvedName; + } + return stubConfiguration.getArtifactId(); + } + + @Override + public void close() throws Exception { + for (NewService service : this.services) { + this.consulClient.agentServiceDeregister(service.getId()); + } + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfiguration.java new file mode 100644 index 0000000000..f43cdf1b29 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud.consul; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.contract.stubrunner.StubRunning; +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration; +import org.springframework.cloud.contract.stubrunner.spring.cloud.ConditionalOnStubbedDiscoveryDisabled; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubsRegistrar; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.ecwid.consul.v1.ConsulClient; + +/** + * Autoconfiguration for registering stubs in a Zookeeper Service discovery + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +@Configuration +@AutoConfigureAfter(StubRunnerConfiguration.class) +@ConditionalOnClass(ConsulClient.class) +@ConditionalOnStubbedDiscoveryDisabled +@ConditionalOnProperty(value = "stubrunner.cloud.consul.enabled", matchIfMissing = true) +public class StubRunnerSpringCloudConsulAutoConfiguration { + + @Bean(initMethod = "registerStubs") + public StubsRegistrar stubsRegistrar(StubRunning stubRunning, ConsulClient consulClient, + StubMapperProperties stubMapperProperties) { + return new ConsulStubsRegistrar(stubRunning, consulClient, stubMapperProperties); + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/ApplicationStatus.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/ApplicationStatus.java new file mode 100644 index 0000000000..244f132ccb --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/ApplicationStatus.java @@ -0,0 +1,25 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka; + +import com.netflix.appinfo.InstanceInfo; + +public class ApplicationStatus { + private Application application; + private InstanceInfo.InstanceStatus status; + + public ApplicationStatus(Application application, + InstanceInfo.InstanceStatus status) { + this.application = application; + this.status = status; + } + + public ApplicationStatus() { + } + + public Application getApplication() { + return application; + } + + public InstanceInfo.InstanceStatus getStatus() { + return status; + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/ConditionalOnEurekaEnabled.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/ConditionalOnEurekaEnabled.java new file mode 100644 index 0000000000..1e202a722b --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/ConditionalOnEurekaEnabled.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +/** + * Conditional that checks if Eureka is enabled + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Documented +@ConditionalOnProperty(value = "eureka.client.enabled", havingValue = "true", matchIfMissing = true) +@interface ConditionalOnEurekaEnabled { +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/Eureka.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/Eureka.java new file mode 100644 index 0000000000..96d7d13a1d --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/Eureka.java @@ -0,0 +1,334 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka; + +import java.lang.invoke.MethodHandles; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.cloud.netflix.eureka.CloudEurekaClient; +import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; +import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; +import org.springframework.cloud.netflix.eureka.InstanceInfoFactory; +import org.springframework.http.HttpStatus; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClientConfig; +import com.netflix.discovery.shared.Applications; +import com.netflix.discovery.shared.resolver.ClosableResolver; +import com.netflix.discovery.shared.resolver.EurekaEndpoint; +import com.netflix.discovery.shared.resolver.aws.ApplicationsResolver; +import com.netflix.discovery.shared.resolver.aws.AwsEndpoint; +import com.netflix.discovery.shared.transport.EurekaHttpClient; +import com.netflix.discovery.shared.transport.EurekaHttpClientFactory; +import com.netflix.discovery.shared.transport.EurekaHttpClients; +import com.netflix.discovery.shared.transport.EurekaHttpResponse; +import com.netflix.discovery.shared.transport.EurekaTransportConfig; +import com.netflix.discovery.shared.transport.TransportClientFactory; +import com.netflix.discovery.shared.transport.decorator.MetricsCollectingEurekaHttpClient; +import com.netflix.discovery.shared.transport.jersey.JerseyEurekaHttpClientFactory; +import com.sun.jersey.api.client.filter.ClientFilter; + +import static java.util.concurrent.TimeUnit.SECONDS; + +/** + * Taken from https://github.com/spencergibb/spring-cloud-netflix-eureka-lite + * + * @author Spencer Gibb + * + * @since 1.0.0 + */ +public class Eureka { + + private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + + private final InetUtils inetUtils; + final CloudEurekaClient eurekaClient; + final EurekaClientConfigBean clientConfig; + final EurekaTransport transport; + + public Eureka(InetUtils inetUtils, CloudEurekaClient eurekaClient) { + this.inetUtils = inetUtils; + this.eurekaClient = eurekaClient; + this.clientConfig = new EurekaClientConfigBean(); + this.clientConfig.setRegisterWithEureka(false); // turn off registering with eureka, let apps send heartbeats. + this.transport = createTransport(); + } + + public Registration register(Application application) { + long start = System.currentTimeMillis(); + if (log.isDebugEnabled()) { + log.debug(String.format("Starting registration of %s", application)); + } + InstanceInfo instanceInfo = getInstanceInfo(application); + Registration registration = new Registration(instanceInfo, application); + long duration = (System.currentTimeMillis() - start) ; + if (log.isDebugEnabled()) { + log.debug(String.format("Created registration for %s in %s ms", application, duration)); + } + register(registration); + return registration; + } + + public InstanceInfo getInstanceInfo(Application application, long lastUpdatedTimestamp, long lastDirtyTimestamp) { + InstanceInfo instanceInfo = getInstanceInfo(application); + instanceInfo = new InstanceInfo.Builder(instanceInfo) + .setLastDirtyTimestamp(lastDirtyTimestamp) + .setLastUpdatedTimestamp(lastUpdatedTimestamp) + .build(); + return instanceInfo; + } + + public InstanceInfo getInstanceInfo(Application application) { + EurekaInstanceConfigBean instanceConfig = new EurekaInstanceConfigBean(inetUtils); + instanceConfig.setInstanceEnabledOnit(true); + instanceConfig.setAppname(application.getName()); + instanceConfig.setVirtualHostName(application.getName()); + instanceConfig.setInstanceId(application.getInstance_id()); + instanceConfig.setHostname(application.getHostname()); + instanceConfig.setNonSecurePort(application.getPort()); + + return new InstanceInfoFactory().create(instanceConfig); + } + + public EurekaTransport createTransport() { + TransportClientFactory transportClientFactory = newTransportClientFactory(clientConfig, Collections.emptyList()); + EurekaTransportConfig transportConfig = clientConfig.getTransportConfig(); + + ClosableResolver bootstrapResolver = EurekaHttpClients.newBootstrapResolver( + clientConfig, + transportConfig, + transportClientFactory, + null, + new ApplicationsResolver.ApplicationsSource() { + @Override + public Applications getApplications(int stalenessThreshold, TimeUnit timeUnit) { + long thresholdInMs = TimeUnit.MILLISECONDS.convert(stalenessThreshold, timeUnit); + long delay = eurekaClient.getLastSuccessfulRegistryFetchTimePeriod(); + if (delay > thresholdInMs) { + log.info(String.format("Local registry is too stale for local lookup. Threshold:%s, actual:%s", + thresholdInMs, delay)); + return null; + } else { + return eurekaClient.getApplications(); + } + } + } + ); + + EurekaHttpClientFactory httpClientFactory; + try { + httpClientFactory = EurekaHttpClients.registrationClientFactory( + bootstrapResolver, + transportClientFactory, + transportConfig + ); + } catch (Exception e) { + log.warn("Experimental transport initialization failure", e); + throw new RuntimeException(e); + } + + return new EurekaTransport(httpClientFactory, httpClientFactory.newClient(), transportClientFactory, bootstrapResolver); + } + + public static TransportClientFactory newTransportClientFactory( + final EurekaClientConfig clientConfig, + final Collection additionalFilters) { + final TransportClientFactory jerseyFactory = JerseyEurekaHttpClientFactory.create( + clientConfig, additionalFilters, null, null); + final TransportClientFactory metricsFactory = MetricsCollectingEurekaHttpClient.createFactory(jerseyFactory); + + return new TransportClientFactory() { + @Override + public EurekaHttpClient newClient(EurekaEndpoint serviceUrl) { + return metricsFactory.newClient(serviceUrl); + } + + @Override + public void shutdown() { + metricsFactory.shutdown(); + jerseyFactory.shutdown(); + } + }; + } + + /** + * Renew with the eureka service by making the appropriate REST call + */ + public boolean renew(Registration registration) { + InstanceInfo instanceInfo = registration.getInstanceInfo(); + EurekaHttpResponse httpResponse; + try { + httpResponse = this.transport.getEurekaHttpClient().sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null); + if (log.isDebugEnabled()) { + log.debug(String.format("EurekaLite_%s/%s - Heartbeat status: %s", instanceInfo.getAppName(), instanceInfo.getId(), httpResponse.getStatusCode())); + } + if (httpResponse.getStatusCode() == HttpStatus.NOT_FOUND.value()) { + log.info(String.format("EurekaLite_%s/%s - Re-registering apps/%s", instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo.getAppName())); + return register(registration); + } + return httpResponse.getStatusCode() == HttpStatus.OK.value(); + } catch (Exception e) { + log.error("EurekaLite_"+instanceInfo.getAppName()+"/"+ instanceInfo.getId() + " - was unable to send heartbeat!", e); + return false; + } + } + + /** + * Register with the eureka service by making the appropriate REST call. + */ + protected boolean register(Registration registration) { + InstanceInfo instanceInfo = registration.getInstanceInfo(); + log.info(String.format("EurekaLite_%s/%s: registering service...", instanceInfo.getAppName(), instanceInfo.getId())); + EurekaHttpResponse httpResponse; + try { + httpResponse = this.transport.getEurekaHttpClient().register(instanceInfo); + } catch (Exception e) { + log.warn("EurekaLite_"+instanceInfo.getAppName()+"/"+ instanceInfo.getId() + " - registration failed " + e.getMessage(), e); + throw e; + } + if (log.isInfoEnabled()) { + log.info(String.format("EurekaLite_%s/%s - registration status: %s", instanceInfo.getAppName(), instanceInfo.getId(), httpResponse.getStatusCode())); + } + return httpResponse.getStatusCode() == HttpStatus.NO_CONTENT.value(); + } + + public void shutdown(Registration registration) { + InstanceInfo instanceInfo = registration.getInstanceInfo(); + try { + EurekaHttpResponse httpResponse = this.transport.getEurekaHttpClient().cancel(instanceInfo.getAppName(), instanceInfo.getInstanceId()); + log.info(String.format("EurekaLite_%s/%s - deregister status: %s", instanceInfo.getAppName(), instanceInfo.getId(), httpResponse.getStatusCode())); + } catch (Exception e) { + log.error("EurekaLite_"+instanceInfo.getAppName()+"/"+ instanceInfo.getId() + " - de-registration failed " + e.getMessage(), e); + } + this.transport.shutdown(); + } +} + +/** + * Taken from https://github.com/spencergibb/spring-cloud-netflix-eureka-lite + * + * @author Spencer Gibb + * + * @since 1.0.0 + */ +class EurekaTransport { + private final EurekaHttpClientFactory eurekaHttpClientFactory; + private final EurekaHttpClient eurekaHttpClient; + private final TransportClientFactory transportClientFactory; + private final ClosableResolver closableResolver; + + public EurekaTransport(EurekaHttpClientFactory eurekaHttpClientFactory, + EurekaHttpClient eurekaHttpClient, + TransportClientFactory transportClientFactory, + ClosableResolver closableResolver) { + this.eurekaHttpClientFactory = eurekaHttpClientFactory; + this.eurekaHttpClient = eurekaHttpClient; + this.transportClientFactory = transportClientFactory; + this.closableResolver = closableResolver; + } + + public void shutdown() { + eurekaHttpClientFactory.shutdown(); + eurekaHttpClient.shutdown(); + transportClientFactory.shutdown(); + closableResolver.shutdown(); + } + + public EurekaHttpClientFactory getEurekaHttpClientFactory() { + return eurekaHttpClientFactory; + } + + public EurekaHttpClient getEurekaHttpClient() { + return eurekaHttpClient; + } + + public TransportClientFactory getTransportClientFactory() { + return transportClientFactory; + } + + public ClosableResolver getClosableResolver() { + return closableResolver; + } +} + +/** + * Taken from https://github.com/spencergibb/spring-cloud-netflix-eureka-lite + * + * @author Spencer Gibb + * + * @since 1.0.0 + */ +class Application { + private String name; + private String instance_id; + private String hostname; + private int port; + + public Application(String name, String instance_id, String hostname, int port) { + this.name = name; + this.instance_id = instance_id; + this.hostname = hostname; + this.port = port; + } + + public Application() { + } + + @JsonIgnore + public String getRegistrationKey() { + return computeRegistrationKey(this.name, instance_id); + } + + static String computeRegistrationKey(String name, String instanceId) { + return name + ":" + instanceId; + } + + public String getName() { + return name; + } + + public String getInstance_id() { + return instance_id; + } + + public String getHostname() { + return hostname; + } + + public int getPort() { + return port; + } +} + +/** + * Scheduled service that automatically will renew registrations in Eureka + */ +class Renewer implements Runnable { + + private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + + final Eureka eureka; + final Registration registration; + final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + Renewer(int flushInterval, Eureka eureka, + Registration registration) { + this.eureka = eureka; + this.registration = registration; + this.scheduler.scheduleWithFixedDelay(this, 0, flushInterval, SECONDS); + } + + @Override + public void run() { + if (log.isTraceEnabled()) { + log.trace("Renewing registration [" + this.registration + "]"); + } + this.eureka.renew(this.registration); + } +} \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/EurekaStubsRegistrar.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/EurekaStubsRegistrar.java new file mode 100644 index 0000000000..b0e7402f9e --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/EurekaStubsRegistrar.java @@ -0,0 +1,75 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka; + +import java.lang.invoke.MethodHandles; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.cloud.contract.stubrunner.StubConfiguration; +import org.springframework.cloud.contract.stubrunner.StubRunning; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubsRegistrar; +import org.springframework.util.StringUtils; + +/** + * Registers all stubs in Eureka Service Discovery + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +public class EurekaStubsRegistrar implements StubsRegistrar { + + private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + + private final StubRunning stubRunning; + private final Eureka eurekaClient; + private final StubMapperProperties stubMapperProperties; + private final List discoveryList = new LinkedList<>(); + + public EurekaStubsRegistrar(StubRunning stubRunning, Eureka eureka, + StubMapperProperties stubMapperProperties) { + this.stubRunning = stubRunning; + this.stubMapperProperties = stubMapperProperties; + this.eurekaClient = eureka; + } + + @Override public void registerStubs() { + Map activeStubs = this.stubRunning.runStubs() + .validNamesAndPorts(); + for (Map.Entry entry : activeStubs.entrySet()) { + Application application = new Application(name(entry.getKey()), entry.getKey().getArtifactId(), "localhost", entry.getValue()); + try { + Registration register = this.eurekaClient.register(application); + this.discoveryList.add(new Renewer(this.eurekaClient.clientConfig.getInstanceInfoReplicationIntervalSeconds() / 2, this.eurekaClient, register)); + if (log.isDebugEnabled()) { + log.debug("Successfully registered stub [" + entry.getKey().toColonSeparatedDependencyNotation() + + "] in Service Discovery"); + } + } + catch (Exception e) { + log.warn("Exception occurred while trying to register a stub [" + entry.getKey().toColonSeparatedDependencyNotation() + + "] in Service Discovery", e); + } + } + } + + private String name(StubConfiguration stubConfiguration) { + String resolvedName = this.stubMapperProperties.fromIvyNotationToId( + stubConfiguration.toColonSeparatedDependencyNotation()); + if (StringUtils.hasText(resolvedName)) { + return resolvedName; + } + return stubConfiguration.getArtifactId(); + } + + @Override + public void close() throws Exception { + for (Renewer renewer : this.discoveryList) { + this.eurekaClient.shutdown(renewer.registration); + renewer.scheduler.shutdown(); + } + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/Registration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/Registration.java new file mode 100644 index 0000000000..3f615be875 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/Registration.java @@ -0,0 +1,45 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka; + +import com.netflix.appinfo.InstanceInfo; + +/** + * Taken from https://github.com/spencergibb/spring-cloud-netflix-eureka-lite + * + * @author Spencer Gibb + * + * @since 1.0.0 + */ +public class Registration { + private final InstanceInfo instanceInfo; + private final ApplicationStatus applicationStatus; + + public Registration(InstanceInfo instanceInfo, ApplicationStatus applicationStatus) { + this.instanceInfo = instanceInfo; + this.applicationStatus = applicationStatus; + } + + public Registration(InstanceInfo instanceInfo, Application application) { + this(instanceInfo, new ApplicationStatus(application, InstanceInfo.InstanceStatus.UP)); + } + + public String getRegistrationKey() { + return this.applicationStatus.getApplication().getRegistrationKey(); + } + + public String getApplicationName() { + return this.applicationStatus.getApplication().getName(); + } + + public InstanceInfo getInstanceInfo() { + return instanceInfo; + } + + public ApplicationStatus getApplicationStatus() { + return applicationStatus; + } + + @Override public String toString() { + return "Registration{" + "instanceInfo=" + instanceInfo + ", applicationStatus=" + + applicationStatus + '}'; + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/StubRunnerSpringCloudEurekaAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/StubRunnerSpringCloudEurekaAutoConfiguration.java new file mode 100644 index 0000000000..78108111df --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/StubRunnerSpringCloudEurekaAutoConfiguration.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.cloud.contract.stubrunner.StubRunning; +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration; +import org.springframework.cloud.contract.stubrunner.spring.cloud.ConditionalOnStubbedDiscoveryDisabled; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubsRegistrar; +import org.springframework.cloud.netflix.eureka.CloudEurekaClient; +import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.netflix.appinfo.ApplicationInfoManager; +import com.netflix.discovery.EurekaClientConfig; + +/** + * Autoconfiguration for registering stubs in a Eureka Service discovery + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +@Configuration +@AutoConfigureAfter({StubRunnerConfiguration.class, EurekaClientAutoConfiguration.class}) +@ConditionalOnClass(CloudEurekaClient.class) +@ConditionalOnStubbedDiscoveryDisabled +@ConditionalOnEurekaEnabled +@ConditionalOnProperty(value = "stubrunner.cloud.eureka.enabled", matchIfMissing = true) +public class StubRunnerSpringCloudEurekaAutoConfiguration { + + @Bean(initMethod = "registerStubs") + public StubsRegistrar stubsRegistrar(StubRunning stubRunning, Eureka eureka, + StubMapperProperties stubMapperProperties) { + return new EurekaStubsRegistrar(stubRunning, eureka, stubMapperProperties); + } + + @Bean(name = "eurekaRegistrar") + public Eureka eureka(InetUtils inetUtils, ApplicationInfoManager manager, + EurekaClientConfig config, ApplicationContext applicationContext) { + return new Eureka(inetUtils, new CloudEurekaClient(manager, config, applicationContext)); + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonAutoConfiguration.java index 7e886e6eac..2fe2a3da76 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonAutoConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonAutoConfiguration.java @@ -16,21 +16,24 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud.ribbon; -import com.netflix.loadbalancer.ServerList; -import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.contract.stubrunner.spring.cloud.ConditionalOnStubbedDiscoveryEnabled; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import org.springframework.cloud.netflix.ribbon.RibbonClients; import org.springframework.context.annotation.Configuration; +import com.netflix.loadbalancer.ServerList; + @Configuration @ConditionalOnClass(ServerList.class) @ConditionalOnBean(StubMapperProperties.class) @AutoConfigureAfter(RibbonAutoConfiguration.class) @RibbonClients(defaultConfiguration = StubRunnerRibbonConfiguration.class) +@ConditionalOnStubbedDiscoveryEnabled @ConditionalOnProperty(value = "stubrunner.cloud.ribbon.enabled", matchIfMissing = true) public class StubRunnerRibbonAutoConfiguration { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonServerList.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonServerList.java index a5915347bb..55dbf11ef4 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonServerList.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/ribbon/StubRunnerRibbonServerList.java @@ -43,9 +43,8 @@ class StubRunnerRibbonServerList implements ServerList { private final ServerList serverList; StubRunnerRibbonServerList(final StubFinder stubFinder, - final StubMapperProperties stubMapperProperties, - final IClientConfig clientConfig, - final ServerList delegate) { + final StubMapperProperties stubMapperProperties, + final IClientConfig clientConfig, final ServerList delegate) { String serviceName = clientConfig.getClientName(); String mappedServiceName = StringUtils .hasText(stubMapperProperties.fromServiceIdToIvyNotation(serviceName)) ? diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/StubRunnerSpringCloudZookeeperAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/StubRunnerSpringCloudZookeeperAutoConfiguration.java new file mode 100644 index 0000000000..b0ba46fbd2 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/StubRunnerSpringCloudZookeeperAutoConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud.zookeeper; + +import org.apache.curator.framework.CuratorFramework; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.contract.stubrunner.StubRunning; +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration; +import org.springframework.cloud.contract.stubrunner.spring.cloud.ConditionalOnStubbedDiscoveryDisabled; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubsRegistrar; +import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Autoconfiguration for registering stubs in a Zookeeper Service discovery + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +@Configuration +@AutoConfigureAfter(StubRunnerConfiguration.class) +@ConditionalOnBean({ CuratorFramework.class, ZookeeperDiscoveryProperties.class}) +@ConditionalOnClass(org.apache.curator.x.discovery.ServiceInstance.class) +@ConditionalOnStubbedDiscoveryDisabled +@ConditionalOnProperty(value = "stubrunner.cloud.zookeeper.enabled", matchIfMissing = true) +public class StubRunnerSpringCloudZookeeperAutoConfiguration { + + @Bean(initMethod = "registerStubs") + public StubsRegistrar stubsRegistrar(StubRunning stubRunning, CuratorFramework curatorFramework, + StubMapperProperties stubMapperProperties, ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) { + return new ZookeeperStubsRegistrar(stubRunning, curatorFramework, stubMapperProperties, zookeeperDiscoveryProperties); + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/ZookeeperStubsRegistrar.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/ZookeeperStubsRegistrar.java new file mode 100644 index 0000000000..2473211582 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/ZookeeperStubsRegistrar.java @@ -0,0 +1,101 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud.zookeeper; + +import java.lang.invoke.MethodHandles; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.x.discovery.ServiceDiscovery; +import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; +import org.apache.curator.x.discovery.ServiceInstance; +import org.apache.curator.x.discovery.UriSpec; +import org.springframework.cloud.contract.stubrunner.StubConfiguration; +import org.springframework.cloud.contract.stubrunner.StubRunning; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubsRegistrar; +import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties; +import org.springframework.util.StringUtils; + +/** + * Registers all stubs in Zookeeper Service Discovery + * + * @author Marcin Grzejszczak + * + * @since 1.0.0 + */ +public class ZookeeperStubsRegistrar implements StubsRegistrar { + + private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + + private final StubRunning stubRunning; + private final CuratorFramework curatorFramework; + private final StubMapperProperties stubMapperProperties; + private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; + private final List discoveryList = new LinkedList<>(); + + public ZookeeperStubsRegistrar(StubRunning stubRunning, CuratorFramework curatorFramework, + StubMapperProperties stubMapperProperties, + ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) { + this.stubRunning = stubRunning; + this.curatorFramework = curatorFramework; + this.stubMapperProperties = stubMapperProperties; + this.zookeeperDiscoveryProperties = zookeeperDiscoveryProperties; + } + + @Override public void registerStubs() { + Map activeStubs = this.stubRunning.runStubs() + .validNamesAndPorts(); + for (Map.Entry entry : activeStubs.entrySet()) { + ServiceInstance serviceInstance = serviceInstance(entry.getKey(), entry.getValue()); + ServiceDiscovery serviceDiscovery = serviceDiscovery(serviceInstance); + this.discoveryList.add(serviceDiscovery); + try { + serviceDiscovery.start(); + if (log.isDebugEnabled()) { + log.debug("Successfully registered stub [" + entry.getKey().toColonSeparatedDependencyNotation() + + "] in Service Discovery"); + } + } + catch (Exception e) { + log.warn("Exception occurred while trying to register a stub [" + entry.getKey().toColonSeparatedDependencyNotation() + + "] in Service Discovery", e); + } + } + } + + protected ServiceInstance serviceInstance(StubConfiguration stubConfiguration, int port) { + try { + return ServiceInstance.builder().uriSpec(new UriSpec(this.zookeeperDiscoveryProperties.getUriSpec())) + .address("localhost").port(port).name(name(stubConfiguration)) + .build(); + } + catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private String name(StubConfiguration stubConfiguration) { + String resolvedName = this.stubMapperProperties.fromIvyNotationToId( + stubConfiguration.toColonSeparatedDependencyNotation()); + if (StringUtils.hasText(resolvedName)) { + return resolvedName; + } + return stubConfiguration.getArtifactId(); + } + + protected ServiceDiscovery serviceDiscovery(ServiceInstance serviceInstance) { + return ServiceDiscoveryBuilder.builder(Void.class) + .basePath(this.zookeeperDiscoveryProperties.getRoot()) + .client(this.curatorFramework).thisInstance(serviceInstance).build(); + } + + @Override + public void close() throws Exception { + for (ServiceDiscovery discovery : this.discoveryList) { + discovery.close(); + } + } +} diff --git a/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories index 3fdb01c748..dfd9b8215b 100644 --- a/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories @@ -5,4 +5,7 @@ org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloud org.springframework.cloud.contract.stubrunner.spring.cloud.ribbon.StubRunnerRibbonAutoConfiguration,\ org.springframework.cloud.contract.stubrunner.messaging.stream.StubRunnerStreamConfiguration,\ org.springframework.cloud.contract.stubrunner.messaging.integration.StubRunnerIntegrationConfiguration,\ -org.springframework.cloud.contract.stubrunner.messaging.camel.StubRunnerCamelConfiguration +org.springframework.cloud.contract.stubrunner.messaging.camel.StubRunnerCamelConfiguration,\ +org.springframework.cloud.contract.stubrunner.spring.cloud.zookeeper.StubRunnerSpringCloudZookeeperAutoConfiguration,\ +org.springframework.cloud.contract.stubrunner.spring.cloud.eureka.StubRunnerSpringCloudEurekaAutoConfiguration,\ +org.springframework.cloud.contract.stubrunner.spring.cloud.consul.StubRunnerSpringCloudConsulAutoConfiguration diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AdhocTestSuite.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AdhocTestSuite.groovy deleted file mode 100644 index 3bf905cf9b..0000000000 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AdhocTestSuite.groovy +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.stubrunner; - -import org.junit.Ignore -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses -import org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfigurationSpec -import org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloudAutoConfigurationSpec - -/** - * A test suite for probing weird ordering problems in the tests. - * - * @author Dave Syer - */ -@RunWith(Suite) -@SuiteClasses([ - StubRunnerSpringCloudAutoConfigurationSpec, - StubRunnerConfigurationSpec - ]) -@Ignore -public class AdhocTestSuite { - -} diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubConfigurationSpec.groovy index 0e5d631d8d..6f6587f97c 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubConfigurationSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubConfigurationSpec.groovy @@ -34,4 +34,13 @@ class StubConfigurationSpec extends Specification { stubConfiguration.classifier == 'classifier' stubConfiguration.version == 'version' } + + def 'should return ivy notation'() { + given: + String ivy = 'group:artifact:version:classifier' + when: + StubConfiguration stubConfiguration = new StubConfiguration(ivy) + then: + stubConfiguration.toColonSeparatedDependencyNotation() == ivy + } } diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootConsulExample.java b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootConsulExample.java new file mode 100644 index 0000000000..8760b75f7e --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootConsulExample.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.serverexamples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.contract.stubrunner.server.EnableStubRunnerServer; +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; + +/** + * @author Marcin Grzejszczak + */ +@SpringBootApplication +@EnableStubRunnerServer +@EnableDiscoveryClient +@AutoConfigureStubRunner +public class StubRunnerBootConsulExample { + + public static void main(String[] args) { + SpringApplication.run(StubRunnerBootConsulExample.class, args); + } + +} +/* + +-Dstubrunner.repositoryRoot=classpath:m2repo/repository/ +-Dstubrunner.cloud.stubbed.discovery.enabled=false +-Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService +-Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer +-Dstubrunner.cloud.consul.enabled=true +-Dstubrunner.camel.enabled=false +-Dspring.cloud.zookeeper.enabled=false +-Deureka.client.enabled=false +-Dspring.cloud.zookeeper.discovery.enabled=false +-Ddebug=true +-Dspring.cloud.consul.host=192.168.99.100 + + */ diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootEurekaExample.java b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootEurekaExample.java new file mode 100644 index 0000000000..a699c68415 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootEurekaExample.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.serverexamples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.contract.stubrunner.server.EnableStubRunnerServer; +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +/** + * @author Marcin Grzejszczak + */ +// tag::stubrunnereureka[] +@SpringBootApplication +@EnableStubRunnerServer +@EnableEurekaClient +@AutoConfigureStubRunner +public class StubRunnerBootEurekaExample { + + public static void main(String[] args) { + SpringApplication.run(StubRunnerBootEurekaExample.class, args); + } + +} +// end::stubrunnereureka[] + +/* + +// tag::stubrunnereureka_args[] +-Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1) +-Dstubrunner.cloud.stubbed.discovery.enabled=false (2) +-Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService (3) +-Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer (4) + +(1) - we tell Stub Runner where all the stubs reside +(2) - we don't want the default behaviour where the discovery service is stubbed. That's why the stub registration will be picked +(3) - we provide a list of stubs to download +(4) - we provide a list of artifactId to serviceId mapping +// end::stubrunnereureka_args[] + + +-Dstubrunner.cloud.eureka.enabled=true +-Dstubrunner.repositoryRoot=classpath:m2repo/repository/ +-Dstubrunner.camel.enabled=false +-Dspring.cloud.zookeeper.enabled=false +-Dspring.cloud.zookeeper.discovery.enabled=false +-Ddebug=true + + */ diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootZookeeperExample.java b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootZookeeperExample.java new file mode 100644 index 0000000000..3cf64bc64c --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/serverexamples/StubRunnerBootZookeeperExample.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.serverexamples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.contract.stubrunner.server.EnableStubRunnerServer; +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; + +/** + * @author Marcin Grzejszczak + */ +@SpringBootApplication +@EnableStubRunnerServer +@EnableDiscoveryClient +@AutoConfigureStubRunner +public class StubRunnerBootZookeeperExample { + + public static void main(String[] args) { + SpringApplication.run(StubRunnerBootZookeeperExample.class, args); + } + +} +/* + +-Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService +-Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer +-Dstubrunner.cloud.stubbed.discovery.enabled=false +-Dstubrunner.cloud.zookeepr.enabled=true +-Dstubrunner.repositoryRoot=classpath:m2repo/repository/ +-Dstubrunner.camel.enabled=false +-Deureka.client.enabled=false +-Ddebug=true + + */ diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperPropertiesSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperPropertiesSpec.groovy new file mode 100644 index 0000000000..a85ade9f73 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubMapperPropertiesSpec.groovy @@ -0,0 +1,21 @@ +package org.springframework.cloud.contract.stubrunner.spring.cloud + +import spock.lang.Specification + +/** + * @author Marcin Grzejszczak + */ +class StubMapperPropertiesSpec extends Specification { + + def "should convert ivy notation to serviceId by fallbacking to artifactId if nothing else matches"() { + given: + Map idsToServiceIds = [ + fraudDetectionServer: 'someNameThatShouldMapFraudDetectionServer' + ] + StubMapperProperties properties = new StubMapperProperties(idsToServiceIds: idsToServiceIds) + expect: + 'someNameThatShouldMapFraudDetectionServer' == properties.fromIvyNotationToId('fraudDetectionServer') + 'someNameThatShouldMapFraudDetectionServer' == properties.fromIvyNotationToId('groupid:fraudDetectionServer') + 'someNameThatShouldMapFraudDetectionServer' == properties.fromIvyNotationToId('groupid:fraudDetectionServer:+:classifier') + } +} diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy index d4719ad57e..b4a795ee25 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy @@ -16,34 +16,37 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud -import org.apache.curator.test.TestingServer import org.junit.AfterClass import org.junit.BeforeClass import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest -import org.springframework.cloud.client.discovery.EnableDiscoveryClient import org.springframework.cloud.client.loadbalancer.LoadBalanced +import org.springframework.cloud.consul.ConsulAutoConfiguration import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner -import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties -import org.springframework.cloud.zookeeper.ZookeeperProperties -import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery +import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration +import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration +import org.springframework.cloud.zookeeper.discovery.RibbonZookeeperAutoConfiguration import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration -import org.springframework.util.SocketUtils import org.springframework.web.client.RestTemplate import spock.lang.Specification - /** * @author Marcin Grzejszczak */ @ContextConfiguration(classes = Config, loader = SpringBootContextLoader) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = ["stubrunner.camel.enabled=false"]) + properties = ["stubrunner.camel.enabled=false", + "spring.cloud.zookeeper.enabled=false", + "spring.cloud.consul.enabled=false", + "eureka.client.enabled=false", + "stubrunner.cloud.stubbed.discovery.enabled=true", + "spring.cloud.consul.discovery.enabled=false", + "spring.cloud.zookeeper.discovery.enabled=false"]) // tag::autoconfigure[] @AutoConfigureStubRunner( ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", @@ -56,9 +59,6 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification { @Autowired StubFinder stubFinder @Autowired @LoadBalanced RestTemplate restTemplate - // TODO: this shouldn't be needed? - @Autowired ZookeeperServiceDiscovery zookeeperServiceDiscovery - @Autowired StubRunnerProperties stubRunnerProperties @BeforeClass @AfterClass @@ -67,10 +67,6 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification { System.clearProperty("stubrunner.classifier") } - def setup() { - println "StubRunner properties are [$stubRunnerProperties]" - } - // tag::test[] def 'should make service discovery work'() { expect: 'WireMocks are running' @@ -82,29 +78,11 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification { } // end::test[] - TestingServer startTestingServer() { - return new TestingServer(SocketUtils.findAvailableTcpPort()) - } - - def cleanup() { - zookeeperServiceDiscovery?.serviceDiscovery?.close() - } - @Configuration - @EnableAutoConfiguration - @EnableDiscoveryClient + @EnableAutoConfiguration(exclude = [RibbonZookeeperAutoConfiguration, EurekaClientAutoConfiguration, + ConsulAutoConfiguration, ZookeeperAutoConfiguration]) static class Config { - @Bean - TestingServer testingServer() { - return new TestingServer(SocketUtils.findAvailableTcpPort()) - } - - @Bean - ZookeeperProperties zookeeperProperties() { - return new ZookeeperProperties(connectString: testingServer().connectString) - } - @Bean @LoadBalanced RestTemplate restTemplate() { diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfigurationSpec.groovy new file mode 100644 index 0000000000..334b511fbc --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfigurationSpec.groovy @@ -0,0 +1,114 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud.consul + +import com.ecwid.consul.v1.ConsulClient +import com.ecwid.consul.v1.agent.model.NewService +import org.hamcrest.Description +import org.hamcrest.TypeSafeMatcher +import org.junit.AfterClass +import org.junit.BeforeClass +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.context.SpringBootContextLoader +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.cloud.client.discovery.EnableDiscoveryClient +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import spock.lang.Specification + +import static org.mockito.BDDMockito.then +import static org.mockito.Matchers.argThat +import static org.mockito.Mockito.mock +/** + * @author Marcin Grzejszczak + */ +@ContextConfiguration(classes = Config, loader = SpringBootContextLoader) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = ["stubrunner.camel.enabled=false", + "eureka.client.enabled=false", + "spring.cloud.zookeeper.enabled=false", + "stubrunner.cloud.stubbed.discovery.enabled=false", + "stubrunner.cloud.eureka.enabled=false", + "spring.cloud.zookeeper.discovery.enabled=false", + "stubrunner.cloud.consul.enabled=true", + "stubrunner.cloud.zookeeper.enabled=false", + "debug=true"]) +@AutoConfigureStubRunner( ids = + ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer", + "org.springframework.cloud.contract.verifier.stubs:bootService"], + repositoryRoot = "classpath:m2repo/repository/") +@DirtiesContext +class StubRunnerSpringCloudConsulAutoConfigurationSpec extends Specification { + + @Autowired ConsulClient client + + @BeforeClass + @AfterClass + static void setupProps() { + System.clearProperty("stubrunner.stubs.repository.root"); + System.clearProperty("stubrunner.stubs.classifier"); + } + + def 'should make service discovery work for #serviceName'() { + given: + final String expectedId = serviceName.split(':')[0] + final String expectedName = serviceName.split(':')[1] + when: 'Consul registration took place for 3 stubs' + then(client).should().agentServiceRegister(argThat(new NewServiceMatcher(expectedId, expectedName))) + then: + noExceptionThrown() + where: + serviceName << ['loanIssuance:loanIssuance', 'bootService:bootService', 'fraudDetectionServer:someNameThatShouldMapFraudDetectionServer'] + } + + private static class NewServiceMatcher extends TypeSafeMatcher { + + private final String expectedId + private final String expectedName + + NewServiceMatcher(String expectedId, String expectedName) { + this.expectedId = expectedId + this.expectedName = expectedName + } + + @Override + protected boolean matchesSafely(NewService item) { + return item.id == expectedId && item.name == expectedName + } + + @Override + void describeTo(Description description) { + + } + } + + @Configuration + @EnableAutoConfiguration + @EnableDiscoveryClient + static class Config { + + @Bean + ConsulClient mockedConsulClient() { + return mock(ConsulClient) + } + } +} diff --git a/spring-cloud-contract-stub-runner/src/test/resources/application-eureka.yml b/spring-cloud-contract-stub-runner/src/test/resources/application-eureka.yml new file mode 100644 index 0000000000..4ebdf98ff4 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/resources/application-eureka.yml @@ -0,0 +1,9 @@ +eureka: + enableSelfPreservation: false + client: + fetchRegistry: false + initialInstanceInfoReplicationIntervalSeconds: 1 + instance: + registryFetchIntervalSeconds: 5 + leaseRenewalIntervalInSeconds: 5 + leaseExpirationDurationInSeconds: 5 \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/src/test/resources/application.yml b/spring-cloud-contract-stub-runner/src/test/resources/application.yml index 2eaffb52e9..ccdd6c32f8 100644 --- a/spring-cloud-contract-stub-runner/src/test/resources/application.yml +++ b/spring-cloud-contract-stub-runner/src/test/resources/application.yml @@ -1,4 +1,9 @@ +spring.cloud: + zookeeper.enabled: false + consul.enabled: false +eureka.client.enabled: false stubrunner: + camel.enabled: false idsToServiceIds: ivyNotation: someValueInsideYourCode fraudDetectionServer: someNameThatShouldMapFraudDetectionServer \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java index 5dd82a7fb1..aff8c210d0 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java @@ -40,7 +40,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { final LinkedList methodsBuffer; DelegatingJsonVerifiable(JsonVerifiable delegate, - LinkedList methodsBuffer) { + LinkedList methodsBuffer) { this.delegate = delegate; this.methodsBuffer = new LinkedList<>(methodsBuffer); } @@ -62,7 +62,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { } private void appendMethodWithValue(String methodName, Object value) { - methodsBuffer.offer("." + methodName + "(" + value + ")"); + this.methodsBuffer.offer("." + methodName + "(" + value + ")"); } private void appendMethodWithQuotedValue(String methodName, Object value) { @@ -71,7 +71,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable contains(Object value) { - DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(delegate.contains(value), methodsBuffer); + DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.contains(value), this.methodsBuffer); verifiable.appendMethodWithQuotedValue("contains", value); if (isAssertingAValueInArray()) { verifiable.methodsBuffer.offer(".value()"); @@ -82,8 +82,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable field(Object value) { Object valueToPut = value instanceof ShouldTraverse ? ((ShouldTraverse) value).value : value; - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.field(valueToPut), methodsBuffer); - if (delegate.isIteratingOverArray() && !(value instanceof ShouldTraverse)) { + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(valueToPut), this.methodsBuffer); + if (this.delegate.isIteratingOverArray() && !(value instanceof ShouldTraverse)) { verifiable.appendMethodWithQuotedValue("contains", valueToPut); } else { verifiable.appendMethodWithQuotedValue("field", valueToPut); @@ -102,51 +102,51 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable array(Object value) { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.array(value), methodsBuffer); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(value), this.methodsBuffer); verifiable.appendMethodWithQuotedValue("array", value); return verifiable; } @Override public MethodBufferingJsonVerifiable arrayField(Object value) { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.field(value).arrayField(), methodsBuffer); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(value).arrayField(), this.methodsBuffer); verifiable.appendMethodWithQuotedValue("array", value); return verifiable; } @Override public MethodBufferingJsonVerifiable arrayField() { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.arrayField(), methodsBuffer); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.arrayField(), this.methodsBuffer); verifiable.methodsBuffer.offer(".arrayField()"); return verifiable; } @Override public MethodBufferingJsonVerifiable array() { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.array(), methodsBuffer); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(), this.methodsBuffer); verifiable.methodsBuffer.offer(".array()"); return verifiable; } @Override public JsonVerifiable elementWithIndex(int i) { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.elementWithIndex(i), methodsBuffer); - verifiable.methodsBuffer.offer(".elementWithIndex(" + i + ")"); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.elementWithIndex(i), this.methodsBuffer); + this.methodsBuffer.offer(".elementWithIndex(" + i + ")"); return verifiable; } @Override public MethodBufferingJsonVerifiable iterationPassingArray() { - return new DelegatingJsonVerifiable(delegate, methodsBuffer); + return new DelegatingJsonVerifiable(this.delegate, this.methodsBuffer); } @Override public MethodBufferingJsonVerifiable isEqualTo(String value) { - DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isEqualTo(value), methodsBuffer); - if (delegate.isAssertingAValueInArray() && readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) { + DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer); + if (this.delegate.isAssertingAValueInArray() && readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) { readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value)); readyToCheck.methodsBuffer.offer(".value()"); - } else if (delegate.isAssertingAValueInArray() && !readyToCheck.methodsBuffer.peekLast().contains("array")) { + } else if (this.delegate.isAssertingAValueInArray() && !readyToCheck.methodsBuffer.peekLast().contains("array")) { readyToCheck.methodsBuffer.offer(".value()"); } else { readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value)); @@ -164,11 +164,11 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable isEqualTo(Number value) { - DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isEqualTo(value), methodsBuffer); + DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer); // related to #271 - the problem is with asserting arrays of maps vs arrays of primitives String last = readyToCheck.methodsBuffer.peekLast(); boolean containsAMatcher = containsAnyMatcher(last); - if (delegate.isAssertingAValueInArray() && containsAMatcher) { + if (this.delegate.isAssertingAValueInArray() && containsAMatcher) { readyToCheck.methodsBuffer.offer(".value()"); } else { readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value)); @@ -182,15 +182,15 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable isNull() { - DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isNull(), methodsBuffer); + DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isNull(), this.methodsBuffer); readyToCheck.methodsBuffer.offer(".isNull()"); return readyToCheck; } @Override public MethodBufferingJsonVerifiable matches(String value) { - DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.matches(value), methodsBuffer); - if (delegate.isAssertingAValueInArray()) { + DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.matches(value), this.methodsBuffer); + if (this.delegate.isAssertingAValueInArray()) { readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value)); readyToCheck.methodsBuffer.offer(".value()"); } else { @@ -201,8 +201,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable isEqualTo(Boolean value) { - DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isEqualTo(value), methodsBuffer); - if (delegate.isAssertingAValueInArray()) { + DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer); + if (this.delegate.isAssertingAValueInArray()) { readyToCheck.methodsBuffer.offer(".value()"); } else { readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value)); @@ -212,12 +212,12 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable value() { - return new FinishedDelegatingJsonVerifiable(delegate, methodsBuffer); + return new FinishedDelegatingJsonVerifiable(this.delegate, this.methodsBuffer); } @Override public boolean assertsSize() { - for (String s : methodsBuffer) { + for (String s : this.methodsBuffer) { if (s.contains(".hasSize(")) { return true; } @@ -227,7 +227,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public boolean assertsConcreteValue() { - for (String s : methodsBuffer) { + for (String s : this.methodsBuffer) { if (FIELD_PATTERN.matcher(s).matches()|| ARRAY_PATTERN.matcher(s).matches()) { return true; } @@ -237,39 +237,39 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public JsonVerifiable withoutThrowingException() { - return delegate.withoutThrowingException(); + return this.delegate.withoutThrowingException(); } @Override public String jsonPath() { - return delegate.jsonPath(); + return this.delegate.jsonPath(); } @Override public void matchesJsonPath(String s) { - delegate.matchesJsonPath(s); + this.delegate.matchesJsonPath(s); } @Override public JsonVerifiable hasSize(int size) { - FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(delegate.hasSize(size), methodsBuffer); + FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.hasSize(size), this.methodsBuffer); verifiable.methodsBuffer.offer(".hasSize(" + size + ")"); return verifiable; } @Override public boolean isIteratingOverNamelessArray() { - return delegate.isIteratingOverNamelessArray(); + return this.delegate.isIteratingOverNamelessArray(); } @Override public boolean isIteratingOverArray() { - return delegate.isIteratingOverArray(); + return this.delegate.isIteratingOverArray(); } @Override public boolean isAssertingAValueInArray() { - return delegate.isAssertingAValueInArray(); + return this.delegate.isAssertingAValueInArray(); } @Override @@ -278,7 +278,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { } private String createMethodString() { - LinkedList queue = new LinkedList<>(methodsBuffer); + LinkedList queue = new LinkedList<>(this.methodsBuffer); StringBuilder stringBuffer = new StringBuilder(); while (!queue.isEmpty()) { stringBuffer.append(queue.remove()); @@ -295,33 +295,33 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { DelegatingJsonVerifiable that = (DelegatingJsonVerifiable) o; - if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) + if (this.delegate != null ? !this.delegate.equals(that.delegate) : that.delegate != null) return false; - if (delegate == null) { + if (this.delegate == null) { return false; } - if (delegate.jsonPath() == null && that.delegate.jsonPath() == null) + if (this.delegate.jsonPath() == null && that.delegate.jsonPath() == null) return true; - return delegate.jsonPath().equals(that.delegate.jsonPath()); + return this.delegate.jsonPath().equals(that.delegate.jsonPath()); } @Override public int hashCode() { - int result = delegate != null ? delegate.jsonPath().hashCode() : 0; + int result = this.delegate != null ? this.delegate.jsonPath().hashCode() : 0; return 31 * result; } @Override public String toString() { return "DelegatingJsonVerifiable{" + - "delegate=\n" + delegate + - ", methodsBuffer=" + methodsBuffer + + "delegate=\n" + this.delegate + + ", methodsBuffer=" + this.methodsBuffer + '}'; } @Override public T read(Class aClass) { - return delegate.read(aClass); + return this.delegate.read(aClass); } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/FinishedDelegatingJsonVerifiable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/FinishedDelegatingJsonVerifiable.java index 000d6e75a4..6b11714a2f 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/FinishedDelegatingJsonVerifiable.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/FinishedDelegatingJsonVerifiable.java @@ -31,7 +31,7 @@ import com.toomuchcoding.jsonassert.JsonVerifiable; class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable { FinishedDelegatingJsonVerifiable(JsonVerifiable delegate, - LinkedList methodsBuffer) { + LinkedList methodsBuffer) { super(delegate, methodsBuffer); } diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/CamelStubMessages.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/CamelStubMessages.java index 058dd13b99..ae1272d4a4 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/CamelStubMessages.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/CamelStubMessages.java @@ -51,8 +51,8 @@ public class CamelStubMessages implements MessageVerifier { @Override public void send(Message message, String destination) { try { - ProducerTemplate producerTemplate = context.createProducerTemplate(); - Exchange exchange = new DefaultExchange(context); + ProducerTemplate producerTemplate = this.context.createProducerTemplate(); + Exchange exchange = new DefaultExchange(this.context); exchange.setIn(message); producerTemplate.send(destination, exchange); } catch (Exception e) { @@ -64,13 +64,13 @@ public class CamelStubMessages implements MessageVerifier { @Override public void send(T payload, Map headers, String destination) { - send(builder.create(payload, headers), destination); + send(this.builder.create(payload, headers), destination); } @Override public Message receive(String destination, long timeout, TimeUnit timeUnit) { try { - ConsumerTemplate consumerTemplate = context.createConsumerTemplate(); + ConsumerTemplate consumerTemplate = this.context.createConsumerTemplate(); Exchange exchange = consumerTemplate.receive(destination, timeUnit.toMillis(timeout)); return exchange.getIn(); } catch (Exception e) { diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/integration/SpringIntegrationStubMessages.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/integration/SpringIntegrationStubMessages.java index 5020cabc97..f6708bdf52 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/integration/SpringIntegrationStubMessages.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/integration/SpringIntegrationStubMessages.java @@ -49,13 +49,13 @@ public class SpringIntegrationStubMessages implements @Override public void send(T payload, Map headers, String destination) { - send(builder.create(payload, headers), destination); + send(this.builder.create(payload, headers), destination); } @Override public void send(Message message, String destination) { try { - MessageChannel messageChannel = context.getBean(destination, MessageChannel.class); + MessageChannel messageChannel = this.context.getBean(destination, MessageChannel.class); messageChannel.send(message); } catch (Exception e) { log.error("Exception occurred while trying to send a message [" + message + "] " + @@ -67,7 +67,7 @@ public class SpringIntegrationStubMessages implements @Override public Message receive(String destination, long timeout, TimeUnit timeUnit) { try { - PollableChannel messageChannel = context.getBean(destination, PollableChannel.class); + PollableChannel messageChannel = this.context.getBean(destination, PollableChannel.class); return messageChannel.receive(timeUnit.toMillis(timeout)); } catch (Exception e) { log.error("Exception occurred while trying to read a message from " + diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessage.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessage.java index 2467df933a..d04958e4e2 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessage.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessage.java @@ -43,7 +43,7 @@ public class ContractVerifierMessage { } public Object getPayload() { - return payload; + return this.payload; } public void setPayload(Object payload) { @@ -51,11 +51,11 @@ public class ContractVerifierMessage { } public Map getHeaders() { - return headers; + return this.headers; } public Object getHeader(String name) { - return headers.get(name); + return this.headers.get(name); } public void setHeaders(Map headers) { diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessaging.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessaging.java index 4efb8cc661..88af11aa7f 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessaging.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierMessaging.java @@ -33,11 +33,11 @@ public class ContractVerifierMessaging { } public void send(ContractVerifierMessage message, String destination) { - exchange.send(message.getPayload(), message.getHeaders(), destination); + this.exchange.send(message.getPayload(), message.getHeaders(), destination); } public ContractVerifierMessage receive(String destination) { - return convert(exchange.receive(destination)); + return convert(this.exchange.receive(destination)); } public ContractVerifierMessage create(T payload, Map headers) { diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierObjectMapper.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierObjectMapper.java index 064de4f28f..375d04ef56 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierObjectMapper.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/internal/ContractVerifierObjectMapper.java @@ -41,6 +41,6 @@ public class ContractVerifierObjectMapper { if (payload instanceof String) { return payload.toString(); } - return objectMapper.writeValueAsString(payload); + return this.objectMapper.writeValueAsString(payload); } } diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamStubMessages.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamStubMessages.java index 8d493b80ab..f6553cce67 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamStubMessages.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/stream/StreamStubMessages.java @@ -49,13 +49,13 @@ public class StreamStubMessages implements MessageVerifier> { @Override public void send(T payload, Map headers, String destination) { - send(builder.create(payload, headers), destination); + send(this.builder.create(payload, headers), destination); } @Override public void send(Message message, String destination) { try { - MessageChannel messageChannel = context + MessageChannel messageChannel = this.context .getBean(resolvedDestination(destination), MessageChannel.class); messageChannel.send(message); } @@ -69,9 +69,9 @@ public class StreamStubMessages implements MessageVerifier> { @Override public Message receive(String destination, long timeout, TimeUnit timeUnit) { try { - MessageChannel messageChannel = context + MessageChannel messageChannel = this.context .getBean(resolvedDestination(destination), MessageChannel.class); - return messageCollector.forChannel(messageChannel).poll(timeout, timeUnit); + return this.messageCollector.forChannel(messageChannel).poll(timeout, timeUnit); } catch (Exception e) { log.error("Exception occurred while trying to read a message from " @@ -81,7 +81,7 @@ public class StreamStubMessages implements MessageVerifier> { } private String resolvedDestination(String destination) { - ChannelBindingServiceProperties channelBindingServiceProperties = context + ChannelBindingServiceProperties channelBindingServiceProperties = this.context .getBean(ChannelBindingServiceProperties.class); for (Map.Entry entry : channelBindingServiceProperties .getBindings().entrySet()) { diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/util/ContractVerifierMessagingUtil.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/util/ContractVerifierMessagingUtil.java index 307e0457ac..df84ad4c4f 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/util/ContractVerifierMessagingUtil.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/util/ContractVerifierMessagingUtil.java @@ -43,72 +43,72 @@ public class ContractVerifierMessagingUtil { @Override public int size() { - return delegate.size(); + return this.delegate.size(); } @Override public boolean isEmpty() { - return delegate.isEmpty(); + return this.delegate.isEmpty(); } @Override public boolean containsKey(Object key) { - return delegate.containsKey(key); + return this.delegate.containsKey(key); } @Override public boolean containsValue(Object value) { - return delegate.containsValue(value); + return this.delegate.containsValue(value); } @Override public Object get(Object key) { - return delegate.get(key); + return this.delegate.get(key); } @Override public Object put(String key, Object value) { - return delegate.put(key, value); + return this.delegate.put(key, value); } @Override public Object remove(Object key) { - return delegate.remove(key); + return this.delegate.remove(key); } @Override public void putAll(Map m) { - delegate.putAll(m); + this.delegate.putAll(m); } @Override public void clear() { - delegate.clear(); + this.delegate.clear(); } @Override public Set keySet() { - return delegate.keySet(); + return this.delegate.keySet(); } @Override public Collection values() { - return delegate.values(); + return this.delegate.values(); } @Override public Set> entrySet() { - return delegate.entrySet(); + return this.delegate.entrySet(); } @Override public boolean equals(Object o) { - return delegate.equals(o); + return this.delegate.equals(o); } @Override public int hashCode() { - return delegate.hashCode(); + return this.delegate.hashCode(); } } } diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java index 9b5ee1a566..e78e3bb9bd 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java @@ -25,13 +25,11 @@ import java.lang.annotation.Target; import org.springframework.boot.test.autoconfigure.properties.PropertyMapping; import org.springframework.context.annotation.Import; -import com.github.tomakehurst.wiremock.core.Options; - /** * Annotation for test classes that want to start a WireMock server as part of the Spring * Application Context. The port, https port and stub locations (if any) can all be * controlled directly here. For more fine-grained control of the server instance add a - * bean of type {@link Options} to the application context. + * bean of type {@link com.github.tomakehurst.wiremock.core.Options} to the application context. * * @author Dave Syer * diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java index 2d1c3a3a05..9f30793c13 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java @@ -139,9 +139,9 @@ class SpringBootHttpServer private ContainerProperties container() { if (this.context != null) { - return context.getBean(ContainerProperties.class); + return this.context.getBean(ContainerProperties.class); } - return new ContainerProperties(options); + return new ContainerProperties(this.options); } @Override @@ -253,7 +253,7 @@ class WiremockServerConfiguration { WiremockServerConfiguration.this.adminRequestHandler); servletContext.setAttribute(StubRequestHandler.class.getName(), WiremockServerConfiguration.this.stubRequestHandler); - servletContext.setAttribute(Notifier.KEY, options.notifier()); + servletContext.setAttribute(Notifier.KEY, WiremockServerConfiguration.this.options.notifier()); } }; } @@ -278,13 +278,13 @@ class ContainerProperties { } public int port() { - if (options.httpsSettings().enabled()) { - return options.portNumber(); + if (this.options.httpsSettings().enabled()) { + return this.options.portNumber(); } if (this.localPort != null) { return this.localPort; } - EmbeddedWebApplicationContext embedded = (EmbeddedWebApplicationContext) context; + EmbeddedWebApplicationContext embedded = (EmbeddedWebApplicationContext) this.context; return embedded.getEmbeddedServletContainer().getPort(); } @@ -330,9 +330,9 @@ class ContainerConfiguration { @EventListener public void serverUp(EmbeddedServletContainerInitializedEvent event) { - if (connector != null) { - container.setLocalPort(connector.getLocalPort()); - container + if (this.connector != null) { + this.container.setLocalPort(this.connector.getLocalPort()); + this.container .setLocalHttpsPort(event.getEmbeddedServletContainer().getPort()); } } @@ -367,8 +367,8 @@ class ContainerConfiguration { undertow.addBuilderCustomizers(new UndertowBuilderCustomizer() { @Override public void customize(Builder builder) { - builder.addHttpListener(options.portNumber(), "localhost"); - UndertowContainerConfiguration.this.port = options.portNumber(); + builder.addHttpListener(UndertowContainerConfiguration.this.options.portNumber(), "localhost"); + UndertowContainerConfiguration.this.port = UndertowContainerConfiguration.this.options.portNumber(); } }); } @@ -377,10 +377,10 @@ class ContainerConfiguration { @EventListener public void serverUp(EmbeddedServletContainerInitializedEvent event) { - if (port != null) { + if (this.port != null) { // TODO: make it dynamic as well - container.setLocalPort(port); - container + this.container.setLocalPort(this.port); + this.container .setLocalHttpsPort(event.getEmbeddedServletContainer().getPort()); } } @@ -419,7 +419,7 @@ class ContainerConfiguration { Server server) { ServerConnector connector = new ServerConnector(server, -1, -1); connector.setHost("localhost"); - connector.setPort(options.portNumber()); + connector.setPort(this.options.portNumber()); for (ConnectionFactory connectionFactory : connector .getConnectionFactories()) { if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) { @@ -433,9 +433,9 @@ class ContainerConfiguration { @EventListener public void serverUp(EmbeddedServletContainerInitializedEvent event) { - if (connector != null) { - container.setLocalPort(connector.getLocalPort()); - container + if (this.connector != null) { + this.container.setLocalPort(this.connector.getLocalPort()); + this.container .setLocalHttpsPort(event.getEmbeddedServletContainer().getPort()); } } diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockConfiguration.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockConfiguration.java index 1e18ce7473..43d9cfb621 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockConfiguration.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockConfiguration.java @@ -71,29 +71,29 @@ public class WireMockConfiguration implements SmartLifecycle { @PostConstruct public void init() throws IOException { - if (options == null) { + if (this.options == null) { com.github.tomakehurst.wiremock.core.WireMockConfiguration factory = WireMockSpring .options(); - if (wireMock.getPort() != 8080) { - factory.port(wireMock.getPort()); + if (this.wireMock.getPort() != 8080) { + factory.port(this.wireMock.getPort()); } - if (wireMock.getHttpsPort() != -1) { - factory.httpsPort(wireMock.getHttpsPort()); + if (this.wireMock.getHttpsPort() != -1) { + factory.httpsPort(this.wireMock.getHttpsPort()); } this.options = factory; } - server = new WireMockServer(options); + this.server = new WireMockServer(this.options); registerStubs(); - if (!beanFactory.containsBean("wireMockServer")) { - beanFactory.registerSingleton("wireMockServer", server); + if (!this.beanFactory.containsBean("wireMockServer")) { + this.beanFactory.registerSingleton("wireMockServer", this.server); } } private void registerStubs() throws IOException { - if (StringUtils.hasText(wireMock.getStubs())) { + if (StringUtils.hasText(this.wireMock.getStubs())) { PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( - resourceLoader); - String pattern = wireMock.getStubs(); + this.resourceLoader); + String pattern = this.wireMock.getStubs(); if (!pattern.contains("*")) { if (!pattern.endsWith("/")) { pattern = pattern + "/"; @@ -101,7 +101,7 @@ public class WireMockConfiguration implements SmartLifecycle { pattern = pattern + "**/*.json"; } for (Resource resource : resolver.getResources(pattern)) { - server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString( + this.server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString( resource.getInputStream(), Charset.forName("UTF-8")))); } } @@ -109,22 +109,22 @@ public class WireMockConfiguration implements SmartLifecycle { @Override public void start() { - server.start(); - WireMock.configureFor("localhost", server.port()); - running = true; + this.server.start(); + WireMock.configureFor("localhost", this.server.port()); + this.running = true; } @Override public void stop() { - if (running) { - server.stop(); - running = false; + if (this.running) { + this.server.stop(); + this.running = false; } } @Override public boolean isRunning() { - return running; + return this.running; } @Override @@ -154,7 +154,7 @@ class WireMockProperties { private String stubs; public int getPort() { - return port; + return this.port; } public void setPort(int port) { @@ -162,7 +162,7 @@ class WireMockProperties { } public int getHttpsPort() { - return httpsPort; + return this.httpsPort; } public void setHttpsPort(int httpsPort) { @@ -170,7 +170,7 @@ class WireMockProperties { } public String getStubs() { - return stubs; + return this.stubs; } public void setStubs(String stubs) { diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java index 4b3d0f15d9..4539612890 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java @@ -16,9 +16,6 @@ package org.springframework.cloud.contract.wiremock; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; - import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; @@ -45,6 +42,9 @@ import com.github.tomakehurst.wiremock.matching.MultiValuePattern; import com.github.tomakehurst.wiremock.matching.RequestPattern; import com.github.tomakehurst.wiremock.stubbing.StubMapping; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; + /** * Convenience class for loading WireMock stubs into a {@link MockRestServiceServer}. In * this way using a {@link RestTemplate} can mock the responses from a server using @@ -136,7 +136,7 @@ public class WireMockRestServiceServer { * @return a MockRestServiceServer */ public MockRestServiceServer build() { - MockRestServiceServer server = builder.build(); + MockRestServiceServer server = this.builder.build(); for (String location : this.locations) { try { for (Resource resource : this.resolver.getResources(pattern(location))) { diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java index ab3f78e357..e23dc40879 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java @@ -24,7 +24,6 @@ import org.apache.http.ssl.SSLContexts; import org.junit.Assert; import org.springframework.util.ClassUtils; -import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; /** @@ -37,7 +36,7 @@ import com.github.tomakehurst.wiremock.core.WireMockConfiguration; * WireMockSpring.config()); * * - * and then use {@link WireMock} as normal in your test methods. + * and then use {@link com.github.tomakehurst.wiremock.client.WireMock} as normal in your test methods. * * @author Dave Syer * diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractRequestHandler.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractRequestHandler.java index 8a14e52c22..e2c88734f5 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractRequestHandler.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractRequestHandler.java @@ -67,20 +67,20 @@ public class ContractRequestHandler implements ResultHandler { Map configuration = getConfiguration(result); String actual = StreamUtils.copyToString(request.getInputStream(), Charset.forName("UTF-8")); - for (JsonPath jsonPath : jsonPaths.values()) { + for (JsonPath jsonPath : this.jsonPaths.values()) { new JsonPathValue(jsonPath, actual).assertHasValue(Object.class, "an object"); } - configuration.put("contract.jsonPaths", jsonPaths.keySet()); - if (contentType != null) { - configuration.put("contract.contentType", contentType); + configuration.put("contract.jsonPaths", this.jsonPaths.keySet()); + if (this.contentType != null) { + configuration.put("contract.contentType", this.contentType); String resultType = request.getContentType(); assertThat(resultType).isNotNull().as("no content type"); - assertThat(contentType.includes(MediaType.valueOf(resultType))).isTrue() + assertThat(this.contentType.includes(MediaType.valueOf(resultType))).isTrue() .as("content type did not match"); } - if (builder != null) { - builder.willReturn(getResponseDefinition(result)); - StubMapping stubMapping = builder.build(); + if (this.builder != null) { + this.builder.willReturn(getResponseDefinition(result)); + StubMapping stubMapping = this.builder.build(); MatchResult match = stubMapping.getRequest() .match(new WireMockHttpServletRequestAdapter(request)); assertThat(match.isExactMatch()).as("wiremock did not match request").isTrue(); @@ -137,7 +137,7 @@ public class ContractRequestHandler implements ResultHandler { (expression == null ? null : expression), "expression must not be null or empty"); expression = String.format(expression, args); - jsonPaths.put(expression, JsonPath.compile(expression)); + this.jsonPaths.put(expression, JsonPath.compile(expression)); } } diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java index 51dc7fc276..802d37e01e 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java @@ -16,7 +16,6 @@ package org.springframework.cloud.contract.wiremock.restdocs; -import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfigurationCustomizer; import org.springframework.context.annotation.Configuration; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer; @@ -24,7 +23,7 @@ import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer; /** * Custom configuration for Spring RestDocs that adds a WireMock snippet (for generating * JSON stubs). Applied automatically if you use - * {@link AutoConfigureRestDocs @AutoConfigureRestDocs} in your test case and this class + * {@link org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs @AutoConfigureRestDocs} in your test case and this class * is available. JSON stubs are generated and added to the restdocs path under "stubs". * * @see WireMockRestDocs for a convenient entry point for customizing and asserting the diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockSnippet.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockSnippet.java index 5f67473a00..f657ff4ff9 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockSnippet.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockSnippet.java @@ -16,16 +16,6 @@ package org.springframework.cloud.contract.wiremock.restdocs; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.delete; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.matching; -import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.put; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -50,6 +40,16 @@ import com.github.tomakehurst.wiremock.http.HttpHeaders; import com.github.tomakehurst.wiremock.matching.UrlPattern; import com.github.tomakehurst.wiremock.stubbing.StubMapping; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.delete; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; + public class WireMockSnippet implements Snippet { private String snippetName = "stubs"; @@ -66,10 +66,10 @@ public class WireMockSnippet implements Snippet { @Override public void document(Operation operation) throws IOException { extractMatchers(operation); - if (stubMapping == null) { - stubMapping = request(operation).willReturn(response(operation)).build(); + if (this.stubMapping == null) { + this.stubMapping = request(operation).willReturn(response(operation)).build(); } - String json = Json.write(stubMapping); + String json = Json.write(this.stubMapping); RestDocumentationContext context = (RestDocumentationContext) operation .getAttributes().get(RestDocumentationContext.class.getName()); File output = new File(context.getOutputDirectory(), @@ -81,15 +81,15 @@ public class WireMockSnippet implements Snippet { } private void extractMatchers(Operation operation) { - stubMapping = (StubMapping) operation.getAttributes().get("contract.stubMapping"); - if (stubMapping != null) { + this.stubMapping = (StubMapping) operation.getAttributes().get("contract.stubMapping"); + if (this.stubMapping != null) { return; } @SuppressWarnings("unchecked") Set jsonPaths = (Set) operation.getAttributes() .get("contract.jsonPaths"); this.jsonPaths = jsonPaths; - contentType = (MediaType) operation.getAttributes().get("contract.contentType"); + this.contentType = (MediaType) operation.getAttributes().get("contract.contentType"); } private ResponseDefinitionBuilder response(Operation operation) { @@ -107,7 +107,7 @@ public class WireMockSnippet implements Snippet { .getHeaders(); // TODO: whitelist headers for (String name : headers.keySet()) { - if (!headerBlackList.contains(name.toLowerCase())) { + if (!this.headerBlackList.contains(name.toLowerCase())) { if ("content-type".equalsIgnoreCase(name) && this.contentType != null) { continue; } @@ -138,8 +138,8 @@ public class WireMockSnippet implements Snippet { private RemoteMappingBuilder bodyPattern(RemoteMappingBuilder builder, String content) { - if (jsonPaths != null) { - for (String jsonPath : jsonPaths) { + if (this.jsonPaths != null) { + for (String jsonPath : this.jsonPaths) { builder.withRequestBody(matchingJsonPath(jsonPath)); } } @@ -158,7 +158,7 @@ public class WireMockSnippet implements Snippet { .getHeaders(); HttpHeaders result = new HttpHeaders(); for (String name : headers.keySet()) { - if (!headerBlackList.contains(name.toLowerCase())) { + if (!this.headerBlackList.contains(name.toLowerCase())) { result = result.plus(new HttpHeader(name, headers.get(name))); } } diff --git a/tests/pom.xml b/tests/pom.xml index 7c4215426c..b1729b56bb 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -22,6 +22,8 @@ samples-messaging-spring samples-messaging-stream samples-messaging-integration + spring-cloud-contract-stub-runner-boot-eureka + spring-cloud-contract-stub-runner-boot-zookeeper spring-cloud-contract-stub-runner-camel spring-cloud-contract-stub-runner-integration spring-cloud-contract-stub-runner-stream diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/pom.xml b/tests/spring-cloud-contract-stub-runner-boot-eureka/pom.xml new file mode 100644 index 0000000000..ee93dd2a69 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-contract-tests + 1.0.0.BUILD-SNAPSHOT + .. + + spring-cloud-contract-stub-runner-boot-eureka + jar + Spring Cloud Contract Stub Runner Boot Eureka + Spring Cloud Contract Stub Runner Boot Eureka + + + org.springframework.cloud + spring-cloud-contract-stub-runner + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner-jetty + test + + + org.springframework.cloud + spring-cloud-starter-eureka + true + + + org.springframework.cloud + spring-cloud-starter-eureka-server + test + + + junit + junit + test + + + org.codehaus.groovy + groovy + + + org.spockframework + spock-core + test + + + org.spockframework + spock-spring + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + test + + + info.solidsoft.spock + spock-global-unroll + test + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + + + + testCompile + + + + + + + diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/StubRunnerSpringCloudEurekaAutoConfigurationSpec.groovy b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/StubRunnerSpringCloudEurekaAutoConfigurationSpec.groovy new file mode 100644 index 0000000000..f6d082651b --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/eureka/StubRunnerSpringCloudEurekaAutoConfigurationSpec.groovy @@ -0,0 +1,135 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.stubrunner.spring.cloud.eureka + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.SpringApplication +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.context.SpringBootContextLoader +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.cloud.client.loadbalancer.LoadBalanced +import org.springframework.cloud.contract.stubrunner.StubFinder +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner +import org.springframework.cloud.netflix.eureka.EnableEurekaClient +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer +import org.springframework.context.ConfigurableApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.http.HttpMethod +import org.springframework.http.client.ClientHttpResponse +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.client.* +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification +import spock.util.concurrent.PollingConditions + +/** + * @author Marcin Grzejszczak + */ +//TODO: Speed up this test somehow +@ContextConfiguration(classes = Config, loader = SpringBootContextLoader) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = ["stubrunner.cloud.eureka.enabled=true", + "stubrunner.cloud.stubbed.discovery.enabled=false", + "stubrunner.cloud.ribbon.enabled=false", + "eureka.client.enabled=true", + "eureka.instance.leaseRenewalIntervalInSeconds=1", + "ribbon.ServerListRefreshInterval=100"]) +@AutoConfigureStubRunner( ids = + ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer", + "org.springframework.cloud.contract.verifier.stubs:bootService"], + repositoryRoot = "classpath:m2repo/repository/") +@DirtiesContext +class StubRunnerSpringCloudEurekaAutoConfigurationSpec extends Specification { + + @Autowired StubFinder stubFinder + @Autowired @LoadBalanced RestTemplate restTemplate + @Shared @AutoCleanup ConfigurableApplicationContext eurekaServer + + void setupSpec() { + System.clearProperty("stubrunner.stubs.repository.root") + System.clearProperty("stubrunner.stubs.classifier") + eurekaServer = SpringApplication.run(EurekaServer, + "--stubrunner.cloud.eureka.enabled=true", + "--stubrunner.cloud.stubbed.discovery.enabled=false", + "--eureka.client.enabled=true", + "--server.port=8761", + "--spring.profiles.active=eureka") + } + + void cleanupSpec() { + System.clearProperty("stubrunner.stubs.repository.root") + System.clearProperty("stubrunner.stubs.classifier") + } + + PollingConditions conditions = new PollingConditions(timeout: 40, delay: 1) + + def 'should make service discovery work'() { + expect: 'WireMocks are running' + "${stubFinder.findStubUrl('loanIssuance').toString()}/name".toURL().text == 'loanIssuance' + "${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name".toURL().text == 'fraudDetectionServer' + and: 'Stubs can be reached via load service discovery' + conditions.eventually { + assert restTemplate.getForObject('http://loanIssuance/name', String) == 'loanIssuance' + } + restTemplate.getForObject('http://someNameThatShouldMapFraudDetectionServer/name', String) == 'fraudDetectionServer' + } + + @Configuration + @EnableAutoConfiguration + @EnableEurekaClient + static class Config { + + @Bean + @LoadBalanced + RestTemplate restTemplate() { + def template = new RestTemplate() { + + @Override + protected T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException { + try { + return super.doExecute(url, method, requestCallback, responseExtractor) + } catch (Exception e) { + throw new AssertionError(e) + } + } + } + template.errorHandler = new DefaultResponseErrorHandler() { + @Override + void handleError(ClientHttpResponse response) throws IOException { + try { + super.handleError(response) + } catch (Exception e) { + throw new AssertionError(e) + } + } + } + return template + } + + } + + @Configuration + @EnableAutoConfiguration + @EnableEurekaServer + static class EurekaServer { + + } +} diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/application.yml b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/application.yml new file mode 100644 index 0000000000..bfd49917db --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/application.yml @@ -0,0 +1,4 @@ +stubrunner: + camel.enabled: false + idsToServiceIds: + fraudDetectionServer: someNameThatShouldMapFraudDetectionServer diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/logback.xml b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/logback.xml new file mode 100644 index 0000000000..df6a2daa72 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/logback.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT-stubs.jar new file mode 100644 index 0000000000..c57c836db4 Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT-stubs.jar differ diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT.pom new file mode 100644 index 0000000000..73d2c00a31 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT.pom @@ -0,0 +1,25 @@ + + + + + 4.0.0 + org.springframework.cloud.contract.verifier.stubs + bootService + 0.0.1-SNAPSHOT + pom + diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/maven-metadata.xml new file mode 100644 index 0000000000..13a1e7975f --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/maven-metadata.xml @@ -0,0 +1,28 @@ + + + + + org.springframework.cloud.contract.verifier.stubs + bootService + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + + 20160409062112 + + diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT-stubs.jar new file mode 100644 index 0000000000..fdb70e383f Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT-stubs.jar differ diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT.pom new file mode 100644 index 0000000000..40610c8cdb --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT.pom @@ -0,0 +1,25 @@ + + + + + 4.0.0 + org.springframework.cloud.contract.verifier.stubs + fraudDetectionServer + 0.0.1-SNAPSHOT + pom + diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/maven-metadata.xml new file mode 100644 index 0000000000..281b9b3b80 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/maven-metadata.xml @@ -0,0 +1,28 @@ + + + + + org.springframework.cloud.contract.verifier.stubs + fraudDetectionServer + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + + 20160409062112 + + diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT-stubs.jar new file mode 100644 index 0000000000..e322590636 Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT-stubs.jar differ diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT.pom new file mode 100644 index 0000000000..59db343686 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT.pom @@ -0,0 +1,25 @@ + + + + + 4.0.0 + org.springframework.cloud.contract.verifier.stubs + loanIssuance + 0.0.1-SNAPSHOT + pom + diff --git a/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/maven-metadata.xml new file mode 100644 index 0000000000..615428dae6 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-eureka/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/maven-metadata.xml @@ -0,0 +1,28 @@ + + + + + org.springframework.cloud.contract.verifier.stubs + loanIssuance + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + + 20160409062111 + + diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/pom.xml b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/pom.xml new file mode 100644 index 0000000000..7f2c5fd4ce --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-contract-tests + 1.0.0.BUILD-SNAPSHOT + .. + + spring-cloud-contract-stub-runner-boot-zookeeper + jar + Spring Cloud Contract Stub Runner Boot Zookeeper + Spring Cloud Contract Stub Runner Boot Zookeeper + + + org.springframework.cloud + spring-cloud-contract-stub-runner + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner-jetty + test + + + org.springframework.cloud + spring-cloud-starter-zookeeper-discovery + true + + + junit + junit + test + + + org.codehaus.groovy + groovy + + + org.spockframework + spock-core + test + + + org.spockframework + spock-spring + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + test + + + info.solidsoft.spock + spock-global-unroll + test + + + org.apache.curator + curator-test + test + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + + + + testCompile + + + + + + + diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/StubRunnerSpringCloudZookeeperAutoConfigurationSpec.groovy similarity index 73% rename from spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy rename to tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/StubRunnerSpringCloudZookeeperAutoConfigurationSpec.groovy index 702364cc57..681011e301 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/zookeeper/StubRunnerSpringCloudZookeeperAutoConfigurationSpec.groovy @@ -14,8 +14,9 @@ * limitations under the License. */ -package org.springframework.cloud.contract.stubrunner.spring.cloud +package org.springframework.cloud.contract.stubrunner.spring.cloud.zookeeper +import org.apache.curator.test.TestingServer import org.junit.AfterClass import org.junit.BeforeClass import org.springframework.beans.factory.annotation.Autowired @@ -26,31 +27,35 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient import org.springframework.cloud.client.loadbalancer.LoadBalanced import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner -import org.springframework.cloud.zookeeper.discovery.RibbonZookeeperAutoConfiguration +import org.springframework.cloud.zookeeper.ZookeeperProperties +import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration +import org.springframework.util.SocketUtils import org.springframework.web.client.RestTemplate import spock.lang.Specification + /** * @author Marcin Grzejszczak */ @ContextConfiguration(classes = Config, loader = SpringBootContextLoader) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = ["stubrunner.camel.enabled=false", - "spring.cloud.zookeeper.enabled=false", - "spring.cloud.zookeeper.discovery.enabled=false"]) + "stubrunner.cloud.stubbed.discovery.enabled=false", + "debug=true"]) @AutoConfigureStubRunner( ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer", "org.springframework.cloud.contract.verifier.stubs:bootService"], repositoryRoot = "classpath:m2repo/repository/") @DirtiesContext -class StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec extends Specification { +class StubRunnerSpringCloudZookeeperAutoConfigurationSpec extends Specification { @Autowired StubFinder stubFinder @Autowired @LoadBalanced RestTemplate restTemplate + @Autowired ZookeeperServiceDiscovery zookeeperServiceDiscovery @BeforeClass @AfterClass @@ -68,11 +73,31 @@ class StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec extends Specifi restTemplate.getForObject('http://someNameThatShouldMapFraudDetectionServer/name', String) == 'fraudDetectionServer' } + def 'should have all apps registered in Service Discovery'() { + expect: + !zookeeperServiceDiscovery.getServiceDiscovery().queryForInstances('loanIssuance').empty + !zookeeperServiceDiscovery.getServiceDiscovery().queryForInstances('someNameThatShouldMapFraudDetectionServer').empty + } + + def cleanup() { + zookeeperServiceDiscovery?.serviceDiscovery?.close() + } + @Configuration - @EnableAutoConfiguration(exclude = [RibbonZookeeperAutoConfiguration]) + @EnableAutoConfiguration @EnableDiscoveryClient static class Config { + @Bean + TestingServer testingServer() { + return new TestingServer(SocketUtils.findAvailableTcpPort()) + } + + @Bean + ZookeeperProperties zookeeperProperties() { + return new ZookeeperProperties(connectString: testingServer().connectString) + } + @Bean @LoadBalanced RestTemplate restTemplate() { diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/application.yml b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/application.yml new file mode 100644 index 0000000000..bfd49917db --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/application.yml @@ -0,0 +1,4 @@ +stubrunner: + camel.enabled: false + idsToServiceIds: + fraudDetectionServer: someNameThatShouldMapFraudDetectionServer diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/logback.xml b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/logback.xml new file mode 100644 index 0000000000..df6a2daa72 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/logback.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT-stubs.jar new file mode 100644 index 0000000000..c57c836db4 Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT-stubs.jar differ diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT.pom new file mode 100644 index 0000000000..73d2c00a31 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/0.0.1-SNAPSHOT/bootService-0.0.1-SNAPSHOT.pom @@ -0,0 +1,25 @@ + + + + + 4.0.0 + org.springframework.cloud.contract.verifier.stubs + bootService + 0.0.1-SNAPSHOT + pom + diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/maven-metadata.xml new file mode 100644 index 0000000000..13a1e7975f --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/bootService/maven-metadata.xml @@ -0,0 +1,28 @@ + + + + + org.springframework.cloud.contract.verifier.stubs + bootService + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + + 20160409062112 + + diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT-stubs.jar new file mode 100644 index 0000000000..fdb70e383f Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT-stubs.jar differ diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT.pom new file mode 100644 index 0000000000..40610c8cdb --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/0.0.1-SNAPSHOT/fraudDetectionServer-0.0.1-SNAPSHOT.pom @@ -0,0 +1,25 @@ + + + + + 4.0.0 + org.springframework.cloud.contract.verifier.stubs + fraudDetectionServer + 0.0.1-SNAPSHOT + pom + diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/maven-metadata.xml new file mode 100644 index 0000000000..281b9b3b80 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/fraudDetectionServer/maven-metadata.xml @@ -0,0 +1,28 @@ + + + + + org.springframework.cloud.contract.verifier.stubs + fraudDetectionServer + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + + 20160409062112 + + diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT-stubs.jar new file mode 100644 index 0000000000..e322590636 Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT-stubs.jar differ diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT.pom new file mode 100644 index 0000000000..59db343686 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/0.0.1-SNAPSHOT/loanIssuance-0.0.1-SNAPSHOT.pom @@ -0,0 +1,25 @@ + + + + + 4.0.0 + org.springframework.cloud.contract.verifier.stubs + loanIssuance + 0.0.1-SNAPSHOT + pom + diff --git a/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/maven-metadata.xml new file mode 100644 index 0000000000..615428dae6 --- /dev/null +++ b/tests/spring-cloud-contract-stub-runner-boot-zookeeper/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/loanIssuance/maven-metadata.xml @@ -0,0 +1,28 @@ + + + + + org.springframework.cloud.contract.verifier.stubs + loanIssuance + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + + 20160409062111 + +