diff --git a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/pom.xml b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/pom.xml index 8e45a3af9e..bd2858f538 100644 --- a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/pom.xml +++ b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/pom.xml @@ -73,7 +73,7 @@ org.spockframework - spock-core + spock-spring test diff --git a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java new file mode 100644 index 0000000000..c5eb9af52a --- /dev/null +++ b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java @@ -0,0 +1,37 @@ +/* + * 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; + +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.ImportAutoConfiguration; + +/** + * @author Dave Syer + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ImportAutoConfiguration +public @interface AutoConfigureStubRunner { + +} diff --git a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java new file mode 100644 index 0000000000..3a9e2d040c --- /dev/null +++ b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java @@ -0,0 +1,86 @@ +/* + * 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; + +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.contract.stubrunner.AetherStubDownloader; +import org.springframework.cloud.contract.stubrunner.BatchStubRunner; +import org.springframework.cloud.contract.stubrunner.BatchStubRunnerFactory; +import org.springframework.cloud.contract.stubrunner.StubDownloader; +import org.springframework.cloud.contract.stubrunner.StubRunner; +import org.springframework.cloud.contract.stubrunner.StubRunnerOptions; +import org.springframework.cloud.contract.stubrunner.StubRunnerOptionsBuilder; +import org.springframework.cloud.contract.verifier.messaging.ContractVerifierMessaging; +import org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierMessaging; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; + +/** + * Configuration that initializes a {@link BatchStubRunner} that runs {@link StubRunner} instance for each stub + */ +@Configuration +@ConditionalOnMissingBean(type="org.springframework.cloud.contract.wiremock.WiremockServerConfiguration") +public class StubRunnerConfiguration { + + @Autowired(required = false) ContractVerifierMessaging contractVerifierMessaging; + @Autowired(required = false) StubDownloader stubDownloader; + + /** + * Bean that initializes stub runners, runs them and on shutdown closes them. Upon its instantiation + * JAR with stubs is downloaded and unpacked to a temporary folder and WireMock server are started + * for each of those stubs + * + * @param minPortValue min port value of the WireMock instance for stubs + * @param maxPortValue max port value of the WireMock instance for stubs + * @param stubRepositoryRoot root URL from where the JAR with stub mappings will be downloaded + * @param stubsSuffix classifier for the jar containing stubs + * @param workOffline forces offline work + * @param stubs comma separated list of stubs presented in Ivy notation + */ + @Bean + public BatchStubRunner batchStubRunner( + @Value("${stubrunner.port.range.min:10000}") Integer minPortValue, + @Value("${stubrunner.port.range.max:15000}") Integer maxPortValue, + @Value("${stubrunner.stubs.repository.root:}") Resource stubRepositoryRoot, + @Value("${stubrunner.stubs.classifier:stubs}") String stubsSuffix, + @Value("${stubrunner.work-offline:false}") boolean workOffline, + @Value("${stubrunner.stubs.ids:}") String stubs) throws IOException { + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withMinMaxPort(minPortValue, maxPortValue) + .withStubRepositoryRoot(uriStringOrEmpty(stubRepositoryRoot)) + .withWorkOffline(stubRepositoryRoot == null || workOffline) + .withStubsClassifier(stubsSuffix) + .withStubs(stubs) + .build(); + BatchStubRunner batchStubRunner = new BatchStubRunnerFactory(stubRunnerOptions, + stubDownloader != null ? stubDownloader : new AetherStubDownloader(stubRunnerOptions), + contractVerifierMessaging != null ? contractVerifierMessaging : new NoOpContractVerifierMessaging()).buildBatchStubRunner(); + // TODO: Consider running it in a separate thread + batchStubRunner.runStubs(); + return batchStubRunner; + } + + private String uriStringOrEmpty(Resource stubRepositoryRoot) throws IOException { + return stubRepositoryRoot != null ? stubRepositoryRoot.getURI().toString() : ""; + } + +} diff --git a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000..a0e462c04c --- /dev/null +++ b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +# Auto Configuration +org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner=\ +org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy new file mode 100644 index 0000000000..6d749e0efa --- /dev/null +++ b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy @@ -0,0 +1,58 @@ +/* + * 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 + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.context.SpringBootContextLoader +import org.springframework.cloud.contract.stubrunner.StubFinder +import org.springframework.context.annotation.Configuration +import org.springframework.test.context.ContextConfiguration + +import spock.lang.Specification + +/** + * @author Marcin Grzejszczak + */ +// tag::test[] +@ContextConfiguration(classes = Config, loader = SpringBootContextLoader) +@AutoConfigureStubRunner +class StubRunnerConfigurationSpec extends Specification { + + @Autowired StubFinder stubFinder + + def 'should start WireMock servers'() { + expect: 'WireMocks are running' + stubFinder.findStubUrl('org.springframework.cloud.contract.verifier.stubs', 'loanIssuance') != null + stubFinder.findStubUrl('loanIssuance') != null + stubFinder.findStubUrl('loanIssuance') == stubFinder.findStubUrl('org.springframework.cloud.contract.verifier.stubs', 'loanIssuance') + stubFinder.findStubUrl('org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer') != null + and: + stubFinder.findAllRunningStubs().isPresent('loanIssuance') + stubFinder.findAllRunningStubs().isPresent('org.springframework.cloud.contract.verifier.stubs', 'fraudDetectionServer') + stubFinder.findAllRunningStubs().isPresent('org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer') + and: 'Stubs were registered' + "${stubFinder.findStubUrl('loanIssuance').toString()}/name".toURL().text == 'loanIssuance' + "${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name".toURL().text == 'fraudDetectionServer' + } + + @Configuration + @EnableAutoConfiguration + static class Config {} +} +// end::test[] \ No newline at end of file diff --git a/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/test/resources/application.yml b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/test/resources/application.yml new file mode 100644 index 0000000000..4f618057e1 --- /dev/null +++ b/spring-cloud-contract-stub-runner/spring-cloud-contract-stub-runner/src/test/resources/application.yml @@ -0,0 +1,2 @@ +stubrunner.stubs.repository.root: classpath:m2repo/repository/ +stubrunner.stubs.ids: org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer \ No newline at end of file