* 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.
- *
+ *
* 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 @@
junitjunit
+
+ com.sun.jersey
+ jersey-client
+ true
+ cglibcglib
@@ -128,13 +133,23 @@
org.springframework.cloudspring-cloud-starter-zookeeper-discovery
- test
+ trueorg.apache.curatorcurator-testtest
+
+ 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 extends String, ?> 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