From a6bf27ddb40e7125a223f165508a492c5e83ef42 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Thu, 21 May 2020 14:59:29 +0200 Subject: [PATCH] Updated configuration to include the stubbing of the new load balancer; fixes gh-1391 --- .../spring/StubRunnerConfiguration.java | 58 ++++++----- ...tubRunnerSpringCloudAutoConfiguration.java | 11 +-- ...ingCloudLoadBalancerAutoConfiguration.java | 74 +++++++++++--- .../main/resources/META-INF/spring.factories | 1 + ...nerSpringCloudAutoConfigurationSpec.groovy | 10 ++ ...gCloudNoRibbonAutoConfigurationSpec.groovy | 96 +++++++++++++++++++ .../application-cloudtest-no-ribbon.yml | 17 ++++ .../builder/JaxRsRequestMethodWhen.java | 6 +- 8 files changed, 220 insertions(+), 53 deletions(-) create mode 100644 spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudNoRibbonAutoConfigurationSpec.groovy create mode 100644 spring-cloud-contract-stub-runner/src/test/resources/application-cloudtest-no-ribbon.yml 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 f9bcf021b3..5af24e26c2 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 @@ -62,9 +62,6 @@ public class StubRunnerConfiguration { private StubDownloaderBuilderProvider provider = new StubDownloaderBuilderProvider(); - @Autowired - private StubRunnerProperties props; - @Autowired private ConfigurableEnvironment environment; @@ -77,9 +74,10 @@ public class StubRunnerConfiguration { */ @Bean public BatchStubRunner batchStubRunner(BeanFactory beanFactory) { - StubRunnerOptionsBuilder builder = builder(); - if (this.props.getProxyHost() != null) { - builder.withProxy(this.props.getProxyHost(), this.props.getProxyPort()); + StubRunnerProperties props = beanFactory.getBean(StubRunnerProperties.class); + StubRunnerOptionsBuilder builder = builder(props); + if (props.getProxyHost() != null) { + builder.withProxy(props.getProxyHost(), props.getProxyPort()); } StubRunnerOptions stubRunnerOptions = stubRunnerOptions(builder); BatchStubRunner batchStubRunner = new BatchStubRunnerFactory(stubRunnerOptions, @@ -101,30 +99,30 @@ public class StubRunnerConfiguration { }; } - private StubRunnerOptionsBuilder builder() { + private StubRunnerOptionsBuilder builder(StubRunnerProperties props) { return new StubRunnerOptionsBuilder() .withMinMaxPort( - Integer.valueOf(resolvePlaceholder(this.props.getMinPort(), - this.props.getMinPort())), - Integer.valueOf(resolvePlaceholder(this.props.getMaxPort(), - this.props.getMaxPort()))) - .withStubRepositoryRoot(this.props.getRepositoryRoot()) - .withStubsMode(resolvePlaceholder(this.props.getStubsMode())) - .withStubsClassifier(resolvePlaceholder(this.props.getClassifier())) - .withStubs(resolvePlaceholder(this.props.getIds())) - .withUsername(resolvePlaceholder(this.props.getUsername())) - .withPassword(resolvePlaceholder(this.props.getPassword())) - .withStubPerConsumer(Boolean.parseBoolean( - resolvePlaceholder(this.props.isStubsPerConsumer()))) - .withConsumerName(consumerName()) + Integer.valueOf(resolvePlaceholder(props.getMinPort(), + props.getMinPort())), + Integer.valueOf(resolvePlaceholder(props.getMaxPort(), + props.getMaxPort()))) + .withStubRepositoryRoot(props.getRepositoryRoot()) + .withStubsMode(resolvePlaceholder(props.getStubsMode())) + .withStubsClassifier(resolvePlaceholder(props.getClassifier())) + .withStubs(resolvePlaceholder(props.getIds())) + .withUsername(resolvePlaceholder(props.getUsername())) + .withPassword(resolvePlaceholder(props.getPassword())) + .withStubPerConsumer(Boolean + .parseBoolean(resolvePlaceholder(props.isStubsPerConsumer()))) + .withConsumerName(consumerName(props)) .withMappingsOutputFolder( - resolvePlaceholder(this.props.getMappingsOutputFolder())) - .withDeleteStubsAfterTest(Boolean.parseBoolean( - resolvePlaceholder(this.props.isDeleteStubsAfterTest()))) - .withGenerateStubs(Boolean - .parseBoolean(resolvePlaceholder(this.props.isGenerateStubs()))) - .withProperties(this.props.getProperties()) - .withHttpServerStubConfigurer(this.props.getHttpServerStubConfigurer()); + resolvePlaceholder(props.getMappingsOutputFolder())) + .withDeleteStubsAfterTest(Boolean + .parseBoolean(resolvePlaceholder(props.isDeleteStubsAfterTest()))) + .withGenerateStubs( + Boolean.parseBoolean(resolvePlaceholder(props.isGenerateStubs()))) + .withProperties(props.getProperties()) + .withHttpServerStubConfigurer(props.getHttpServerStubConfigurer()); } private String[] resolvePlaceholder(String[] string) { @@ -142,9 +140,9 @@ public class StubRunnerConfiguration { return this.environment.resolvePlaceholders(string.toString()); } - private String consumerName() { - if (StringUtils.hasText(this.props.getConsumerName())) { - return resolvePlaceholder(this.props.getConsumerName()); + private String consumerName(StubRunnerProperties props) { + if (StringUtils.hasText(props.getConsumerName())) { + return resolvePlaceholder(props.getConsumerName()); } return this.environment.getProperty("spring.application.name"); } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java index 85c78d6fea..3e52e5254f 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java @@ -18,7 +18,6 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -44,12 +43,10 @@ import org.springframework.core.env.Environment; @ConditionalOnProperty(value = "stubrunner.cloud.enabled", matchIfMissing = true) public class StubRunnerSpringCloudAutoConfiguration { - @Autowired - BeanFactory beanFactory; - @Bean - public StubRunnerDiscoveryClientWrapper stubRunnerDiscoveryClientWrapper() { - return new StubRunnerDiscoveryClientWrapper(this.beanFactory); + public StubRunnerDiscoveryClientWrapper stubRunnerDiscoveryClientWrapper( + BeanFactory beanFactory) { + return new StubRunnerDiscoveryClientWrapper(beanFactory); } @Bean @@ -70,8 +67,6 @@ class StubRunnerDiscoveryClientWrapper implements BeanPostProcessor { private final BeanFactory beanFactory; - DiscoveryClient discoveryClient; - StubFinder stubFinder; StubMapperProperties stubMapperProperties; diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/loadbalancer/SpringCloudLoadBalancerAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/loadbalancer/SpringCloudLoadBalancerAutoConfiguration.java index 4ef717d7e6..5ca4e925df 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/loadbalancer/SpringCloudLoadBalancerAutoConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/loadbalancer/SpringCloudLoadBalancerAutoConfiguration.java @@ -18,11 +18,13 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer; import java.io.Closeable; import java.net.URI; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import reactor.core.publisher.Mono; +import org.springframework.beans.factory.BeanFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -37,18 +39,21 @@ import org.springframework.cloud.contract.stubrunner.StubConfiguration; import org.springframework.cloud.contract.stubrunner.StubFinder; import org.springframework.cloud.contract.stubrunner.spring.cloud.ConditionalOnStubbedDiscoveryEnabled; import org.springframework.cloud.contract.stubrunner.spring.cloud.StubMapperProperties; +import org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloudAutoConfiguration; import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration; import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration; +import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.core.ResolvableType; import org.springframework.util.StringUtils; /** * Provides autoconfiguraion for the Spring Cloud Load Balancer module. * - * @since 3.0.0 + * @since 2.2.3 * @author Marcin Grzejszczak */ @Configuration(proxyBeanMethods = false) @@ -57,15 +62,16 @@ import org.springframework.util.StringUtils; matchIfMissing = true) @ConditionalOnBean(StubMapperProperties.class) @AutoConfigureBefore(LoadBalancerAutoConfiguration.class) -@AutoConfigureAfter(LoadBalancerClientConfiguration.class) +@AutoConfigureAfter({ LoadBalancerClientConfiguration.class, + StubRunnerSpringCloudAutoConfiguration.class }) @ConditionalOnStubbedDiscoveryEnabled public class SpringCloudLoadBalancerAutoConfiguration { @Bean @Primary - LoadBalancerClientFactory stubRunnerLoadBalancerClientFactory(StubFinder stubFinder, - StubMapperProperties stubMapperProperties) { - return new StubRunnerLoadBalancerClientFactory(stubFinder, stubMapperProperties); + LoadBalancerClientFactory stubRunnerLoadBalancerClientFactory( + BeanFactory beanFactory) { + return new StubRunnerLoadBalancerClientFactory(beanFactory); } } @@ -73,20 +79,62 @@ public class SpringCloudLoadBalancerAutoConfiguration { class StubRunnerLoadBalancerClientFactory extends LoadBalancerClientFactory implements Closeable { - private final StubFinder stubFinder; + private StubFinder stubFinder; - private final StubMapperProperties stubMapperProperties; + private StubMapperProperties stubMapperProperties; - StubRunnerLoadBalancerClientFactory(StubFinder stubFinder, - StubMapperProperties stubMapperProperties) { - this.stubFinder = stubFinder; - this.stubMapperProperties = stubMapperProperties; + private final BeanFactory beanFactory; + + StubRunnerLoadBalancerClientFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + private StubFinder stubFinder() { + if (this.stubFinder == null) { + this.stubFinder = this.beanFactory.getBean(StubFinder.class); + } + return this.stubFinder; + } + + private StubMapperProperties stubMapperProperties() { + if (this.stubMapperProperties == null) { + this.stubMapperProperties = this.beanFactory + .getBean(StubMapperProperties.class); + } + return this.stubMapperProperties; } @Override public ReactiveLoadBalancer getInstance(String serviceId) { - return request -> Mono.just(new DefaultResponse( - new StubbedServiceInstance(stubFinder, stubMapperProperties, serviceId))); + return (ReactorServiceInstanceLoadBalancer) request -> Mono + .just(new DefaultResponse(new StubbedServiceInstance(stubFinder(), + stubMapperProperties(), serviceId))); + } + + @Override + @SuppressWarnings("unchecked") + public T getInstance(String name, Class type) { + return (T) getInstance(name); + } + + @Override + @SuppressWarnings("unchecked") + public T getInstance(String name, Class clazz, Class... generics) { + return (T) getInstance(name); + } + + @Override + @SuppressWarnings("unchecked") + public T getInstance(String name, ResolvableType type) { + return (T) getInstance(name); + } + + @Override + @SuppressWarnings("unchecked") + public Map getInstances(String name, Class type) { + Map map = new HashMap<>(); + map.put(name, (T) getInstance(name)); + return map; } @Override 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 6b0934fcd7..fbe4976224 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 @@ -2,6 +2,7 @@ org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner=\ org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration,\ org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloudAutoConfiguration,\ +org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer.SpringCloudLoadBalancerAutoConfiguration,\ org.springframework.cloud.contract.stubrunner.spring.cloud.ribbon.StubRunnerRibbonAutoConfiguration,\ org.springframework.cloud.contract.stubrunner.messaging.integration.StubRunnerIntegrationConfiguration,\ org.springframework.cloud.contract.stubrunner.messaging.jms.StubRunnerJmsConfiguration,\ diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy index a92e5e738a..91132723d6 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy @@ -28,12 +28,15 @@ import org.springframework.cloud.consul.ConsulAutoConfiguration import org.springframework.cloud.contract.stubrunner.StubFinder import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties +import org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer.StubRunnerLoadBalancerClientFactory +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource import org.springframework.web.client.RestTemplate /** * @author Marcin Grzejszczak @@ -41,6 +44,7 @@ import org.springframework.web.client.RestTemplate //TODO: Document that ribbon.eureka.enabled=false needs to be set or override it somehow @ContextConfiguration(classes = Config, loader = SpringBootContextLoader) @ActiveProfiles("cloudtest") +@TestPropertySource(properties = "stubrunner.cloud.loadbalancer.enabled=false") // tag::autoconfigure[] @AutoConfigureStubRunner( ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", @@ -56,6 +60,8 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification { @Autowired @LoadBalanced RestTemplate restTemplate + @Autowired + LoadBalancerClientFactory loadBalancerClientFactory; @BeforeClass @AfterClass @@ -64,6 +70,10 @@ class StubRunnerSpringCloudAutoConfigurationSpec extends Specification { System.clearProperty("stubrunner.classifier") } + def setup() { + assert !(loadBalancerClientFactory instanceof StubRunnerLoadBalancerClientFactory) + } + // tag::test[] def 'should make service discovery work'() { expect: 'WireMocks are running' diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudNoRibbonAutoConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudNoRibbonAutoConfigurationSpec.groovy new file mode 100644 index 0000000000..14c91af1c9 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudNoRibbonAutoConfigurationSpec.groovy @@ -0,0 +1,96 @@ +/* + * Copyright 2013-2020 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.spring.cloud + +import org.junit.AfterClass +import org.junit.BeforeClass +import spock.lang.Specification + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.context.SpringBootContextLoader +import org.springframework.cloud.client.loadbalancer.LoadBalanced +import org.springframework.cloud.consul.ConsulAutoConfiguration +import org.springframework.cloud.contract.stubrunner.StubFinder +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties +import org.springframework.cloud.contract.stubrunner.spring.cloud.loadbalancer.StubRunnerLoadBalancerClientFactory +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory +import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration +import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.client.RestTemplate +/** + * @author Marcin Grzejszczak + */ +@ContextConfiguration(classes = Config, loader = SpringBootContextLoader) +@ActiveProfiles("cloudtest-no-ribbon") +// tag::autoconfigure[] +@AutoConfigureStubRunner( + ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer", + "org.springframework.cloud.contract.verifier.stubs:bootService"], + stubsMode = StubRunnerProperties.StubsMode.REMOTE, + repositoryRoot = "classpath:m2repo/repository/") +// end::autoconfigure[] +class StubRunnerSpringCloudNoRibbonAutoConfigurationSpec extends Specification { + + @Autowired + StubFinder stubFinder + @Autowired + @LoadBalanced + RestTemplate restTemplate + @Autowired + LoadBalancerClientFactory loadBalancerClientFactory; + + @BeforeClass + @AfterClass + static void setupProps() { + System.clearProperty("stubrunner.repository.root") + System.clearProperty("stubrunner.classifier") + } + + def setup() { + assert loadBalancerClientFactory instanceof StubRunnerLoadBalancerClientFactory + } + + // tag::test[] + def 'should make service discovery work'() { + expect: 'WireMocks are running' + "${stubFinder.findStubUrl('loanIssuance').toString()}/name".toURL().text == 'loanIssuance' + "${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name".toURL().text == 'fraudDetectionServer' + and: 'Stubs can be reached via load service discovery' + restTemplate.getForObject('http://loanIssuance/name', String) == 'loanIssuance' + restTemplate.getForObject('http://someNameThatShouldMapFraudDetectionServer/name', String) == 'fraudDetectionServer' + } + // end::test[] + + @Configuration + @EnableAutoConfiguration(exclude = [EurekaClientAutoConfiguration, + ConsulAutoConfiguration, ZookeeperAutoConfiguration]) + static class Config { + + @Bean + @LoadBalanced + RestTemplate restTemplate() { + return new RestTemplate() + } + } +} diff --git a/spring-cloud-contract-stub-runner/src/test/resources/application-cloudtest-no-ribbon.yml b/spring-cloud-contract-stub-runner/src/test/resources/application-cloudtest-no-ribbon.yml new file mode 100644 index 0000000000..ab511e383a --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/resources/application-cloudtest-no-ribbon.yml @@ -0,0 +1,17 @@ +stubrunner: + cloud.stubbed.discovery.enabled: true +spring.cloud: + zookeeper: + enabled: false + discovery.enabled: false + consul: + enabled: false + discovery.enabled: false + service-registry.enabled: false +eureka.client.enabled: false +ribbon.eureka.enabled: false +spring: + cloud: + loadbalancer: + ribbon: + enabled: false # Use Reactive Load Balancer diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java index 7e4f163440..f50bd394fd 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java @@ -45,8 +45,10 @@ class JaxRsRequestMethodWhen implements When, JaxRsBodyParser { ContentType type = metadata.getInputTestContentType(); String method = request.getMethod().getServerValue().toString().toLowerCase(); if (request.getBody() != null) { - String contentType = StringUtils.hasText(metadata.getDefinedInputTestContentType()) - ? metadata.getDefinedInputTestContentType() : type.getMimeType(); + String contentType = StringUtils + .hasText(metadata.getDefinedInputTestContentType()) + ? metadata.getDefinedInputTestContentType() + : type.getMimeType(); Object body = request.getBody().getServerValue(); String value; if (body instanceof ExecutionProperty) {