Convert stub runner camel to Java

This commit is contained in:
Dave Syer
2016-07-15 17:28:48 +01:00
parent 3a85b60408
commit f1634eb0ff
6 changed files with 182 additions and 156 deletions

View File

@@ -86,9 +86,6 @@
<executions>
<execution>
<goals>
<goal>addSources</goal>
<goal>addTestSources</goal>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>

View File

@@ -1,79 +0,0 @@
/*
* 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.messaging.camel
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import com.toomuchcoding.jsonassert.JsonAssertion
import com.toomuchcoding.jsonassert.JsonVerifiable
import groovy.transform.PackageScope
import org.springframework.cloud.contract.spec.Contract
import org.apache.camel.Exchange
import org.apache.camel.Predicate
import org.springframework.cloud.contract.verifier.messaging.ContractVerifierObjectMapper
import org.springframework.cloud.contract.verifier.util.JsonPaths
import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter
import java.util.regex.Pattern
/**
* Passes through a message that matches the one defined in the DSL
*
* @author Marcin Grzejszczak
*/
@PackageScope
class StubRunnerCamelPredicate implements Predicate {
private final Contract groovyDsl
private final ContractVerifierObjectMapper objectMapper = new ContractVerifierObjectMapper()
StubRunnerCamelPredicate(Contract groovyDsl) {
this.groovyDsl = groovyDsl
}
@Override
boolean matches(Exchange exchange) {
if(!headersMatch(exchange)){
return false
}
Object inputMessage = exchange.in.body
JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithStubsSideValues(groovyDsl.input.messageBody)
DocumentContext parsedJson = JsonPath.parse(objectMapper.writeValueAsString(inputMessage))
return jsonPaths.every { matchesJsonPath(parsedJson, it) }
}
private boolean matchesJsonPath(DocumentContext parsedJson, JsonVerifiable jsonVerifiable) {
try {
JsonAssertion.assertThat(parsedJson).matchesJsonPath(jsonVerifiable.jsonPath())
return true
} catch (Exception e) {
return false
}
}
private boolean headersMatch(Exchange exchange) {
Map<String, Object> headers = exchange.getIn().getHeaders()
return groovyDsl.input.messageHeaders.entries.every {
String name = it.name
Object value = it.clientValue
Object valueInHeader = headers.get(name)
return value instanceof Pattern ?
value.matcher(valueInHeader.toString()).matches() :
valueInHeader == value
}
}
}

View File

@@ -1,55 +0,0 @@
/*
* 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.messaging.camel
import groovy.transform.PackageScope
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
/**
* 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
*/
@PackageScope
class StubRunnerCamelProcessor implements Processor {
private final Contract groovyDsl
StubRunnerCamelProcessor(Contract groovyDsl) {
this.groovyDsl = groovyDsl
}
@Override
void process(Exchange exchange) throws Exception {
Message input = exchange.in
groovyDsl.input.messageHeaders?.entries?.each {
input.removeHeader(it.name)
}
if (!groovyDsl.outputMessage) {
return
}
input.body = BodyExtractor.extractStubValueFrom(groovyDsl.outputMessage.body)
groovyDsl.outputMessage.headers?.entries?.each {
input.setHeader(it.name, it.clientValue)
}
}
}

View File

@@ -14,37 +14,44 @@
* limitations under the License.
*/
package org.springframework.cloud.contract.stubrunner.messaging.camel
package org.springframework.cloud.contract.stubrunner.messaging.camel;
import org.apache.camel.RoutesBuilder
import org.apache.camel.spring.SpringRouteBuilder
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.Bean
import org.springframework.context.annotation.Configuration
import java.util.Collection;
import java.util.Map;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.spring.SpringRouteBuilder;
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.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Camel configuration that iterates over the downloaded Groovy DSLs
* and registers a route for each DSL.
* Camel configuration that iterates over the downloaded Groovy DSLs and registers a route
* for each DSL.
*
* @author Marcin Grzejszczak
*/
@Configuration
class StubRunnerCamelConfiguration {
public class StubRunnerCamelConfiguration {
@Bean
RoutesBuilder myRouter(BatchStubRunner batchStubRunner) {
public RoutesBuilder myRouter(final BatchStubRunner batchStubRunner) {
return new SpringRouteBuilder() {
@Override
public void configure() throws Exception {
Map<StubConfiguration, Collection<Contract>> contracts = batchStubRunner.contracts
(contracts.values().flatten() as Collection<Contract>).findAll { it?.input?.messageFrom?.clientValue && it?.outputMessage?.sentTo }.each {
from(it.input.messageFrom.clientValue)
.filter(new StubRunnerCamelPredicate(it))
.process(new StubRunnerCamelProcessor(it))
.to(it.outputMessage.sentTo.clientValue)
}
Map<StubConfiguration, Collection<Contract>> contracts = batchStubRunner.getContracts();
for (Collection<Contract> 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());
}
}
}
}
};
}

View File

@@ -0,0 +1,97 @@
/*
* 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.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.Header;
import org.springframework.cloud.contract.verifier.messaging.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;
import com.toomuchcoding.jsonassert.JsonVerifiable;
/**
* Passes through a message that matches the one defined in the DSL
*
* @author Marcin Grzejszczak
*/
public 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)) {
return false;
}
Object inputMessage = exchange.getIn().getBody();
JsonPaths jsonPaths = JsonToJsonPathsConverter
.transformToJsonPathWithStubsSideValues(groovyDsl.getInput().getMessageBody());
DocumentContext parsedJson;
try {
parsedJson = JsonPath
.parse(objectMapper.writeValueAsString(inputMessage));
}
catch (JsonProcessingException e) {
throw new IllegalStateException("Cannot serialize to JSON", e);
}
boolean matches = true;
for (MethodBufferingJsonVerifiable path : jsonPaths) {
matches &= matchesJsonPath(parsedJson, path);
}
return matches;
}
private boolean matchesJsonPath(DocumentContext parsedJson, JsonVerifiable jsonVerifiable) {
try {
JsonAssertion.assertThat(parsedJson).matchesJsonPath(jsonVerifiable.jsonPath());
return true;
} catch (Exception e) {
return false;
}
}
private boolean headersMatch(Exchange exchange) {
Map<String, Object> headers = exchange.getIn().getHeaders();
boolean matches = true;
for (Header it : groovyDsl.getInput().getMessageHeaders().getEntries()) {
String name = it.getName();
Object value = it.getClientValue();
Object valueInHeader = headers.get(name);
matches &= value instanceof Pattern ?
((Pattern) value).matcher(valueInHeader.toString()).matches() :
valueInHeader.equals(value);
}
return matches;
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.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 (groovyDsl.getInput().getMessageHeaders() != null) {
for (Header entry : groovyDsl.getInput().getMessageHeaders().getEntries()) {
input.removeHeader(entry.getName());
}
}
if (groovyDsl.getOutputMessage() == null) {
return;
}
input.setBody(BodyExtractor
.extractStubValueFrom(groovyDsl.getOutputMessage().getBody()));
if (groovyDsl.getOutputMessage().getHeaders() != null) {
for (Header entry : groovyDsl.getOutputMessage().getHeaders().getEntries()) {
input.setHeader(entry.getName(), entry.getClientValue());
}
}
}
}