diff --git a/docs/src/main/asciidoc/migrations.adoc b/docs/src/main/asciidoc/migrations.adoc
index a93194bee9..a4ef065a02 100644
--- a/docs/src/main/asciidoc/migrations.adoc
+++ b/docs/src/main/asciidoc/migrations.adoc
@@ -177,9 +177,4 @@ version of the release train (and vice versa).
Done via https://github.com/spring-cloud/spring-cloud-contract/issues/267[issue 267]
[[cloud-verifier-1.2-2.0]]
-=== 1.2.x -> 2.0.x
-
-==== No Camel support
-
-We will add back Apache Camel support only after this https://issues.apache.org/jira/browse/CAMEL-11430[issue]
-gets fixed
\ No newline at end of file
+=== 1.2.x -> 2.0.x
\ No newline at end of file
diff --git a/docs/src/main/asciidoc/verifier_stubrunner_msg.adoc b/docs/src/main/asciidoc/verifier_stubrunner_msg.adoc
index 725c4e8db9..1a5a68a96f 100644
--- a/docs/src/main/asciidoc/verifier_stubrunner_msg.adoc
+++ b/docs/src/main/asciidoc/verifier_stubrunner_msg.adoc
@@ -6,6 +6,7 @@ frameworks:
* Spring Integration
* Spring Cloud Stream
+* Apache Camel
* Spring AMQP
It also provides entry points to integrate with any other solution on the market.
@@ -65,6 +66,8 @@ include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/o
include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=trigger_all,indent=0]
----
+include::{tests_path}/spring-cloud-contract-stub-runner-camel/README.adoc[]
+
include::{tests_path}/spring-cloud-contract-stub-runner-integration/README.adoc[]
include::{tests_path}/spring-cloud-contract-stub-runner-stream/README.adoc[]
diff --git a/pom.xml b/pom.xml
index 2f524287f6..b129177de3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,9 @@
2016
+ 5.12.1
+ 2.22.1
+ 2.17
3.5.13
0.0.9
2.1.0.BUILD-SNAPSHOT
@@ -71,6 +74,51 @@
pom
import
+
+ org.apache.camel
+ camel-spring-boot-starter
+ ${camel.version}
+
+
+ org.apache.camel
+ camel-spring
+ ${camel.version}
+
+
+ org.apache.camel
+ camel-spring-boot
+ ${camel.version}
+
+
+ org.apache.camel
+ camel-core
+ ${camel.version}
+
+
+ org.apache.camel
+ camel-kafka
+ ${camel.version}
+
+
+ org.apache.camel
+ camel-jackson
+ ${camel.version}
+
+
+ org.apache.camel
+ camel-jms
+ ${camel.version}
+
+
+ org.apache.activemq
+ activemq-camel
+ ${activemq.version}
+
+
+ org.apache.activemq
+ activemq-pool
+ ${activemq.version}
+
net.sf.jopt-simple
jopt-simple
diff --git a/spring-cloud-contract-stub-runner/pom.xml b/spring-cloud-contract-stub-runner/pom.xml
index 6bf2b2fcdc..8c578900a6 100644
--- a/spring-cloud-contract-stub-runner/pom.xml
+++ b/spring-cloud-contract-stub-runner/pom.xml
@@ -60,6 +60,21 @@
jopt-simple
true
+
+ org.apache.camel
+ camel-spring-boot-starter
+ true
+
+
+ org.apache.camel
+ camel-spring-boot
+ true
+
+
+ org.apache.camel
+ camel-jackson
+ true
+
junit
junit
diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelConfiguration.java
new file mode 100644
index 0000000000..f5488d4eeb
--- /dev/null
+++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelConfiguration.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013-2017 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.messaging.camel;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.spring.SpringRouteBuilder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.contract.spec.Contract;
+import org.springframework.cloud.contract.stubrunner.BatchStubRunner;
+import org.springframework.cloud.contract.stubrunner.StubConfiguration;
+import org.springframework.context.annotation.*;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Camel configuration that iterates over the downloaded Groovy DSLs and registers a route
+ * for each DSL.
+ *
+ * @author Marcin Grzejszczak
+ */
+@Configuration
+@ConditionalOnClass(RoutesBuilder.class)
+@ConditionalOnProperty(name = "stubrunner.camel.enabled", havingValue = "true", matchIfMissing = true)
+public class StubRunnerCamelConfiguration {
+
+ @Bean
+ public RoutesBuilder myRouter(final BatchStubRunner batchStubRunner) {
+ return new SpringRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ Map> contracts = batchStubRunner
+ .getContracts();
+ for (Collection list : contracts.values()) {
+ for (Contract it : list) {
+ if (it.getInput() != null
+ && it.getInput().getMessageFrom() != null
+ && it.getOutputMessage() != null
+ && it.getOutputMessage().getSentTo() != null) {
+ from(it.getInput().getMessageFrom().getClientValue())
+ .filter(new StubRunnerCamelPredicate(it))
+ .process(new StubRunnerCamelProcessor(it))
+ .to(it.getOutputMessage().getSentTo()
+ .getClientValue());
+ }
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelPredicate.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelPredicate.java
new file mode 100644
index 0000000000..f62a75e4ae
--- /dev/null
+++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelPredicate.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2013-2017 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.messaging.camel;
+
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Predicate;
+import org.springframework.cloud.contract.spec.Contract;
+import org.springframework.cloud.contract.spec.internal.BodyMatcher;
+import org.springframework.cloud.contract.spec.internal.BodyMatchers;
+import org.springframework.cloud.contract.spec.internal.Header;
+import org.springframework.cloud.contract.verifier.util.MapConverter;
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper;
+import org.springframework.cloud.contract.verifier.util.JsonPaths;
+import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter;
+import org.springframework.cloud.contract.verifier.util.MethodBufferingJsonVerifiable;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import com.toomuchcoding.jsonassert.JsonAssertion;
+
+/**
+ * Passes through a message that matches the one defined in the DSL
+ *
+ * @author Marcin Grzejszczak
+ */
+class StubRunnerCamelPredicate implements Predicate {
+
+ private final Contract groovyDsl;
+ private final ContractVerifierObjectMapper objectMapper = new ContractVerifierObjectMapper();
+
+ public StubRunnerCamelPredicate(Contract groovyDsl) {
+ this.groovyDsl = groovyDsl;
+ }
+
+ @Override
+ public boolean matches(Exchange exchange) {
+ if (!headersMatch(exchange.getIn().getHeaders())) {
+ return false;
+ }
+ Object inputMessage = exchange.getIn().getBody();
+ BodyMatchers matchers = this.groovyDsl.getInput().getBodyMatchers();
+ Object dslBody = MapConverter.getStubSideValues(this.groovyDsl.getInput().getMessageBody());
+
+ DocumentContext parsedJson = deserialize(inputMessage);
+ return matchMessage(matchers, dslBody, parsedJson);
+ }
+
+ private boolean matchMessage(BodyMatchers matchers, Object dslBody, DocumentContext parsedJson) {
+ boolean matches = true;
+ JsonPaths jsonPaths = getJsonPaths(matchers, dslBody);
+ for (MethodBufferingJsonVerifiable path : jsonPaths) {
+ matches &= matchesJsonPath(parsedJson, path.jsonPath());
+ }
+ if (matchers != null && matchers.hasMatchers()) {
+ for (BodyMatcher matcher : matchers.jsonPathMatchers()) {
+ String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher, dslBody);
+ matches &= matchesJsonPath(parsedJson, jsonPath);
+ }
+ }
+ return matches;
+ }
+
+ private JsonPaths getJsonPaths(BodyMatchers matchers, Object dslBody) {
+ Object matchingInputMessage = JsonToJsonPathsConverter
+ .removeMatchingJsonPaths(dslBody, matchers);
+ return JsonToJsonPathsConverter
+ .transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(
+ matchingInputMessage);
+ }
+
+ private DocumentContext deserialize(Object inputMessage) {
+ DocumentContext parsedJson;
+ try {
+ parsedJson = JsonPath
+ .parse(this.objectMapper.writeValueAsString(inputMessage));
+ }
+ catch (JsonProcessingException e) {
+ throw new IllegalStateException("Cannot serialize to JSON", e);
+ }
+ return parsedJson;
+ }
+
+ private boolean matchesJsonPath(DocumentContext parsedJson, String jsonPath) {
+ try {
+ JsonAssertion.assertThat(parsedJson).matchesJsonPath(jsonPath);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private boolean headersMatch(Map headers) {
+ boolean matches = true;
+ for (Header it : this.groovyDsl.getInput().getMessageHeaders().getEntries()) {
+ String name = it.getName();
+ Object value = it.getClientValue();
+ Object valueInHeader = headers.get(name);
+ matches &= matchValue(value, valueInHeader);
+ }
+ return matches;
+ }
+
+ private boolean matchValue(Object value, Object valueInHeader) {
+ return value instanceof Pattern ?
+ ((Pattern) value).matcher(valueInHeader.toString()).matches() :
+ valueInHeader!=null && valueInHeader.equals(value);
+ }
+}
diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelProcessor.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelProcessor.java
new file mode 100644
index 0000000000..e733c5a817
--- /dev/null
+++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelProcessor.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013-2017 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.messaging.camel;
+
+import org.springframework.cloud.contract.verifier.util.BodyExtractor;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.springframework.cloud.contract.spec.Contract;
+import org.springframework.cloud.contract.spec.internal.Header;
+
+/**
+ * Sends forward a message defined in the DSL. Also removes headers from the input message
+ * and provides the headers from the DSL.
+ *
+ * @author Marcin Grzejszczak
+ */
+class StubRunnerCamelProcessor implements Processor {
+
+ private final Contract groovyDsl;
+
+ StubRunnerCamelProcessor(Contract groovyDsl) {
+ this.groovyDsl = groovyDsl;
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ Message input = exchange.getIn();
+ if (this.groovyDsl.getInput().getMessageHeaders() != null) {
+ for (Header entry : this.groovyDsl.getInput().getMessageHeaders().getEntries()) {
+ input.removeHeader(entry.getName());
+ }
+ }
+ if (this.groovyDsl.getOutputMessage() == null) {
+ return;
+ }
+ input.setBody(BodyExtractor
+ .extractStubValueFrom(this.groovyDsl.getOutputMessage().getBody()));
+ if (this.groovyDsl.getOutputMessage().getHeaders() != null) {
+ for (Header entry : this.groovyDsl.getOutputMessage().getHeaders().getEntries()) {
+ input.setHeader(entry.getName(), entry.getClientValue());
+ }
+ }
+ }
+}
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 0f3c598395..f8e3bc096f 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
@@ -8,7 +8,8 @@ org.springframework.cloud.contract.stubrunner.messaging.stream.StubRunnerStreamC
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,\
-org.springframework.cloud.contract.stubrunner.messaging.StubRunnerStreamsIntegrationAutoConfiguration
+org.springframework.cloud.contract.stubrunner.messaging.StubRunnerStreamsIntegrationAutoConfiguration,\
+org.springframework.cloud.contract.stubrunner.messaging.camel.StubRunnerCamelConfiguration
# Test Execution Listeners
org.springframework.test.context.TestExecutionListener=\
diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelPredicateSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelPredicateSpec.groovy
new file mode 100644
index 0000000000..ba71c68044
--- /dev/null
+++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelPredicateSpec.groovy
@@ -0,0 +1,137 @@
+package org.springframework.cloud.contract.stubrunner.messaging.camel
+
+import org.apache.camel.Exchange
+import org.apache.camel.Message
+import org.springframework.cloud.contract.spec.Contract
+import spock.lang.Specification
+
+/**
+ * @author Marcin Grzejszczak
+ */
+class StubRunnerCamelPredicateSpec extends Specification {
+ Exchange exchange = Stub(Exchange)
+ Message message = Stub(Message)
+
+ def "should return false if headers don't match"() {
+ given:
+ Contract dsl = Contract.make {
+ input {
+ messageFrom "foo"
+ messageBody(foo: "bar")
+ messageHeaders {
+ header("foo", $(c(regex("[0-9]{3}")), p(123)))
+ }
+ }
+ }
+ and:
+ StubRunnerCamelPredicate predicate = new StubRunnerCamelPredicate(dsl)
+ exchange.in >> message
+ message.headers >> [
+ foo: "non matching stuff"
+ ]
+ expect:
+ !predicate.matches(exchange)
+ }
+
+ def "should return false if headers match and body doesn't"() {
+ given:
+ Contract dsl = Contract.make {
+ input {
+ messageFrom "foo"
+ messageHeaders {
+ header("foo", 123)
+ }
+ messageBody(foo: $(c(regex("[0-9]{3}")), p(123)))
+ }
+ }
+ and:
+ StubRunnerCamelPredicate predicate = new StubRunnerCamelPredicate(dsl)
+ exchange.in >> message
+ message.headers >> [
+ foo: 123
+ ]
+ message.body >> [
+ foo: "non matching stuff"
+ ]
+ expect:
+ !predicate.matches(exchange)
+ }
+
+ def "should return false if headers match and body doesn't when it's using matchers"() {
+ given:
+ Contract dsl = Contract.make {
+ input {
+ messageFrom "foo"
+ messageHeaders {
+ header("foo", 123)
+ }
+ messageBody(foo: "non matching stuff")
+ stubMatchers {
+ jsonPath('$.foo', byRegex("[0-9]{3}"))
+ }
+ }
+ }
+ and:
+ StubRunnerCamelPredicate predicate = new StubRunnerCamelPredicate(dsl)
+ exchange.in >> message
+ message.headers >> [
+ foo: 123
+ ]
+ message.body >> [
+ foo: "non matching stuff"
+ ]
+ expect:
+ !predicate.matches(exchange)
+ }
+ def "should return true if headers and body match"() {
+ given:
+ Contract dsl = Contract.make {
+ input {
+ messageFrom "foo"
+ messageHeaders {
+ header("foo", 123)
+ }
+ messageBody(foo: $(c(regex("[0-9]{3}")), p(123)))
+
+ }
+ }
+ and:
+ StubRunnerCamelPredicate predicate = new StubRunnerCamelPredicate(dsl)
+ exchange.in >> message
+ message.headers >> [
+ foo: 123
+ ]
+ message.body >> [
+ foo: 123
+ ]
+ expect:
+ predicate.matches(exchange)
+
+ }
+ def "should return true if headers and body using matchers match"() {
+ given:
+ Contract dsl = Contract.make {
+ input {
+ messageFrom "foo"
+ messageHeaders {
+ header("foo", 123)
+ }
+ messageBody(foo: 123)
+ stubMatchers {
+ jsonPath('$.foo', byRegex("[0-9]{3}"))
+ }
+ }
+ }
+ and:
+ StubRunnerCamelPredicate predicate = new StubRunnerCamelPredicate(dsl)
+ exchange.in >> message
+ message.headers >> [
+ foo: 123
+ ]
+ message.body >> [
+ foo: 123
+ ]
+ expect:
+ predicate.matches(exchange)
+ }
+}
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
index 538edfe53d..9cc35ccab1 100644
--- 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
@@ -43,6 +43,7 @@ public class StubRunnerBootConsulExample {
-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
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
index a8dcc118f3..7973900003 100644
--- 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
@@ -56,6 +56,7 @@ public class StubRunnerBootEurekaExample {
-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
index 984722d66c..8dea7638dc 100644
--- 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
@@ -42,6 +42,7 @@ public class StubRunnerBootZookeeperExample {
-Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer
-Dstubrunner.cloud.stubbed.discovery.enabled=false
-Dstubrunner.cloud.zookeepr.enabled=true
+-Dstubrunner.camel.enabled=false
-Dstubrunner.repositoryRoot=classpath:m2repo/repository/
-Deureka.client.enabled=false
-Ddebug=true
diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml
index 2773b5f414..d41c4d169f 100644
--- a/spring-cloud-contract-verifier/pom.xml
+++ b/spring-cloud-contract-verifier/pom.xml
@@ -30,6 +30,26 @@
spring-messaging
true
+
+ org.apache.camel
+ camel-spring-boot-starter
+ true
+
+
+ org.apache.camel
+ camel-spring
+ true
+
+
+ org.apache.camel
+ camel-core
+ true
+
+
+ org.apache.camel
+ camel-kafka
+ true
+
org.springframework.cloud
spring-cloud-stream-test-support
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
new file mode 100644
index 0000000000..502c81c1ef
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/CamelStubMessages.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2013-2017 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.verifier.messaging.camel;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.impl.DefaultExchange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+@Component
+public class CamelStubMessages implements MessageVerifier {
+
+ private static final Logger log = LoggerFactory.getLogger(
+ CamelStubMessages.class);
+
+ private final CamelContext context;
+ private final ContractVerifierCamelMessageBuilder builder;
+
+ @Autowired
+ public CamelStubMessages(CamelContext context) {
+ this.context = context;
+ this.builder = new ContractVerifierCamelMessageBuilder(context);
+ }
+
+ @Override
+ public void send(Message message, String destination) {
+ try {
+ ProducerTemplate producerTemplate = this.context.createProducerTemplate();
+ Exchange exchange = new DefaultExchange(this.context);
+ exchange.setIn(message);
+ producerTemplate.send(destination, exchange);
+ } catch (Exception e) {
+ log.error("Exception occurred while trying to send a message [" + message + "] " +
+ "to a channel with name [" + destination + "]", e);
+ throw e;
+ }
+ }
+
+ @Override
+ public void send(T payload, Map headers, String destination) {
+ send(this.builder.create(payload, headers), destination);
+ }
+
+ @Override
+ public Message receive(String destination, long timeout, TimeUnit timeUnit) {
+ try {
+ ConsumerTemplate consumerTemplate = this.context.createConsumerTemplate();
+ Exchange exchange = consumerTemplate.receive(destination, timeUnit.toMillis(timeout));
+ return exchange.getIn();
+ } catch (Exception e) {
+ log.error("Exception occurred while trying to read a message from " +
+ " a channel with name [" + destination + "]", e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public Message receive(String destination) {
+ return receive(destination, 5, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/ContractVerifierCamelConfiguration.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/ContractVerifierCamelConfiguration.java
new file mode 100644
index 0000000000..33da68db09
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/ContractVerifierCamelConfiguration.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013-2017 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.verifier.messaging.camel;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Message;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.*;
+import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage;
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging;
+import org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration;
+import org.springframework.context.annotation.*;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+@Configuration
+@ConditionalOnClass(Message.class)
+@Import(CamelAutoConfiguration.class)
+@ConditionalOnProperty(name="stubrunner.camel.enabled", havingValue="true", matchIfMissing = true)
+@AutoConfigureBefore(NoOpContractVerifierAutoConfiguration.class)
+public class ContractVerifierCamelConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ MessageVerifier contractVerifierMessageExchange(
+ CamelContext camelContext) {
+ return new CamelStubMessages(camelContext);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ContractVerifierMessaging contractVerifierMessaging(
+ MessageVerifier exchange) {
+ return new ContractVerifierCamelHelper(exchange);
+ }
+}
+
+class ContractVerifierCamelHelper extends ContractVerifierMessaging {
+
+ public ContractVerifierCamelHelper(
+ MessageVerifier exchange) {
+ super(exchange);
+ }
+
+ @Override
+ protected ContractVerifierMessage convert(Message receive) {
+ return new ContractVerifierMessage(receive.getBody(), receive.getHeaders());
+ }
+}
diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/ContractVerifierCamelMessageBuilder.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/ContractVerifierCamelMessageBuilder.java
new file mode 100644
index 0000000000..bd17e1991a
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/camel/ContractVerifierCamelMessageBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013-2017 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.verifier.messaging.camel;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Message;
+import org.apache.camel.impl.DefaultMessage;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+class ContractVerifierCamelMessageBuilder {
+
+ private final CamelContext context;
+
+ ContractVerifierCamelMessageBuilder(CamelContext context) {
+ this.context = context;
+ }
+
+ public Message create(T payload, Map headers) {
+ DefaultMessage message = new DefaultMessage(this.context);
+ message.setBody(payload);
+ message.setHeaders(headers);
+ return message;
+ }
+
+}
diff --git a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
index c7cfc35629..0e6be1c75d 100644
--- a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
@@ -4,4 +4,5 @@ org.springframework.cloud.contract.verifier.messaging.stream.ContractVerifierStr
org.springframework.cloud.contract.verifier.messaging.integration.ContractVerifierIntegrationConfiguration,\
org.springframework.cloud.contract.verifier.messaging.amqp.ContractVerifierAmqpAutoConfiguration,\
org.springframework.cloud.contract.verifier.messaging.amqp.RabbitMockConnectionFactoryAutoConfiguration,\
+org.springframework.cloud.contract.verifier.messaging.camel.ContractVerifierCamelConfiguration,\
org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration
\ No newline at end of file
diff --git a/tests/pom.xml b/tests/pom.xml
index 3679607d51..ef343e744c 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -18,6 +18,7 @@
Spring Cloud Contract Tests
+ samples-messaging-camel
samples-messaging-stream
samples-messaging-integration
samples-messaging-amqp
diff --git a/tests/samples-messaging-camel/.springBeans b/tests/samples-messaging-camel/.springBeans
new file mode 100644
index 0000000000..b74cfc29b8
--- /dev/null
+++ b/tests/samples-messaging-camel/.springBeans
@@ -0,0 +1,16 @@
+
+
+ 1
+
+
+
+
+
+
+ java:com.example.fraud.CamelMessagingApplication
+
+
+
+
+
+
diff --git a/tests/samples-messaging-camel/pom.xml b/tests/samples-messaging-camel/pom.xml
new file mode 100644
index 0000000000..9b279df007
--- /dev/null
+++ b/tests/samples-messaging-camel/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-contract-tests
+ 2.1.0.BUILD-SNAPSHOT
+ ..
+
+ spring-cloud-contract-sample-camel
+ jar
+ Spring Cloud Contract Sample Camel
+ Spring Cloud Contract Sample Camel
+
+
+ org.apache.camel
+ camel-spring-boot-starter
+
+
+ org.apache.camel
+ camel-jms
+
+
+ org.apache.activemq
+ activemq-camel
+
+
+ org.apache.activemq
+ activemq-pool
+
+
+ org.apache.camel
+ camel-jackson
+
+
+ org.springframework.cloud
+ spring-cloud-contract-verifier
+ test
+
+
+ org.spockframework
+ spock-spring
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
diff --git a/tests/samples-messaging-camel/src/main/java/com/example/BookDeleted.java b/tests/samples-messaging-camel/src/main/java/com/example/BookDeleted.java
new file mode 100644
index 0000000000..03572a97c6
--- /dev/null
+++ b/tests/samples-messaging-camel/src/main/java/com/example/BookDeleted.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-2017 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 com.example;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@SuppressWarnings("serial")
+public class BookDeleted implements Serializable {
+ public final String bookName;
+
+ @JsonCreator
+ public BookDeleted(@JsonProperty("bookName") String bookName) {
+ this.bookName = bookName;
+ }
+}
diff --git a/tests/samples-messaging-camel/src/main/java/com/example/BookDeleter.java b/tests/samples-messaging-camel/src/main/java/com/example/BookDeleter.java
new file mode 100644
index 0000000000..31e051f696
--- /dev/null
+++ b/tests/samples-messaging-camel/src/main/java/com/example/BookDeleter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013-2017 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 com.example;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.camel.Exchange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class BookDeleter {
+
+ private static final Logger log = LoggerFactory.getLogger(BookDeleter.class);
+
+ /**
+ * Scenario for "should generate tests triggered by a message": client side: if sends
+ * a message to input.messageFrom then message will be sent to output.messageFrom
+ * server side: will send a message to input, verify the message contents and await
+ * upon receiving message on the output messageFrom
+ */
+ public void bookDeleted(Exchange exchange) {
+ BookDeleted bookDeleted = exchange.getIn().getBody(BookDeleted.class);
+ log.info("Deleting book " + bookDeleted);
+ this.bookSuccessfulyDeleted.set(true);
+ log.info("Book successfuly deleted [" + this.bookSuccessfulyDeleted + "]");
+ }
+
+ private AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false);
+}
diff --git a/tests/samples-messaging-camel/src/main/java/com/example/BookReturned.java b/tests/samples-messaging-camel/src/main/java/com/example/BookReturned.java
new file mode 100644
index 0000000000..6eea1a5780
--- /dev/null
+++ b/tests/samples-messaging-camel/src/main/java/com/example/BookReturned.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-2017 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 com.example;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@SuppressWarnings("serial")
+public class BookReturned implements Serializable {
+ public final String bookName;
+
+ @JsonCreator
+ BookReturned(@JsonProperty("bookName") String bookName) {
+ this.bookName = bookName;
+ }
+}
diff --git a/tests/samples-messaging-camel/src/main/java/com/example/BookRouteConfiguration.java b/tests/samples-messaging-camel/src/main/java/com/example/BookRouteConfiguration.java
new file mode 100644
index 0000000000..3f4f6c9022
--- /dev/null
+++ b/tests/samples-messaging-camel/src/main/java/com/example/BookRouteConfiguration.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013-2017 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 com.example;
+
+import org.apache.activemq.camel.component.ActiveMQComponent;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.model.dataformat.JsonLibrary;
+import org.apache.camel.spring.SpringRouteBuilder;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+@Configuration
+public class BookRouteConfiguration {
+
+ @Bean
+ ActiveMQComponent activeMQComponent(@Value("${activemq.url:vm://localhost?broker.persistent=false}") String url) {
+ ActiveMQComponent component = new ActiveMQComponent();
+ component.setBrokerURL(url);
+ return component;
+ }
+
+ @Bean
+ RoutesBuilder myRouter(final BookService bookService, final BookDeleter bookDeleter) {
+ return new SpringRouteBuilder() {
+
+ @Override
+ public void configure() throws Exception {
+ // scenario 1 - from bean to output
+ from("direct:start").unmarshal().json(JsonLibrary.Jackson, BookReturned.class).bean(bookService).to("jms:output");
+ // scenario 2 - from input to output
+ from("jms:input").unmarshal().json(JsonLibrary.Jackson, BookReturned.class).bean(bookService).to("jms:output");
+ // scenario 3 - from input to no output
+ from("jms:delete").unmarshal().json(JsonLibrary.Jackson, BookDeleted.class).bean(bookDeleter);
+ }
+
+ };
+ }
+}
diff --git a/tests/samples-messaging-camel/src/main/java/com/example/BookService.java b/tests/samples-messaging-camel/src/main/java/com/example/BookService.java
new file mode 100644
index 0000000000..a145e482d6
--- /dev/null
+++ b/tests/samples-messaging-camel/src/main/java/com/example/BookService.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013-2017 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 com.example;
+
+import org.apache.camel.Exchange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BookService {
+
+ private static final Logger log = LoggerFactory.getLogger(BookService.class);
+
+ /**
+ * Scenario for "should generate tests triggered by a method": client side: must have
+ * a possibility to "trigger" sending of a message to the given messageFrom server
+ * side: will run the method and await upon receiving message on the output
+ * messageFrom
+ *
+ * Method triggers sending a message to a source
+ */
+ public void returnBook(Exchange exchange) {
+ BookReturned bookReturned = exchange.getIn().getBody(BookReturned.class);
+ log.info("Returning book [$bookReturned]");
+ exchange.getOut().setBody(bookReturned);
+ exchange.getOut().setHeader("BOOK-NAME", bookReturned.bookName);
+ }
+}
diff --git a/tests/samples-messaging-camel/src/main/java/com/example/CamelMessagingApplication.java b/tests/samples-messaging-camel/src/main/java/com/example/CamelMessagingApplication.java
new file mode 100644
index 0000000000..25ff4fccc4
--- /dev/null
+++ b/tests/samples-messaging-camel/src/main/java/com/example/CamelMessagingApplication.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013-2017 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 com.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CamelMessagingApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CamelMessagingApplication.class, args);
+ }
+}
diff --git a/tests/samples-messaging-camel/src/test/groovy/com/example/CamelMessagingApplicationSpec.groovy b/tests/samples-messaging-camel/src/test/groovy/com/example/CamelMessagingApplicationSpec.groovy
new file mode 100644
index 0000000000..2785036d98
--- /dev/null
+++ b/tests/samples-messaging-camel/src/test/groovy/com/example/CamelMessagingApplicationSpec.groovy
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2013-2017 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 com.example
+
+import javax.inject.Inject
+
+import org.apache.camel.Message
+import org.apache.camel.model.ModelCamelContext
+import org.junit.BeforeClass
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootContextLoader
+import org.springframework.cloud.contract.spec.Contract
+import org.springframework.cloud.contract.verifier.messaging.MessageVerifier
+import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper;
+import org.springframework.test.context.ContextConfiguration
+
+import spock.lang.Specification
+import spock.util.concurrent.PollingConditions
+
+import com.jayway.jsonpath.DocumentContext
+import com.jayway.jsonpath.JsonPath
+import com.toomuchcoding.jsonassert.JsonAssertion
+/**
+ * SPIKE ON TESTS FROM NOTES IN MessagingSpec
+ */
+// Context configuration would end up in base class
+@ContextConfiguration(classes = [CamelMessagingApplication], loader = SpringBootContextLoader)
+@AutoConfigureMessageVerifier
+class CamelMessagingApplicationSpec extends Specification {
+
+ // ALL CASES
+ @Autowired ModelCamelContext camelContext
+ @Autowired BookDeleter bookDeleter
+ @Inject MessageVerifier contractVerifierMessaging
+
+ ContractVerifierObjectMapper contractVerifierObjectMapper = new ContractVerifierObjectMapper()
+
+ @BeforeClass
+ static void init() {
+ System.setProperty("org.apache.activemq.SERIALIZABLE_PACKAGES", "*")
+ }
+
+ def "should work for triggered based messaging"() {
+ given:
+ Contract.make {
+ label 'some_label'
+ input {
+ triggeredBy('bookReturnedTriggered()')
+ }
+ outputMessage {
+ sentTo('activemq:output')
+ body('''{ "bookName" : "foo" }''')
+ headers {
+ header('BOOK-NAME', 'foo')
+ }
+ }
+ }
+ // generated test should look like this:
+ when:
+ bookReturnedTriggered()
+ then:
+ def response = contractVerifierMessaging.receive('activemq:output')
+ response.headers.get('BOOK-NAME') == 'foo'
+ and:
+ DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.body))
+ JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
+ }
+
+ def "should generate tests triggered by a message"() {
+ given:
+ Contract.make {
+ label 'some_label'
+ input {
+ messageFrom('jms:input')
+ messageBody([
+ bookName: 'foo'
+ ])
+ messageHeaders {
+ header('sample', 'header')
+
+ }
+ }
+ outputMessage {
+ sentTo('jms:output')
+ body([
+ bookName: 'foo'
+ ])
+ headers {
+ header('BOOK-NAME', 'foo')
+ }
+ }
+ }
+ // generated test should look like this:
+ when:
+ contractVerifierMessaging.send(
+ contractVerifierObjectMapper.writeValueAsString([bookName: 'foo']),
+ [sample: 'header'], 'jms:input')
+ then:
+ def response = contractVerifierMessaging.receive('jms:output')
+ response.headers.get('BOOK-NAME') == 'foo'
+ and:
+ DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.body))
+ JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
+ }
+
+ def "should generate tests without destination, triggered by a message"() {
+ given:
+ Contract.make {
+ label 'some_label'
+ input {
+ messageFrom('jms:delete')
+ messageBody([
+ bookName: 'foo'
+ ])
+ messageHeaders {
+ header('sample', 'header')
+ }
+ assertThat('bookWasDeleted()')
+ }
+ }
+ // generated test should look like this:
+ when:
+ contractVerifierMessaging.send(contractVerifierObjectMapper.writeValueAsString([bookName: 'foo']),
+ [sample: 'header'], 'jms:delete')
+ then:
+ noExceptionThrown()
+ bookWasDeleted()
+ }
+
+ void bookReturnedTriggered() {
+ camelContext.createProducerTemplate().sendBody('direct:start', '''{"bookName" : "foo" }''')
+ }
+
+ PollingConditions pollingConditions = new PollingConditions()
+
+ void bookWasDeleted() {
+ pollingConditions.eventually {
+ assert bookDeleter.bookSuccessfulyDeleted.get()
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/tests/spring-cloud-contract-stub-runner-camel/README.adoc b/tests/spring-cloud-contract-stub-runner-camel/README.adoc
new file mode 100644
index 0000000000..30c50c8e55
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/README.adoc
@@ -0,0 +1,123 @@
+:input_name: jms:input
+:output_name: jms:output
+
+=== Stub Runner Camel
+
+Spring Cloud Contract Verifier Stub Runner's messaging module gives you an easy way to integrate with Apache Camel.
+For the provided artifacts it will automatically download the stubs and register the required
+routes.
+
+==== Adding it to the project
+
+It's enough to have both Apache Camel and Spring Cloud Contract Stub Runner on classpath.
+Remember to annotate your test class with `@AutoConfigureStubRunner`.
+
+==== Disabling the functionality
+
+If you need to disable this functionality just pass `stubrunner.camel.enabled=false` property.
+
+==== Examples
+
+===== Stubs structure
+
+Let us assume that we have the following Maven repository with a deployed stubs for the
+`camelService` application.
+
+[source,bash,indent=0]
+----
+└── .m2
+ └── repository
+ └── io
+ └── codearte
+ └── accurest
+ └── stubs
+ └── camelService
+ ├── 0.0.1-SNAPSHOT
+ │ ├── camelService-0.0.1-SNAPSHOT.pom
+ │ ├── camelService-0.0.1-SNAPSHOT-stubs.jar
+ │ └── maven-metadata-local.xml
+ └── maven-metadata-local.xml
+----
+
+And the stubs contain the following structure:
+
+[source,bash,indent=0]
+----
+├── META-INF
+│ └── MANIFEST.MF
+└── repository
+ ├── accurest
+ │ ├── bookDeleted.groovy
+ │ ├── bookReturned1.groovy
+ │ └── bookReturned2.groovy
+ └── mappings
+----
+
+Let's consider the following contracts (let' number it with *1*):
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=sample_dsl,indent=0]
+----
+
+and number *2*
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=sample_dsl_2,indent=0]
+----
+
+===== Scenario 1 (no input message)
+
+So as to trigger a message via the `return_book_1` label we'll use the `StubTigger` interface as follows
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger,indent=0]
+----
+
+Next we'll want to listen to the output of the message sent to `{output_name}`
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger_receive,indent=0]
+----
+
+And the received message would pass the following assertions
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger_message,indent=0]
+----
+
+===== Scenario 2 (output triggered by input)
+
+Since the route is set for you it's enough to just send a message to the `{output_name}` destination.
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_send,indent=0]
+----
+
+Next we'll want to listen to the output of the message sent to `{output_name}`
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_receive,indent=0]
+----
+
+And the received message would pass the following assertions
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_receive_message,indent=0]
+----
+
+===== Scenario 3 (input with no output)
+
+Since the route is set for you it's enough to just send a message to the `{output_name}` destination.
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=trigger_no_output,indent=0]
+----
diff --git a/tests/spring-cloud-contract-stub-runner-camel/pom.xml b/tests/spring-cloud-contract-stub-runner-camel/pom.xml
new file mode 100644
index 0000000000..b1f7906e63
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/pom.xml
@@ -0,0 +1,93 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-contract-tests
+ 2.1.0.BUILD-SNAPSHOT
+ ..
+
+ spring-cloud-contract-stub-runner-camel
+ jar
+ Spring Cloud Contract Stub Runner Camel
+ Spring Cloud Contract Stub Runner Camel
+
+
+ org.springframework.cloud
+ spring-cloud-contract-stub-runner
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-stub-runner-jetty
+ test
+
+
+ org.apache.camel
+ camel-spring-boot-starter
+
+
+ org.apache.camel
+ camel-jackson
+
+
+ junit
+ junit
+ test
+
+
+ org.codehaus.groovy
+ groovy
+
+
+ org.spockframework
+ spock-core
+ test
+
+
+ org.spockframework
+ spock-spring
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.apache.activemq
+ activemq-camel
+ test
+
+
+ org.apache.activemq
+ activemq-pool
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ test
+
+
+ info.solidsoft.spock
+ spock-global-unroll
+ test
+
+
+
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+
+
+
+ testCompile
+
+
+
+
+
+
+
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/BookReturned.groovy b/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/BookReturned.groovy
new file mode 100644
index 0000000000..26428fd9fd
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/BookReturned.groovy
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-2017 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.messaging.camel
+
+import com.fasterxml.jackson.annotation.JsonCreator
+import groovy.transform.CompileStatic
+import groovy.transform.EqualsAndHashCode
+
+@CompileStatic
+@EqualsAndHashCode
+class BookReturned implements Serializable {
+ final String bookName
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ BookReturned(String bookName) {
+ this.bookName = bookName
+ }
+}
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy b/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy
new file mode 100644
index 0000000000..8c6c525c5b
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2013-2017 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.messaging.camel
+
+import groovy.json.JsonOutput
+import groovy.json.JsonSlurper
+import org.apache.activemq.camel.component.ActiveMQComponent
+import org.apache.activemq.spring.ActiveMQConnectionFactory
+import org.apache.camel.CamelContext
+import org.apache.camel.Exchange
+import org.apache.camel.component.jms.JmsConfiguration
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.test.context.SpringBootContextLoader
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.cloud.contract.spec.Contract
+import org.springframework.cloud.contract.stubrunner.StubFinder
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.annotation.Configuration
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.IgnoreIf
+import spock.lang.Specification
+/**
+ * @author Marcin Grzejszczak
+ */
+@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
+@SpringBootTest(properties = "debug=true")
+@AutoConfigureStubRunner
+@IgnoreIf({ os.windows })
+class CamelStubRunnerSpec extends Specification {
+
+ @Autowired StubFinder stubFinder
+ @Autowired CamelContext camelContext
+
+ def setup() {
+ // ensure that message were taken from the queue
+ camelContext.createConsumerTemplate().receive('jms:output', 100)
+ }
+
+ def 'should download the stub and register a route for it'() {
+ when:
+ // tag::client_send[]
+ camelContext.createProducerTemplate().sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])
+ // end::client_send[]
+ then:
+ // tag::client_receive[]
+ Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
+ // end::client_receive[]
+ and:
+ // tag::client_receive_message[]
+ receivedMessage != null
+ assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
+ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
+ // end::client_receive_message[]
+ }
+
+ def 'should trigger a message by label'() {
+ when:
+ // tag::client_trigger[]
+ stubFinder.trigger('return_book_1')
+ // end::client_trigger[]
+ then:
+ // tag::client_trigger_receive[]
+ Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
+ // end::client_trigger_receive[]
+ and:
+ // tag::client_trigger_message[]
+ receivedMessage != null
+ assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
+ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
+ // end::client_trigger_message[]
+ }
+
+ def 'should trigger a label for the existing groupId:artifactId'() {
+ when:
+ // tag::trigger_group_artifact[]
+ stubFinder.trigger('org.springframework.cloud.contract.verifier.stubs:camelService', 'return_book_1')
+ // end::trigger_group_artifact[]
+ then:
+ Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
+ and:
+ receivedMessage != null
+ assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
+ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
+ }
+
+ def 'should trigger a label for the existing artifactId'() {
+ when:
+ // tag::trigger_artifact[]
+ stubFinder.trigger('camelService', 'return_book_1')
+ // end::trigger_artifact[]
+ then:
+ Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
+ and:
+ receivedMessage != null
+ assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
+ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
+ }
+
+ def 'should throw an exception when missing label is passed'() {
+ when:
+ stubFinder.trigger('missing label')
+ then:
+ thrown(IllegalArgumentException)
+ }
+
+ def 'should throw an exception when missing label and artifactid is passed'() {
+ when:
+ stubFinder.trigger('some:service', 'return_book_1')
+ then:
+ thrown(IllegalArgumentException)
+ }
+
+ def 'should trigger messages by running all triggers'() {
+ when:
+ // tag::trigger_all[]
+ stubFinder.trigger()
+ // end::trigger_all[]
+ then:
+ Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
+ and:
+ receivedMessage != null
+ assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
+ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
+ }
+
+ def 'should trigger a label with no output message'() {
+ when:
+ // tag::trigger_no_output[]
+ camelContext.createProducerTemplate().sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])
+ // end::trigger_no_output[]
+ then:
+ noExceptionThrown()
+ }
+
+ def 'should not trigger a message that does not match input'() {
+ when:
+ camelContext.createProducerTemplate().sendBodyAndHeaders('jms:input', new BookReturned('notmatching'), [wrong: 'header_value'])
+ then:
+ Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 100)
+ and:
+ receivedMessage == null
+ }
+
+ private boolean assertThatBodyContainsBookNameFoo(Object payload) {
+ String objectAsString = payload instanceof String ? payload :
+ JsonOutput.toJson(payload)
+ def json = new JsonSlurper().parseText(objectAsString)
+ return json.bookName == 'foo'
+ }
+
+ @Configuration
+ @ComponentScan
+ @EnableAutoConfiguration
+ static class Config {
+
+ @Bean
+ ActiveMQConnectionFactory activeMQConnectionFactory(@Value('${activemq.url:vm://localhost?broker.persistent=false}') String url) {
+ ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL: url)
+ try {
+ factory.trustAllPackages = true
+ } catch (Throwable e) {
+ }
+ return factory
+ }
+
+ @Bean
+ JmsConfiguration jmsConfiguration(ActiveMQConnectionFactory activeMQConnectionFactory) {
+ return new JmsConfiguration(connectionFactory: activeMQConnectionFactory)
+ }
+
+ @Bean
+ ActiveMQComponent activeMQComponent(JmsConfiguration jmsConfiguration) {
+ return new ActiveMQComponent(configuration: jmsConfiguration)
+ }
+ }
+
+
+ Contract dsl =
+ // tag::sample_dsl[]
+ Contract.make {
+ label 'return_book_1'
+ input {
+ triggeredBy('bookReturnedTriggered()')
+ }
+ outputMessage {
+ sentTo('jms:output')
+ body('''{ "bookName" : "foo" }''')
+ headers {
+ header('BOOK-NAME', 'foo')
+ }
+ }
+ }
+ // end::sample_dsl[]
+
+ Contract dsl2 =
+ // tag::sample_dsl_2[]
+ Contract.make {
+ label 'return_book_2'
+ input {
+ messageFrom('jms:input')
+ messageBody([
+ bookName: 'foo'
+ ])
+ messageHeaders {
+ header('sample', 'header')
+ }
+ }
+ outputMessage {
+ sentTo('jms:output')
+ body([
+ bookName: 'foo'
+ ])
+ headers {
+ header('BOOK-NAME', 'foo')
+ }
+ }
+ }
+ // end::sample_dsl_2[]
+
+ Contract dsl3 =
+ // tag::sample_dsl_3[]
+ Contract.make {
+ label 'delete_book'
+ input {
+ messageFrom('jms:delete')
+ messageBody([
+ bookName: 'foo'
+ ])
+ messageHeaders {
+ header('sample', 'header')
+ }
+ assertThat('bookWasDeleted()')
+ }
+ }
+ // end::sample_dsl_3[]
+}
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelProcessorSpec.groovy b/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelProcessorSpec.groovy
new file mode 100644
index 0000000000..279782c65e
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/StubRunnerCamelProcessorSpec.groovy
@@ -0,0 +1,98 @@
+package org.springframework.cloud.contract.stubrunner.messaging.camel
+
+import org.apache.camel.CamelContext
+import org.apache.camel.Exchange
+import org.apache.camel.builder.ExchangeBuilder
+import org.apache.camel.spring.SpringCamelContext
+import org.springframework.cloud.contract.spec.Contract
+import spock.lang.Specification
+
+class StubRunnerCamelProcessorSpec extends Specification {
+
+ CamelContext camelContext = new SpringCamelContext()
+ Exchange message = ExchangeBuilder.anExchange(camelContext).build()
+
+ def noOutputMessageContract = Contract.make {
+ label 'return_book_2'
+ input {
+ messageFrom('bookStorage')
+ messageBody([
+ bookId: $(consumer(regex('[0-9]+')), producer('123'))
+ ])
+ messageHeaders {
+ header('sample', 'header')
+ }
+ }
+ }
+
+ def 'should not process the message if there is no output message'() {
+ given:
+ StubRunnerCamelProcessor processor = new StubRunnerCamelProcessor(noOutputMessageContract)
+ when:
+ processor.process(message)
+ then:
+ noExceptionThrown()
+ }
+
+ def dsl = Contract.make {
+ label 'return_book_2'
+ input {
+ messageFrom('bookStorage')
+ messageBody([
+ bookId: $(consumer(regex('[0-9]+')), producer('123'))
+ ])
+ messageHeaders {
+ header('sample', 'header')
+ }
+ }
+ outputMessage {
+ sentTo('returnBook')
+ body([
+ responseId: $(producer(regex('[0-9]+')), consumer('123'))
+ ])
+ headers {
+ header('BOOK-NAME', 'foo')
+ }
+ }
+ }
+
+ def 'should process message when it has an output message section'() {
+ given:
+ StubRunnerCamelProcessor processor = new StubRunnerCamelProcessor(dsl)
+ when:
+ processor.process(message)
+ then:
+ message.getIn().getBody(String) == '{"responseId":"123"}'
+ }
+
+ def dslWithRegexInGString = Contract.make {
+ // Human readable description
+ description 'Should produce valid sensor data'
+ // Label by means of which the output message can be triggered
+ label 'sensor1'
+ // input to the contract
+ input {
+ // the contract will be triggered by a method
+ triggeredBy('createSensorData()')
+ }
+ // output message of the contract
+ outputMessage {
+ // destination to which the output message will be sent
+ sentTo 'sensor-data'
+ headers {
+ header('contentType': 'application/json')
+ }
+ // the body of the output message
+ body("""{"id":"${value(producer(regex('[0-9]+')), consumer('99'))}","temperature":"123.45"}""")
+ }
+ }
+
+ def 'should convert dsl into message with regex in GString'() {
+ given:
+ StubRunnerCamelProcessor processor = new StubRunnerCamelProcessor(dslWithRegexInGString)
+ when:
+ processor.process(message)
+ then:
+ message.getIn().getBody(String) == '''{"id":"99","temperature":"123.45"}'''
+ }
+}
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/application.yml b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/application.yml
new file mode 100644
index 0000000000..b1b686626b
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/application.yml
@@ -0,0 +1,7 @@
+stubrunner:
+ repositoryRoot: classpath:m2repo/repository/
+ ids: org.springframework.cloud.contract.verifier.stubs:camelService:0.0.1-SNAPSHOT:stubs
+ stubs-mode: remote
+server:
+ port: 0
+debug: true
\ No newline at end of file
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/camelService-0.0.1-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/camelService-0.0.1-SNAPSHOT-stubs.jar
new file mode 100644
index 0000000000..b27b155a3e
Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/camelService-0.0.1-SNAPSHOT-stubs.jar differ
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/camelService-0.0.1-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/camelService-0.0.1-SNAPSHOT.pom
new file mode 100644
index 0000000000..b2210f65ff
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/camelService-0.0.1-SNAPSHOT.pom
@@ -0,0 +1,25 @@
+
+
+
+
+ 4.0.0
+ org.springframework.cloud.contract.verifier.stubs
+ camelService
+ 0.0.1-SNAPSHOT
+ pom
+
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/maven-metadata-local.xml b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/maven-metadata-local.xml
new file mode 100644
index 0000000000..f0954907f2
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/0.0.1-SNAPSHOT/maven-metadata-local.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ org.springframework.cloud.contract.verifier.stubs
+ camelService
+ 0.0.1-SNAPSHOT
+
+
+ true
+
+ 20160409062112
+
+
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/maven-metadata-local.xml b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/maven-metadata-local.xml
new file mode 100644
index 0000000000..00bf4217ee
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/maven-metadata-local.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ org.springframework.cloud.contract.verifier.stubs
+ camelService
+ 0.0.1-SNAPSHOT
+
+
+ 0.0.1-SNAPSHOT
+
+ 20160409062112
+
+
diff --git a/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/maven-metadata.xml
new file mode 100644
index 0000000000..00bf4217ee
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-camel/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/camelService/maven-metadata.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ org.springframework.cloud.contract.verifier.stubs
+ camelService
+ 0.0.1-SNAPSHOT
+
+
+ 0.0.1-SNAPSHOT
+
+ 20160409062112
+
+