diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java index f97628ff88..54a4e33abb 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java @@ -18,8 +18,12 @@ package org.springframework.cloud.contract.stubrunner.spring; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.contract.stubrunner.BatchStubRunner; @@ -54,9 +58,6 @@ public class StubRunnerConfiguration { static final String STUBRUNNER_PREFIX = "stubrunner.runningstubs"; - @Autowired(required = false) - private MessageVerifier contractVerifierMessaging; - private StubDownloaderBuilderProvider provider = new StubDownloaderBuilderProvider(); @Autowired @@ -72,7 +73,7 @@ public class StubRunnerConfiguration { * @return the batch stub runner bean */ @Bean - public BatchStubRunner batchStubRunner() { + public BatchStubRunner batchStubRunner(BeanFactory beanFactory) { StubRunnerOptionsBuilder builder = builder(); if (this.props.getProxyHost() != null) { builder.withProxy(this.props.getProxyHost(), this.props.getProxyPort()); @@ -80,14 +81,19 @@ public class StubRunnerConfiguration { StubRunnerOptions stubRunnerOptions = builder.build(); BatchStubRunner batchStubRunner = new BatchStubRunnerFactory(stubRunnerOptions, this.provider.get(stubRunnerOptions), - this.contractVerifierMessaging != null ? this.contractVerifierMessaging - : new NoOpStubMessages()).buildBatchStubRunner(); + new LazyMessageVerifier(beanFactory)).buildBatchStubRunner(); // TODO: Consider running it in a separate thread RunningStubs runningStubs = batchStubRunner.runStubs(); registerPort(runningStubs); return batchStubRunner; } + @Bean + public BeanPostProcessor batchStubRunnerBeanPostProcessor(BatchStubRunner runner) { + return new BeanPostProcessor() { + }; + } + private StubRunnerOptionsBuilder builder() { return new StubRunnerOptionsBuilder() .withMinMaxPort(this.props.getMinPort(), this.props.getMaxPort()) @@ -131,3 +137,47 @@ public class StubRunnerConfiguration { } } + +class LazyMessageVerifier implements MessageVerifier { + + private MessageVerifier messageVerifier; + + private final BeanFactory beanFactory; + + LazyMessageVerifier(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + private MessageVerifier messageVerifier() { + if (this.messageVerifier == null) { + try { + this.messageVerifier = this.beanFactory.getBean(MessageVerifier.class); + } + catch (BeansException ex) { + this.messageVerifier = new NoOpStubMessages(); + } + } + return this.messageVerifier; + } + + @Override + public void send(Object message, String destination) { + messageVerifier().send(message, destination); + } + + @Override + public Object receive(String destination, long timeout, TimeUnit timeUnit) { + return messageVerifier().receive(destination, timeout, timeUnit); + } + + @Override + public Object receive(String destination) { + return messageVerifier().receive(destination); + } + + @Override + public void send(Object payload, Map headers, String destination) { + messageVerifier().send(payload, headers, destination); + } + +} \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/issue1225/Issue1225Tests.java b/spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/issue1225/Issue1225Tests.java new file mode 100644 index 0000000000..0168b647c4 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/issue1225/Issue1225Tests.java @@ -0,0 +1,80 @@ +/* + * Copyright 2013-2019 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 + * + * https://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.issue1225; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerPort; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.bind.annotation.RestController; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests that stub runner specific auto-configuration can be loaded up in combination with + * other slice tests + * + * @author Biju Kunjummen + */ +@RunWith(SpringRunner.class) +@SpringBootTest(properties = { + "ping.url=http://localhost:${stubrunner.runningstubs.loanIssuance.port}" }) +@AutoConfigureStubRunner(ids = { + "org.springframework.cloud.contract.verifier.stubs:loanIssuance:+:stubs", + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:+:stubs" }) +@ActiveProfiles("test") +public class Issue1225Tests { + + @StubRunnerPort("loanIssuance") + private int stubRunnerLoanIssuancePort; + + @Autowired + private PingProxyController pingProxyController; + + @Test + public void shouldInjectTheStubPortsAsEarlyAsPossible() { + assertThat(this.stubRunnerLoanIssuancePort).isPositive(); + assertThat(this.pingProxyController.pingUrl) + .contains(":" + this.stubRunnerLoanIssuancePort); + } + + @ComponentScan + @SpringBootConfiguration + static class Config { + + } + +} + +@RestController +class PingProxyController { + + String pingUrl; + + public PingProxyController(@Value("${ping.url}") String pingUrl) { + this.pingUrl = pingUrl; + } + +} \ No newline at end of file diff --git a/tests/spring-cloud-contract-stub-runner-context-path/src/test/java/com/example/loan/FailFastLoanApplicationServiceTests.java b/tests/spring-cloud-contract-stub-runner-context-path/src/test/java/com/example/loan/FailFastLoanApplicationServiceTests.java index 98da40bca1..de31af7ca2 100644 --- a/tests/spring-cloud-contract-stub-runner-context-path/src/test/java/com/example/loan/FailFastLoanApplicationServiceTests.java +++ b/tests/spring-cloud-contract-stub-runner-context-path/src/test/java/com/example/loan/FailFastLoanApplicationServiceTests.java @@ -46,9 +46,8 @@ public class FailFastLoanApplicationServiceTests { // Then assertThat(throwable).isInstanceOf(BeanCreationException.class); - assertThat(throwable.getCause()).isInstanceOf(BeanInstantiationException.class); assertThat(throwable.getCause().getCause()) - .isInstanceOf(IllegalArgumentException.class).hasMessageContaining( + .isInstanceOf(BeanInstantiationException.class).hasMessageContaining( "For groupId [org.springframework.cloud.contract.verifier.stubs] artifactId [should-not-be-found] " + "and classifier [stubs] the version was not resolved! The following exceptions took place"); } @@ -66,9 +65,8 @@ public class FailFastLoanApplicationServiceTests { // Then assertThat(throwable).isInstanceOf(BeanCreationException.class); - assertThat(throwable.getCause()).isInstanceOf(BeanInstantiationException.class); assertThat(throwable.getCause().getCause()) - .isInstanceOf(IllegalStateException.class) + .isInstanceOf(BeanInstantiationException.class) .hasMessageContaining("No stubs were found on classpath "); }