From 8a3e80a177f1adfb996a69eb56377c66603c17fe Mon Sep 17 00:00:00 2001 From: Timon Borter Date: Thu, 19 Oct 2023 08:15:44 +0200 Subject: [PATCH] chore: jdk17 cleanup --- .../controller/ScenarioController.java | 59 +++---- .../CorrelationHandlerRegistry.java | 13 +- .../endpoint/SimulatorEndpointPoller.java | 13 +- .../simulator/http/HttpOperationScenario.java | 28 +--- .../HttpRequestAnnotationScenarioMapper.java | 90 +++++------ .../simulator/http/InterceptorHttp.java | 8 +- .../http/SimulatorHttpMessageConverter.java | 10 +- .../http/SimulatorRestAutoConfiguration.java | 48 +++--- .../scenario/AbstractSimulatorScenario.java | 5 +- .../scenario/mapper/ScenarioMappers.java | 4 +- .../service/ScenarioExecutionService.java | 14 +- .../simulator/ws/WsdlScenarioGenerator.java | 150 +++++++++--------- .../HttpRequestAnnotationMatcherTest.java | 2 +- .../scenario/mapper/ScenarioMappersTest.java | 36 ++--- .../template/TemplateHelperTest.java | 6 +- .../simulator/web/rest/MessageResourceIT.java | 6 +- .../web/rest/TestResultResourceIT.java | 3 +- 17 files changed, 246 insertions(+), 249 deletions(-) diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/controller/ScenarioController.java b/simulator-starter/src/main/java/org/citrusframework/simulator/controller/ScenarioController.java index 30563ba46..978fb45e9 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/controller/ScenarioController.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/controller/ScenarioController.java @@ -16,13 +16,17 @@ package org.citrusframework.simulator.controller; +import lombok.Data; +import lombok.NoArgsConstructor; import org.citrusframework.simulator.model.ScenarioParameter; import org.citrusframework.simulator.service.ScenarioExecutionService; import org.citrusframework.simulator.service.ScenarioLookupService; -import lombok.Data; -import lombok.NoArgsConstructor; import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.Collection; @@ -43,17 +47,6 @@ public ScenarioController(ScenarioExecutionService scenarioExecutionService, Sce this.scenarios = getScenarioList(scenarioLookupService); } - @Data - public static class Scenario { - public enum ScenarioType { - STARTER, - MESSAGE_TRIGGERED; - } - - private final String name; - private final ScenarioType type; - } - private static List getScenarioList(ScenarioLookupService scenarioLookupService) { final List scenarios = new ArrayList<>(); scenarioLookupService.getScenarioNames().forEach(name -> scenarios.add(new Scenario(name, Scenario.ScenarioType.MESSAGE_TRIGGERED))); @@ -61,12 +54,6 @@ private static List getScenarioList(ScenarioLookupService scenarioLook return scenarios; } - @Data - @NoArgsConstructor - public static class ScenarioFilter { - private String name; - } - /** * Get a list of scenarios * @@ -76,13 +63,13 @@ public static class ScenarioFilter { @RequestMapping(method = RequestMethod.POST) public Collection getScenarioNames(@RequestBody(required = false) ScenarioFilter filter) { return scenarios.stream() - .filter(scenario -> { - if (filter != null && StringUtils.hasText(filter.getName())) { - return scenario.getName().contains(filter.getName()); - } - return true; - }) - .sorted(Comparator.comparing(Scenario::getName)).toList(); + .filter(scenario -> { + if (filter != null && StringUtils.hasText(filter.getName())) { + return scenario.name().contains(filter.getName()); + } + return true; + }) + .sorted(Comparator.comparing(Scenario::name)).toList(); } /** @@ -104,9 +91,23 @@ public Collection getScenarioParameters(@PathVariable("name") */ @RequestMapping(method = RequestMethod.POST, value = "/launch/{name}") public Long launchScenario( - @PathVariable("name") String name, - @RequestBody(required = false) List scenarioParameters) { + @PathVariable("name") String name, + @RequestBody(required = false) List scenarioParameters) { return scenarioExecutionService.run(name, scenarioParameters); } + public record Scenario(String name, ScenarioController.Scenario.ScenarioType type) { + public enum ScenarioType { + STARTER, + MESSAGE_TRIGGERED + } + + } + + @Data + @NoArgsConstructor + public static class ScenarioFilter { + private String name; + } + } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/correlation/CorrelationHandlerRegistry.java b/simulator-starter/src/main/java/org/citrusframework/simulator/correlation/CorrelationHandlerRegistry.java index b2a10aea1..24b681486 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/correlation/CorrelationHandlerRegistry.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/correlation/CorrelationHandlerRegistry.java @@ -16,19 +16,18 @@ public class CorrelationHandlerRegistry { /** * Map of active handlers */ - private ConcurrentMap registeredHandlers = new ConcurrentHashMap<>(); - - /** - * Maximum capacity of active tests - */ - private int queueCapacity = 1000; + private final ConcurrentMap registeredHandlers = new ConcurrentHashMap<>(); /** * Add new correlation manager to registry. * @param handler */ public void register(CorrelationHandler handler, TestContext context) { - if (!registeredHandlers.keySet().contains(handler)) { + register(handler, context, 1000); + } + + public void register(CorrelationHandler handler, TestContext context, int queueCapacity) { + if (!registeredHandlers.containsKey(handler)) { registeredHandlers.put(handler, context); } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/endpoint/SimulatorEndpointPoller.java b/simulator-starter/src/main/java/org/citrusframework/simulator/endpoint/SimulatorEndpointPoller.java index 6ebe85823..86d6f9c40 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/endpoint/SimulatorEndpointPoller.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/endpoint/SimulatorEndpointPoller.java @@ -16,6 +16,7 @@ package org.citrusframework.simulator.endpoint; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.citrusframework.context.TestContext; import org.citrusframework.context.TestContextFactory; import org.citrusframework.endpoint.Endpoint; @@ -26,7 +27,6 @@ import org.citrusframework.messaging.Producer; import org.citrusframework.messaging.ReplyProducer; import org.citrusframework.simulator.exception.SimulatorException; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; @@ -35,7 +35,12 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; -import java.util.concurrent.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * @author Christoph Deppisch @@ -186,14 +191,14 @@ public void stop() { } @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { if (autoStart) { start(); } } @Override - public void destroy() throws Exception { + public void destroy() { stop(); } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpOperationScenario.java b/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpOperationScenario.java index 6b54d6f08..d84514d15 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpOperationScenario.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpOperationScenario.java @@ -92,36 +92,24 @@ public void run(ScenarioRunner scenario) { scenario.name(operation.getOperationId()); scenario.$(echo("Generated scenario from swagger operation: " + operation.getOperationId())); - HttpServerRequestActionBuilder requestBuilder; - switch (method) { - case GET: - requestBuilder = scenario.http() + HttpServerRequestActionBuilder requestBuilder = switch (method) { + case GET -> scenario.http() .receive() .get(); - break; - case POST: - requestBuilder = scenario.http() + case POST -> scenario.http() .receive() .post(); - break; - case PUT: - requestBuilder = scenario.http() + case PUT -> scenario.http() .receive() .put(); - break; - case HEAD: - requestBuilder = scenario.http() + case HEAD -> scenario.http() .receive() .head(); - break; - case DELETE: - requestBuilder = scenario.http() + case DELETE -> scenario.http() .receive() .delete(); - break; - default: - throw new SimulatorException("Unsupported request method: " + method.name()); - } + default -> throw new SimulatorException("Unsupported request method: " + method.name()); + }; requestBuilder .message() diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpRequestAnnotationScenarioMapper.java b/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpRequestAnnotationScenarioMapper.java index 71339e3e2..598b2c1da 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpRequestAnnotationScenarioMapper.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/http/HttpRequestAnnotationScenarioMapper.java @@ -16,10 +16,8 @@ package org.citrusframework.simulator.http; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - +import jakarta.annotation.Nullable; +import lombok.Builder; import org.citrusframework.http.message.HttpMessage; import org.citrusframework.message.Message; import org.citrusframework.simulator.config.SimulatorConfigurationProperties; @@ -27,12 +25,14 @@ import org.citrusframework.simulator.scenario.ScenarioListAware; import org.citrusframework.simulator.scenario.SimulatorScenario; import org.citrusframework.simulator.scenario.mapper.AbstractScenarioMapper; -import lombok.Builder; -import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.web.bind.annotation.RequestMapping; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + /** * Scenario mapper performs mapping logic on request mapping annotations on given scenarios. Scenarios match on request method as well as * request path pattern matching. @@ -41,11 +41,11 @@ */ public class HttpRequestAnnotationScenarioMapper extends AbstractScenarioMapper implements ScenarioListAware { - @Autowired(required = false) - private List scenarioList = new ArrayList<>(); - private final HttpRequestAnnotationMatcher httpRequestAnnotationMatcher = HttpRequestAnnotationMatcher.instance(); + @Autowired(required = false) + private @Nullable List scenarioList; + @Override protected String getMappingKey(Message request) { if (request instanceof HttpMessage) { @@ -55,48 +55,37 @@ protected String getMappingKey(Message request) { return super.getMappingKey(request); } - @Data - @Builder - private static final class EnrichedScenarioWithRequestMapping { - final SimulatorScenario scenario; - final RequestMapping requestMapping; - - public boolean hasRequestMapping() { - return requestMapping != null; - } - - public String name() { - return scenario.getClass().getAnnotation(Scenario.class).value(); - } - } - protected String getMappingKeyForHttpMessage(HttpMessage httpMessage) { - Optional mapping = scenarioList.stream() + List nullSafeList = Optional.ofNullable(scenarioList).orElse(Collections.emptyList()); + + // First look for exact match + Optional mapping = nullSafeList.stream() + .map(scenario -> EnrichedScenarioWithRequestMapping.builder() + .scenario(scenario) + .requestMapping(AnnotationUtils.findAnnotation(scenario.getClass(), RequestMapping.class)) + .build() + ) + .filter(EnrichedScenarioWithRequestMapping::hasRequestMapping) + .filter(swrm -> httpRequestAnnotationMatcher.checkRequestPathSupported(httpMessage, swrm.requestMapping(), true)) + .filter(swrm -> httpRequestAnnotationMatcher.checkRequestMethodSupported(httpMessage, swrm.requestMapping())) + .filter(swrm -> httpRequestAnnotationMatcher.checkRequestQueryParamsSupported(httpMessage, swrm.requestMapping())) + .map(EnrichedScenarioWithRequestMapping::name) + .findFirst(); + + // If that didn't help, look for inecaxt match + if (mapping.isEmpty()) { + mapping = nullSafeList.stream() .map(scenario -> EnrichedScenarioWithRequestMapping.builder() - .scenario(scenario) - .requestMapping(AnnotationUtils.findAnnotation(scenario.getClass(), RequestMapping.class)) - .build() + .scenario(scenario) + .requestMapping(AnnotationUtils.findAnnotation(scenario.getClass(), RequestMapping.class)) + .build() ) .filter(EnrichedScenarioWithRequestMapping::hasRequestMapping) - .filter(swrm -> httpRequestAnnotationMatcher.checkRequestPathSupported(httpMessage, swrm.getRequestMapping(), true)) - .filter(swrm -> httpRequestAnnotationMatcher.checkRequestMethodSupported(httpMessage, swrm.getRequestMapping())) - .filter(swrm -> httpRequestAnnotationMatcher.checkRequestQueryParamsSupported(httpMessage, swrm.getRequestMapping())) + .filter(swrm -> httpRequestAnnotationMatcher.checkRequestPathSupported(httpMessage, swrm.requestMapping(), false)) + .filter(swrm -> httpRequestAnnotationMatcher.checkRequestMethodSupported(httpMessage, swrm.requestMapping())) + .filter(swrm -> httpRequestAnnotationMatcher.checkRequestQueryParamsSupported(httpMessage, swrm.requestMapping())) .map(EnrichedScenarioWithRequestMapping::name) .findFirst(); - - if (!mapping.isPresent()) { - mapping = scenarioList.stream() - .map(scenario -> EnrichedScenarioWithRequestMapping.builder() - .scenario(scenario) - .requestMapping(AnnotationUtils.findAnnotation(scenario.getClass(), RequestMapping.class)) - .build() - ) - .filter(EnrichedScenarioWithRequestMapping::hasRequestMapping) - .filter(swrm -> httpRequestAnnotationMatcher.checkRequestPathSupported(httpMessage, swrm.getRequestMapping(), false)) - .filter(swrm -> httpRequestAnnotationMatcher.checkRequestMethodSupported(httpMessage, swrm.getRequestMapping())) - .filter(swrm -> httpRequestAnnotationMatcher.checkRequestQueryParamsSupported(httpMessage, swrm.getRequestMapping())) - .map(EnrichedScenarioWithRequestMapping::name) - .findFirst(); } return mapping.orElseGet(() -> super.getMappingKey(httpMessage)); @@ -142,4 +131,15 @@ public SimulatorConfigurationProperties getConfiguration() { public void setConfiguration(SimulatorConfigurationProperties configuration) { this.setSimulatorConfigurationProperties(configuration); } + + @Builder + private record EnrichedScenarioWithRequestMapping(SimulatorScenario scenario, RequestMapping requestMapping) { + public boolean hasRequestMapping() { + return requestMapping != null; + } + + public String name() { + return scenario.getClass().getAnnotation(Scenario.class).value(); + } + } } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/http/InterceptorHttp.java b/simulator-starter/src/main/java/org/citrusframework/simulator/http/InterceptorHttp.java index f7cd0ba8e..3aef60f04 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/http/InterceptorHttp.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/http/InterceptorHttp.java @@ -16,6 +16,8 @@ package org.citrusframework.simulator.http; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.citrusframework.http.controller.HttpMessageController; import org.citrusframework.message.RawMessage; import org.citrusframework.report.MessageListeners; @@ -25,8 +27,6 @@ import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; /** @@ -50,14 +50,14 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons } @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { if (messageListeners != null) { messageListeners.onOutboundMessage(new RawMessage(getResponseContent(request, response, handler)), null); } } @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorHttpMessageConverter.java b/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorHttpMessageConverter.java index ae6e67d99..d0bb479b8 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorHttpMessageConverter.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorHttpMessageConverter.java @@ -1,9 +1,5 @@ package org.citrusframework.simulator.http; -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.List; - import org.citrusframework.http.controller.HttpMessageController; import org.citrusframework.http.message.DelegatingHttpEntityMessageConverter; import org.springframework.http.HttpInputMessage; @@ -13,6 +9,10 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.List; + /** * Special generic message converter only applies to {@link HttpMessageController} context class when reading data. * If context class is different than that default Spring internal message converters should apply. This makes sure that all @@ -63,7 +63,7 @@ public List getSupportedMediaTypes() { } @Override - public Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { + public Object read(Class clazz, HttpInputMessage inputMessage) throws HttpMessageNotReadableException { throw new IllegalStateException("Illegal read operation on simulator message converter."); } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorRestAutoConfiguration.java b/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorRestAutoConfiguration.java index 49522701b..f6d91e8e5 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorRestAutoConfiguration.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/http/SimulatorRestAutoConfiguration.java @@ -18,12 +18,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.citrusframework.endpoint.EndpointAdapter; import org.citrusframework.endpoint.adapter.EmptyResponseEndpointAdapter; import org.citrusframework.http.controller.HttpMessageController; @@ -34,6 +28,7 @@ import org.citrusframework.simulator.SimulatorAutoConfiguration; import org.citrusframework.simulator.endpoint.SimulatorEndpointAdapter; import org.citrusframework.simulator.listener.SimulatorMessageListener; +import org.citrusframework.simulator.scenario.SimulatorScenario; import org.citrusframework.simulator.scenario.mapper.ScenarioMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -56,6 +51,12 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * @author Christoph Deppisch */ @@ -117,21 +118,7 @@ public HandlerMapping simulatorRestHandlerMapping(ApplicationContext application @Bean public HandlerAdapter simulatorRestHandlerAdapter(final ApplicationContext applicationContext) { - final RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping() { - @Override - protected void initHandlerMethods() { - detectHandlerMethods(createRestController(applicationContext)); - super.initHandlerMethods(); - } - - @Override - protected boolean isHandler(Class beanType) { - return (beanType.isAssignableFrom(HttpMessageController.class)) && super.isHandler(beanType); - } - }; - - handlerMapping.setApplicationContext(applicationContext); - handlerMapping.afterPropertiesSet(); + final RequestMappingHandlerMapping handlerMapping = getRequestMappingHandlerMapping(applicationContext); requestMappingHandlerAdapter.getMessageConverters().add(0, new SimulatorHttpMessageConverter()); requestMappingHandlerAdapter.getMessageConverters().add(new DelegatingHttpEntityMessageConverter()); @@ -150,6 +137,25 @@ public ModelAndView handle(HttpServletRequest request, HttpServletResponse respo }; } + private RequestMappingHandlerMapping getRequestMappingHandlerMapping(ApplicationContext applicationContext) { + final RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping() { + @Override + protected void initHandlerMethods() { + detectHandlerMethods(createRestController(applicationContext)); + super.initHandlerMethods(); + } + + @Override + protected boolean isHandler(Class beanType) { + return (beanType.isAssignableFrom(HttpMessageController.class)) && super.isHandler(beanType); + } + }; + + handlerMapping.setApplicationContext(applicationContext); + handlerMapping.afterPropertiesSet(); + return handlerMapping; + } + @Bean public SimulatorEndpointAdapter simulatorRestEndpointAdapter() { return new SimulatorEndpointAdapter(); diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/AbstractSimulatorScenario.java b/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/AbstractSimulatorScenario.java index 28ff78058..5b93117fa 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/AbstractSimulatorScenario.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/AbstractSimulatorScenario.java @@ -16,11 +16,10 @@ package org.citrusframework.simulator.scenario; +import jakarta.annotation.PostConstruct; import org.citrusframework.simulator.correlation.CorrelationHandler; import org.citrusframework.simulator.correlation.CorrelationHandlerBuilder; -import jakarta.annotation.PostConstruct; - /** * @author Christoph Deppisch */ @@ -32,7 +31,7 @@ public abstract class AbstractSimulatorScenario implements SimulatorScenario, Co private ScenarioEndpoint scenarioEndpoint; @PostConstruct - public void init() throws Exception { + public void init() { scenarioEndpoint = new ScenarioEndpoint(new ScenarioEndpointConfiguration()); } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappers.java b/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappers.java index 7906a87e7..c6962c97b 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappers.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappers.java @@ -16,13 +16,13 @@ package org.citrusframework.simulator.scenario.mapper; +import io.swagger.models.Operation; import org.citrusframework.message.Message; import org.citrusframework.simulator.config.SimulatorConfigurationPropertiesAware; import org.citrusframework.simulator.http.HttpOperationScenario; import org.citrusframework.simulator.scenario.Scenario; import org.citrusframework.simulator.scenario.ScenarioListAware; import org.citrusframework.simulator.scenario.SimulatorScenario; -import io.swagger.models.Operation; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.AnnotationUtils; @@ -99,7 +99,7 @@ public String getMappingKey(Message message) { } @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { scenarioMapperList.stream() .filter(mapper -> mapper instanceof ScenarioListAware) .map(mapper -> (ScenarioListAware) mapper) diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionService.java b/simulator-starter/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionService.java index 08bfb70b1..8a4f0e5be 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionService.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionService.java @@ -16,12 +16,6 @@ package org.citrusframework.simulator.service; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; - import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.citrusframework.Citrus; import org.citrusframework.annotations.CitrusAnnotations; @@ -42,6 +36,12 @@ import org.springframework.stereotype.Service; import org.springframework.util.ReflectionUtils; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; + /** * Service capable of executing test executables. The service takes care on setting up the executable before execution. Service * gets a list of normalized parameters which has to be translated to setters on the test executable instance before execution. @@ -155,7 +155,7 @@ protected void prepare(SimulatorScenario scenario) { } @Override - public void destroy() throws Exception { + public void destroy() { executorService.shutdownNow(); } diff --git a/simulator-starter/src/main/java/org/citrusframework/simulator/ws/WsdlScenarioGenerator.java b/simulator-starter/src/main/java/org/citrusframework/simulator/ws/WsdlScenarioGenerator.java index 05abb6fec..c7e7c5088 100644 --- a/simulator-starter/src/main/java/org/citrusframework/simulator/ws/WsdlScenarioGenerator.java +++ b/simulator-starter/src/main/java/org/citrusframework/simulator/ws/WsdlScenarioGenerator.java @@ -1,19 +1,5 @@ package org.citrusframework.simulator.ws; -import javax.wsdl.Binding; -import javax.wsdl.BindingOperation; -import javax.wsdl.Definition; -import javax.wsdl.WSDLException; -import javax.wsdl.extensions.ExtensibilityElement; -import javax.wsdl.extensions.soap.SOAPOperation; -import javax.wsdl.factory.WSDLFactory; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.citrusframework.exceptions.CitrusRuntimeException; -import org.citrusframework.simulator.exception.SimulatorException; -import org.citrusframework.xml.schema.locator.JarWSDLLocator; import org.apache.xmlbeans.SchemaType; import org.apache.xmlbeans.SchemaTypeSystem; import org.apache.xmlbeans.XmlBeans; @@ -22,6 +8,9 @@ import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.impl.xsd2inst.SampleXmlUtil; +import org.citrusframework.exceptions.CitrusRuntimeException; +import org.citrusframework.simulator.exception.SimulatorException; +import org.citrusframework.xml.schema.locator.JarWSDLLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; @@ -36,32 +25,39 @@ import org.springframework.util.StringUtils; import org.xml.sax.InputSource; +import javax.wsdl.Binding; +import javax.wsdl.BindingOperation; +import javax.wsdl.Definition; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensibilityElement; +import javax.wsdl.extensions.soap.SOAPOperation; +import javax.wsdl.factory.WSDLFactory; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + /** * @author Christoph Deppisch */ public class WsdlScenarioGenerator implements BeanFactoryPostProcessor { - /** Logger */ - private static Logger log = LoggerFactory.getLogger(WsdlScenarioGenerator.class); - - /** Target wsdl to generate scenarios from */ - private final Resource wsdlResource; - - /** Naming strategy for generated scenarios */ - private WsdlScenarioNamingStrategy namingStrategy = WsdlScenarioNamingStrategy.INPUT; - - /** Optional WSDL file location system property for auto generated scenarios */ + /** + * Optional WSDL file location system property for auto generated scenarios + */ private static final String SIMULATOR_WSDL_LOCATION_PROPERTY = "citrus.simulator.ws.wsdl.location"; private static final String SIMULATOR_WSDL_LOCATION_ENV = "CITRUS_SIMULATOR_WS_WSDL_LOCATION"; - /** - * Enum representing different kinds of scenario naming. + * Logger */ - public enum WsdlScenarioNamingStrategy { - INPUT, - OPERATION, - SOAP_ACTION - } + private static final Logger log = LoggerFactory.getLogger(WsdlScenarioGenerator.class); + /** + * Target wsdl to generate scenarios from + */ + private final Resource wsdlResource; + /** + * Naming strategy for generated scenarios + */ + private WsdlScenarioNamingStrategy namingStrategy = WsdlScenarioNamingStrategy.INPUT; /** * Default constructor. @@ -72,16 +68,31 @@ public WsdlScenarioGenerator(Environment environment) { /** * Constructor using wsdl file resource. + * * @param wsdlResource */ public WsdlScenarioGenerator(Resource wsdlResource) { this.wsdlResource = wsdlResource; } + private static String getSoapAction(BindingOperation operation) { + String soapAction = ""; + List extensions = operation.getExtensibilityElements(); + if (extensions != null) { + for (Object extension : extensions) { + ExtensibilityElement extElement = (ExtensibilityElement) extension; + if (extElement instanceof SOAPOperation soapOperation) { + soapAction = soapOperation.getSoapActionURI(); + } + } + } + return soapAction; + } + @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Assert.notNull(wsdlResource, - "Missing either WSDL location system property setting or explicit WSDL resource for scenario auto generation"); + "Missing either WSDL location system property setting or explicit WSDL resource for scenario auto generation"); Definition wsdl = getWsdlDefinition(wsdlResource); XmlObject wsdlObject = compileWsdl(wsdlResource); @@ -96,39 +107,20 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) SchemaType requestElem = getSchemaType(schemaTypeSystem, operation.getName(), operation.getOperation().getInput().getName()); SchemaType responseElem = getSchemaType(schemaTypeSystem, operation.getName(), operation.getOperation().getOutput().getName()); - String soapAction = ""; - List extensions = operation.getExtensibilityElements(); - if (extensions != null) { - for (Object extension : extensions) { - ExtensibilityElement extElement = (ExtensibilityElement) extension; - if (extElement instanceof SOAPOperation soapOperation) { - soapAction = soapOperation.getSoapActionURI(); - } - } - } - - String scenarioName; - switch (namingStrategy) { - case INPUT: - scenarioName = operation.getOperation().getInput().getName(); - break; - case OPERATION: - scenarioName = operation.getOperation().getName(); - break; - case SOAP_ACTION: - scenarioName = soapAction; - break; - default: - throw new SimulatorException("Unknown scenario naming strategy"); - } + String soapAction = getSoapAction(operation); + String scenarioName = switch (namingStrategy) { + case INPUT -> operation.getOperation().getInput().getName(); + case OPERATION -> operation.getOperation().getName(); + case SOAP_ACTION -> soapAction; + }; if (beanFactory instanceof BeanDefinitionRegistry) { log.info("Register auto generated scenario as bean definition: " + scenarioName); BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(WsdlOperationScenario.class) - .addConstructorArgValue(operation) - .addPropertyValue("soapAction", soapAction) - .addPropertyValue("input", generateRequest(operation, SampleXmlUtil.createSampleForType(requestElem))) - .addPropertyValue("output", generateResponse(operation, SampleXmlUtil.createSampleForType(responseElem))); + .addConstructorArgValue(operation) + .addPropertyValue("soapAction", soapAction) + .addPropertyValue("input", generateRequest(operation, SampleXmlUtil.createSampleForType(requestElem))) + .addPropertyValue("output", generateResponse(operation, SampleXmlUtil.createSampleForType(responseElem))); if (beanFactory.containsBeanDefinition("inboundXmlDataDictionary")) { beanDefinitionBuilder.addPropertyReference("inboundDataDictionary", "inboundXmlDataDictionary"); @@ -150,6 +142,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) /** * Creates the scenario with given WSDL operation information. + * * @param operation * @param soapAction * @param input @@ -158,13 +151,14 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) */ protected WsdlOperationScenario createScenario(BindingOperation operation, String soapAction, String input, String output) { return new WsdlOperationScenario(operation) - .withInput(input) - .withOutput(output) - .withSoapAction(soapAction); + .withInput(input) + .withOutput(output) + .withSoapAction(soapAction); } /** * Generates request body. Subclasses may add special request body generating logic here. + * * @param operation * @param body * @return @@ -175,6 +169,7 @@ protected String generateRequest(BindingOperation operation, String body) { /** * Generates response body. Subclasses may add special response body generating logic here. + * * @param operation * @param body * @return @@ -197,11 +192,12 @@ private SchemaType getSchemaType(SchemaTypeSystem schemaTypeSystem, String opera } throw new SimulatorException("Unable to find schema type declaration '" + elementName + "'" + - " for WSDL operation '" + operation + "'"); + " for WSDL operation '" + operation + "'"); } /** * Reads WSDL definition from resource. + * * @param wsdl * @return * @throws IOException @@ -227,6 +223,7 @@ private Definition getWsdlDefinition(Resource wsdl) { /** * Compiles WSDL file resource to a XmlObject. + * * @return * @throws IOException */ @@ -235,7 +232,7 @@ private XmlObject compileWsdl(Resource wsdlResource) { return XmlObject.Factory.parse(wsdlResource.getInputStream(), (new XmlOptions()).setLoadLineNumbers().setLoadMessageDigest().setCompileDownloadUrls()); } catch (XmlException e) { for (Object error : e.getErrors()) { - log.error(((XmlError)error).getLine() + "" + error.toString()); + log.error(((XmlError) error).getLine() + String.valueOf(error)); } throw new SimulatorException("WSDL could not be parsed", e); } catch (Exception e) { @@ -245,6 +242,7 @@ private XmlObject compileWsdl(Resource wsdlResource) { /** * Finds nested XML schema definition and compiles it to a schema type system instance. + * * @param wsdl * @return */ @@ -257,7 +255,7 @@ private SchemaTypeSystem compileXsd(XmlObject wsdl) { XmlObject[] xsd = new XmlObject[schemas.length]; try { - for (int i=0; i < schemas.length; i++) { + for (int i = 0; i < schemas.length; i++) { xsd[i] = XmlObject.Factory.parse(schemas[i], (new XmlOptions()).setLoadLineNumbers().setLoadMessageDigest().setCompileDownloadUrls()); } } catch (Exception e) { @@ -269,7 +267,7 @@ private SchemaTypeSystem compileXsd(XmlObject wsdl) { schemaTypeSystem = XmlBeans.compileXsd(xsd, XmlBeans.getContextTypeLoader(), new XmlOptions()); } catch (XmlException e) { for (Object error : e.getErrors()) { - log.error("Line " + ((XmlError)error).getLine() + ": " + error.toString()); + log.error("Line " + ((XmlError) error).getLine() + ": " + error); } throw new SimulatorException("Failed to compile XSD schema", e); } catch (Exception e) { @@ -290,7 +288,7 @@ private String[] extractNamespacesOnWsdlLevel(XmlObject wsdl) { int noNs = StringUtils.countOccurrencesOf(nsWsdlOrig, "xmlns:"); String[] namespacesWsdl = new String[noNs]; cursor = 0; - for (int i=0; i checkRequestPathSupported() { @MethodSource @ParameterizedTest - void checkRequestPathSupported(RequestMapping requestMapping, HttpMessage httpMessage, boolean exactMatch, boolean expectedResult) throws Exception { + void checkRequestPathSupported(RequestMapping requestMapping, HttpMessage httpMessage, boolean exactMatch, boolean expectedResult) { boolean actual = fixture.checkRequestPathSupported(httpMessage, requestMapping, exactMatch) && fixture.checkRequestMethodSupported(httpMessage, requestMapping) && fixture.checkRequestQueryParamsSupported(httpMessage, requestMapping); diff --git a/simulator-starter/src/test/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappersTest.java b/simulator-starter/src/test/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappersTest.java index e2a0233f1..708672775 100644 --- a/simulator-starter/src/test/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappersTest.java +++ b/simulator-starter/src/test/java/org/citrusframework/simulator/scenario/mapper/ScenarioMappersTest.java @@ -16,9 +16,6 @@ package org.citrusframework.simulator.scenario.mapper; -import java.util.Arrays; -import java.util.Optional; - import org.citrusframework.exceptions.CitrusRuntimeException; import org.citrusframework.http.message.HttpMessage; import org.citrusframework.message.DefaultMessage; @@ -33,6 +30,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import java.util.Arrays; +import java.util.Optional; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -44,12 +44,12 @@ class ScenarioMappersTest { private static final String DEFAULT_SCENARIO = "default"; @Test - void testMappingChain() throws Exception { + void testMappingChain() { ScenarioMappers mapperChain = ScenarioMappers.of(new HeaderMapper("foo"), - new ContentBasedXPathScenarioMapper().addXPathExpression("/foo"), - new ContentBasedJsonPathScenarioMapper().addJsonPathExpression("$.foo"), - new HttpRequestPathScenarioMapper(), - new HttpRequestAnnotationScenarioMapper(), + new ContentBasedXPathScenarioMapper().addXPathExpression("/foo"), + new ContentBasedJsonPathScenarioMapper().addJsonPathExpression("$.foo"), + new HttpRequestPathScenarioMapper(), + new HttpRequestAnnotationScenarioMapper(), new HeaderMapper("bar")); SimulatorConfigurationProperties configurationProperties = new SimulatorConfigurationProperties(); @@ -63,9 +63,9 @@ void testMappingChain() throws Exception { assertEquals(mapperChain.getMappingKey(new DefaultMessage("foo").setHeader("foo", "something")), DEFAULT_SCENARIO); assertEquals(mapperChain.getMappingKey(new DefaultMessage().setHeader("foo", FooScenario.SCENARIO_NAME)), FooScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new DefaultMessage().setHeader("foo", FooScenario.SCENARIO_NAME) - .setHeader("bar", BarScenario.SCENARIO_NAME)), FooScenario.SCENARIO_NAME); + .setHeader("bar", BarScenario.SCENARIO_NAME)), FooScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new DefaultMessage().setHeader("foo", "something") - .setHeader("bar", BarScenario.SCENARIO_NAME)), BarScenario.SCENARIO_NAME); + .setHeader("bar", BarScenario.SCENARIO_NAME)), BarScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new DefaultMessage().setHeader("bar", BarScenario.SCENARIO_NAME)), BarScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new HttpMessage().path("/other").method(HttpMethod.GET).setHeader("foo", FooScenario.SCENARIO_NAME)), FooScenario.SCENARIO_NAME); @@ -74,12 +74,12 @@ void testMappingChain() throws Exception { assertEquals(mapperChain.getMappingKey(new DefaultMessage("{ \"foo\": \"something\" }")), DEFAULT_SCENARIO); assertEquals(mapperChain.getMappingKey(new DefaultMessage("{ \"foo\": \"something\" }")), DEFAULT_SCENARIO); - assertEquals(mapperChain.getMappingKey(new DefaultMessage("{ \"bar\": \"" + FooScenario.SCENARIO_NAME + "\" }")), DEFAULT_SCENARIO); + assertEquals(mapperChain.getMappingKey(new DefaultMessage("{ \"bar\": \"" + FooScenario.SCENARIO_NAME + "\" }")), DEFAULT_SCENARIO); assertEquals(mapperChain.getMappingKey(new DefaultMessage("{ \"foo\": \"" + FooScenario.SCENARIO_NAME + "\" }")), FooScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new HttpMessage("{ \"foo\": \"" + FooScenario.SCENARIO_NAME + "\" }").path("/other").method(HttpMethod.GET)), FooScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new DefaultMessage("something")), DEFAULT_SCENARIO); - assertEquals(mapperChain.getMappingKey(new DefaultMessage("" + FooScenario.SCENARIO_NAME + "")), DEFAULT_SCENARIO); + assertEquals(mapperChain.getMappingKey(new DefaultMessage("" + FooScenario.SCENARIO_NAME + "")), DEFAULT_SCENARIO); assertEquals(mapperChain.getMappingKey(new DefaultMessage("" + FooScenario.SCENARIO_NAME + "")), FooScenario.SCENARIO_NAME); assertEquals(mapperChain.getMappingKey(new HttpMessage("" + FooScenario.SCENARIO_NAME + "").path("/other").method(HttpMethod.GET)), FooScenario.SCENARIO_NAME); @@ -103,19 +103,13 @@ void testDefaultMapping() { assertThrows(CitrusRuntimeException.class, () -> mapperChain.getMappingKey(new DefaultMessage())); } - private static class HeaderMapper implements ScenarioMapper { - - private final String name; - - private HeaderMapper(String name) { - this.name = name; - } + private record HeaderMapper(String name) implements ScenarioMapper { @Override public String extractMappingKey(Message request) { return Optional.ofNullable(request.getHeader(name)) - .map(Object::toString) - .orElseThrow(CitrusRuntimeException::new); + .map(Object::toString) + .orElseThrow(CitrusRuntimeException::new); } } diff --git a/simulator-starter/src/test/java/org/citrusframework/simulator/template/TemplateHelperTest.java b/simulator-starter/src/test/java/org/citrusframework/simulator/template/TemplateHelperTest.java index dc1f41e13..152e53924 100644 --- a/simulator-starter/src/test/java/org/citrusframework/simulator/template/TemplateHelperTest.java +++ b/simulator-starter/src/test/java/org/citrusframework/simulator/template/TemplateHelperTest.java @@ -30,7 +30,7 @@ static Stream getFileResource() { @MethodSource @ParameterizedTest - void getFileResource(String basePath, String fileName, String fileExtension, boolean shouldExist) throws Exception { + void getFileResource(String basePath, String fileName, String fileExtension, boolean shouldExist) { final TemplateHelper testling = TemplateHelper.instance(basePath, UTF_8); final Resource fileResource = testling.getFileResource(fileName, fileExtension); @@ -51,7 +51,7 @@ static Stream getXmlMessageTemplate() { @MethodSource @ParameterizedTest - void getXmlMessageTemplate(String basePath, String fileName, String expectedContent) throws Exception { + void getXmlMessageTemplate(String basePath, String fileName, String expectedContent) { final TemplateHelper testling = TemplateHelper.instance(basePath, UTF_8); try { final String content = testling.getXmlMessageTemplate(fileName); @@ -75,7 +75,7 @@ static Stream getJsonMessageTemplate() { @MethodSource @ParameterizedTest - void getJsonMessageTemplate(String basePath, String fileName, String expectedContent) throws Exception { + void getJsonMessageTemplate(String basePath, String fileName, String expectedContent) { final TemplateHelper testling = TemplateHelper.instance(basePath, UTF_8); try { final String content = testling.getJsonMessageTemplate(fileName); diff --git a/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java b/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java index 1f2b510ce..e0cb69dce 100644 --- a/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java +++ b/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java @@ -69,14 +69,13 @@ class MessageResourceIT { * if they test an entity which requires the current entity. */ public static Message createEntity(EntityManager entityManager) { - Message message = Message.builder() + return Message.builder() .direction(DEFAULT_DIRECTION) .payload(DEFAULT_PAYLOAD) .citrusMessageId(DEFAULT_CITRUS_MESSAGE_ID) .createdDate(DEFAULT_CREATED_DATE) .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE) .build(); - return message; } /** @@ -86,14 +85,13 @@ public static Message createEntity(EntityManager entityManager) { * if they test an entity which requires the current entity. */ public static Message createUpdatedEntity(EntityManager entityManager) { - Message message = Message.builder() + return Message.builder() .direction(UPDATED_DIRECTION) .payload(UPDATED_PAYLOAD) .citrusMessageId(UPDATED_CITRUS_MESSAGE_ID) .createdDate(UPDATED_CREATED_DATE) .lastModifiedDate(UPDATED_LAST_MODIFIED_DATE) .build(); - return message; } @BeforeEach diff --git a/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/TestResultResourceIT.java b/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/TestResultResourceIT.java index d4c1a4e9e..cde75bb60 100644 --- a/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/TestResultResourceIT.java +++ b/simulator-starter/src/test/java/org/citrusframework/simulator/web/rest/TestResultResourceIT.java @@ -79,7 +79,7 @@ class TestResultResourceIT { * if they test an entity which requires the current entity. */ public static TestResult createEntity(EntityManager entityManager) { - TestResult testResult = TestResult.builder() + return TestResult.builder() .status(DEFAULT_STATUS.getId()) .testName(DEFAULT_TEST_NAME) .className(DEFAULT_CLASS_NAME) @@ -89,7 +89,6 @@ public static TestResult createEntity(EntityManager entityManager) { .createdDate(DEFAULT_CREATED_DATE) .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE) .build(); - return testResult; } @BeforeEach