nokReport = new HashSet<>();
nokReport.add(new ValidationMessage.Builder().customMessage(
- "This is a simulated validation error message").build());
+ "This is a simulated validation error message").build());
when(schemaMock.validate(any())).thenReturn(nokReport);
return jsonSchemaMock;
}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/GetPetByIdIT.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/GetPetByIdIT.java
index 72b9369ca3..fc37512b03 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/GetPetByIdIT.java
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/GetPetByIdIT.java
@@ -1,254 +1,154 @@
package org.citrusframework.openapi.generator;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.citrusframework.container.Assert.Builder.assertException;
-import static org.citrusframework.util.FileUtils.readToString;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
import org.citrusframework.TestCaseRunner;
import org.citrusframework.annotations.CitrusResource;
import org.citrusframework.annotations.CitrusTest;
import org.citrusframework.config.CitrusSpringConfig;
import org.citrusframework.context.TestContext;
-import org.citrusframework.endpoint.EndpointConfiguration;
import org.citrusframework.http.client.HttpClient;
-import org.citrusframework.http.client.HttpEndpointConfiguration;
-import org.citrusframework.junit.jupiter.spring.CitrusSpringExtension;
-import org.citrusframework.message.DefaultMessage;
+import org.citrusframework.http.client.HttpClientBuilder;
+import org.citrusframework.http.server.HttpServer;
+import org.citrusframework.http.server.HttpServerBuilder;
+import org.citrusframework.junit.jupiter.spring.CitrusSpringSupport;
import org.citrusframework.message.Message;
-import org.citrusframework.messaging.Producer;
-import org.citrusframework.messaging.SelectiveConsumer;
-import org.citrusframework.openapi.generator.GetPetByIdIT.Config;
-import org.citrusframework.openapi.generator.rest.petstore.request.PetApi.GetPetByIdRequest;
import org.citrusframework.openapi.generator.rest.petstore.spring.PetStoreBeanConfiguration;
-import org.citrusframework.spi.Resources;
-import org.junit.jupiter.api.BeforeEach;
+import org.citrusframework.util.SocketUtils;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.http.HttpStatus;
+import org.springframework.test.context.ContextConfiguration;
-@ExtendWith(CitrusSpringExtension.class)
-@SpringBootTest(classes = {PetStoreBeanConfiguration.class, CitrusSpringConfig.class, Config.class})
-class GetPetByIdIT {
+import java.io.File;
- @Autowired
- private GetPetByIdRequest getPetByIdRequest;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.citrusframework.http.actions.HttpActionBuilder.http;
+import static org.citrusframework.message.MessageType.JSON;
+import static org.citrusframework.openapi.generator.rest.petstore.request.PetApi.openapiPetstore;
+import static org.citrusframework.validation.PathExpressionValidationContext.Builder.pathExpression;
+import static org.springframework.http.HttpStatus.NO_CONTENT;
+import static org.springframework.http.HttpStatus.OK;
- @Autowired
- @Qualifier("petStoreEndpoint")
- private HttpClient httpClient;
- private String defaultResponse;
+@CitrusSpringSupport
+@ContextConfiguration(classes = {PetStoreBeanConfiguration.class, CitrusSpringConfig.class, GetPetByIdIT.Config.class})
+class GetPetByIdIT {
- @BeforeEach
- public void beforeTest() throws IOException {
- defaultResponse = readToString(Resources.create(
- "org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json"),
- StandardCharsets.UTF_8) ;
+ @Autowired
+ private HttpClient httpClient;
- mockProducer();
- mockConsumer();
- }
+ @Autowired
+ private HttpServer httpServer;
- /**
- * TODO #1161 - Improve with builder pattern
- */
@Test
@CitrusTest
void testByJsonPath(@CitrusResource TestCaseRunner runner) {
- // Given
- getPetByIdRequest.setPetId("1234");
-
- // Then
- getPetByIdRequest.setResponseStatus(HttpStatus.OK.value());
- getPetByIdRequest.setResponseReasonPhrase(HttpStatus.OK.getReasonPhrase());
-
- // Assert body by json path
- getPetByIdRequest.setResponseValue(Map.of("$.name", "Snoopy"));
-
- // When
- runner.$(getPetByIdRequest);
- }
-
- /**
- * TODO #1161 - Improve with builder pattern
- */
- @Test
- @CitrusTest
- void testValidationFailureByJsonPath(@CitrusResource TestCaseRunner runner) {
-
- // Given
- getPetByIdRequest.setPetId("1234");
-
- // Then
- getPetByIdRequest.setResponseStatus(HttpStatus.OK.value());
- getPetByIdRequest.setResponseReasonPhrase(HttpStatus.OK.getReasonPhrase());
-
- // Assert body by json path
- getPetByIdRequest.setResponseValue(Map.of("$.name", "Garfield"));
-
- // When
- runner.$(assertException()
- .exception(org.citrusframework.exceptions.CitrusRuntimeException.class)
- .message("Values not equal for element '$.name', expected 'Garfield' but was 'Snoopy'")
- .when(
- getPetByIdRequest
- )
+ runner.$(
+ openapiPetstore(httpClient)
+ .getPetById()
+ .send(request -> request
+ .withPetId(2002L)
+ .withCorrelationIds("5599")
+ .withVerbose(true)
+ )
);
- // When
-
- }
-
- /**
- * TODO #1161 - Improve with builder pattern
- */
- @Test
- @CitrusTest
- void testByResource(@CitrusResource TestCaseRunner runner) {
-
- // Given
- getPetByIdRequest.setPetId("1234");
-
- // Then
- getPetByIdRequest.setResponseStatus(HttpStatus.OK.value());
- getPetByIdRequest.setResponseReasonPhrase(HttpStatus.OK.getReasonPhrase());
- // Assert body by resource
- getPetByIdRequest.setResource(
- "org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json");
- // When
- runner.$(getPetByIdRequest);
- }
-
- /**
- * TODO #1161 - Improve with builder pattern
- */
- @Test
- @CitrusTest
- void testValidationFailureByResource(@CitrusResource TestCaseRunner runner) {
-
- // Given
- getPetByIdRequest.setPetId("1234");
-
- // Then
- getPetByIdRequest.setResponseStatus(HttpStatus.OK.value());
- getPetByIdRequest.setResponseReasonPhrase(HttpStatus.OK.getReasonPhrase());
- // Assert body by resource
- getPetByIdRequest.setResource(
- "org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage2.json");
-
- // When
- runner.$(assertException()
- .exception(org.citrusframework.exceptions.CitrusRuntimeException.class)
- .message("Values not equal for entry: '$['name']', expected 'Garfield' but was 'Snoopy'")
- .when(
- getPetByIdRequest
- )
+ respondPet(runner);
+
+ runner.$(
+ openapiPetstore(httpClient)
+ .getPetById()
+ .receive()
+ .message()
+ .validate(
+ pathExpression()
+ .jsonPath("$.name", "Snoopy")
+ .jsonPath("$.id", 2002)
+ )
);
}
- /**
- * TODO #1161 - Improve with builder pattern
- */
@Test
@CitrusTest
- void validateByVariable(@CitrusResource TestContext testContext,
- @CitrusResource TestCaseRunner runner) {
-
- // Given
- getPetByIdRequest.setPetId("1234");
-
- // Then
- getPetByIdRequest.setResponseStatus(HttpStatus.OK.value());
- getPetByIdRequest.setResponseReasonPhrase(HttpStatus.OK.getReasonPhrase());
-
- // Assert load data into variables
- getPetByIdRequest.setResponseVariable(Map.of("$", "RESPONSE", "$.id", "ID"));
-
- // When
- runner.$(getPetByIdRequest);
-
- // Then
- assertThat(testContext)
- .satisfies(
- c -> assertThat(c.getVariable("RESPONSE"))
- .isNotNull(),
- c -> assertThat(c.getVariable("ID"))
- .isNotNull()
- .isEqualTo("12")
- );
- }
-
- /**
- * TODO #1161 - Improve with builder pattern
- */
- @Test
- @CitrusTest
- void validateReceivedResponse(@CitrusResource TestContext testContext) {
-
- // Given
- getPetByIdRequest.setPetId("1234");
-
- // When
- getPetByIdRequest.sendRequest(testContext);
-
- // Then
- Message receiveResponse = getPetByIdRequest.receiveResponse(testContext);
- assertThat(receiveResponse)
- .isNotNull()
- .extracting(Message::getPayload)
- .asString()
- .isEqualToIgnoringWhitespace(defaultResponse);
- assertThat(receiveResponse.getHeaders())
- .containsEntry("citrus_http_status_code", 200)
- .containsEntry("citrus_http_reason_phrase", "OK");
- }
-
- private void mockProducer() {
- Producer producerMock = mock();
- when(httpClient.createProducer()).thenReturn(producerMock);
- }
-
- private void mockConsumer() {
- Message receiveMessage = createReceiveMessage();
+ void testJsonFileBody(@CitrusResource TestCaseRunner runner) {
+
+ runner.$(
+ openapiPetstore(httpClient)
+ .getPetById()
+ .send(request -> request
+ .withPetId(2002L)
+ .withCorrelationIds("5599")
+ .withVerbose(true)
+ )
+ );
- SelectiveConsumer consumer = mock(SelectiveConsumer.class);
- when(httpClient.createConsumer()).thenReturn(consumer);
- when(consumer.receive(any(), eq(5000L))).thenReturn(receiveMessage);
+ respondPet(runner);
+
+ var expectedResponse = new File("src/test/resources/org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json");
+ runner.$(
+ openapiPetstore(httpClient)
+ .getPetById()
+ .receive()
+ .message()
+ .validate((Message message, TestContext context) -> {
+ assertThat(expectedResponse).exists().content().satisfies(expectedContent -> {
+ assertThat(message.getPayload(String.class)).isEqualToIgnoringWhitespace(expectedContent);
+ });
+ })
+ );
}
- private Message createReceiveMessage() {
- Message receiveMessage = new DefaultMessage();
- receiveMessage.setPayload(defaultResponse);
- receiveMessage.getHeaders().put("citrus_http_reason_phrase", "OK");
- receiveMessage.getHeaders().put("citrus_http_version", "HTTP/1.1");
- receiveMessage.getHeaders().put("Content-Type", 200);
- receiveMessage.getHeaders().put("citrus_http_status_code", 200);
- return receiveMessage;
+ private void respondPet(TestCaseRunner runner) {
+ runner.$(http().server(httpServer)
+ .receive()
+ .get("/pet/2002")
+ .message()
+ .queryParam("verbose", "true")
+ .header("correlationIds", "5599")
+ .accept("@contains('application/json')@"));
+
+ runner.$(http().server(httpServer)
+ .send()
+ .response(OK)
+ .message()
+ .body("""
+ {
+ "id": ${petId},
+ "name": "Snoopy",
+ "tags": [],
+ "photoUrls": [],
+ "category": {
+ "name": "a name",
+ "id": 112233
+ },
+ "status": "available"
+ }
+ """)
+ .contentType("application/json").type(JSON));
}
@TestConfiguration
public static class Config {
- @Bean(name = {"applicationServiceClient", "petStoreEndpoint"})
- public HttpClient applicationServiceClient() {
- HttpClient client = mock(HttpClient.class);
- EndpointConfiguration endpointConfiguration = mock(EndpointConfiguration.class);
- when(client.getEndpointConfiguration()).thenReturn(new HttpEndpointConfiguration());
- when(endpointConfiguration.getTimeout()).thenReturn(5000L);
- return client;
+ private final int port = SocketUtils.findAvailableTcpPort(8080);
+
+ @Bean
+ public HttpClient httpClient() {
+ return new HttpClientBuilder()
+ .requestUrl("http://localhost:%d".formatted(port))
+ .build();
+ }
+
+ @Bean
+ public HttpServer httpServer() {
+ return new HttpServerBuilder()
+ .port(port)
+ // .endpointAdapter(endpointAdapter)
+ .timeout(5000L)
+ .autoStart(true)
+ .defaultStatus(NO_CONTENT)
+ .build();
}
}
}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenIT.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenIT.java
index 1d205f9400..6909086960 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenIT.java
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenIT.java
@@ -1,16 +1,10 @@
package org.citrusframework.openapi.generator;
-import static java.nio.file.Files.readString;
-import static java.nio.file.Files.walk;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.citrusframework.openapi.generator.JavaCitrusCodegenTest.getAbsoluteTargetDirectoryPath;
-import static org.citrusframework.openapi.generator.JavaCitrusCodegenTest.getAbsoluteTestResourcePath;
-import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
+import java.util.List;
import java.util.stream.Stream;
import org.apache.commons.lang3.stream.Streams;
import org.citrusframework.exceptions.CitrusRuntimeException;
@@ -25,108 +19,75 @@
/**
* This test case is designed to validate the consistency of the code generation process and detect
* any discrepancies between the generated API files and the reference files stored in
- * '/JavaCitrusCodegenIT/expectedgen/'. It compares the results of API generation against the
- * reference files, and a failure indicates potential changes in mustache templates or code
- * generation logic.
+ * '/JavaCitrusCodegenIntegrationTest/expectedgen/'. It compares the results of API generation
+ * against the reference files, and a failure indicates potential changes in mustache templates or
+ * code generation logic.
*
* If this test fails, it is essential to review the code generation process and underlying
* templates carefully. If the changes are intentional and verified, update the reference files by
- * copying the generated API sources to the '/JavaCitrusCodegenIT/expectedgen/' directory. To ensure
- * accurate copying, without unwanted code formatting, use a simple File Explorer instead of relying
- * on IDE-based operations.
+ * copying the generated API sources to the '/JavaCitrusCodegenIntegrationTest/expectedgen/'
+ * directory. To ensure accurate copying, without unwanted code formatting, use a simple File
+ * Explorer instead of relying on IDE-based operations.
*/
class JavaCitrusCodegenIT {
- public static final String BASE_PACKAGE = "org/citrusframework/openapi/generator";
-
- private static long countFilesRecursively(Path dir) throws IOException {
- try (Stream walk = walk(dir)) {
- return walk.filter(Files::isRegularFile).count();
- }
- }
-
- @Test
- void noAdditionalFiles() throws IOException {
- long expectedFileCount = countFilesRecursively(
- Path.of(getAbsoluteTestResourcePath(
- BASE_PACKAGE + "/JavaCitrusCodegenIT/expectedgen/rest")));
- long actualFileCount = countFilesRecursively(
- Path.of(getAbsoluteTargetDirectoryPath(
- "generated-test-sources/" + BASE_PACKAGE + "/rest")));
-
- assertEquals(expectedFileCount, actualFileCount,
- "Directories do not have the same number of files.");
- }
-
- static Stream getResourcesForRest() throws IOException {
- return geClassResourcesIgnoringInnerClasses(BASE_PACKAGE + "/rest");
- }
-
- @ParameterizedTest
- @MethodSource("getResourcesForRest")
- void testGeneratedFiles(Resource resource) throws IOException {
- File classFile = resource.getFile();
- String absolutePath = classFile.getAbsolutePath();
- String javaFilePath = absolutePath
- .replace("test-classes", "generated-test-sources")
- .replace(".class", ".java");
-
- assertFileContent(new File(javaFilePath), "rest");
- }
-
- static Stream getResourcesForSoap() throws IOException {
- return geClassResourcesIgnoringInnerClasses(
- BASE_PACKAGE + "/soap/bookservice");
- }
-
- @ParameterizedTest
- @MethodSource("getResourcesForSoap")
- void testGeneratedSoapFiles(Resource resource) throws IOException {
- File classFile = resource.getFile();
- String absolutePath = classFile.getAbsolutePath();
-
- String javaFilePath = absolutePath
- .replace("test-classes", "generated-test-sources")
- .replace(".class", ".java");
-
- assertFileContent(new File(javaFilePath), "soap");
- }
-
- private static Stream geClassResourcesIgnoringInnerClasses(String path)
- throws IOException {
- return Streams.of(
- new PathMatchingResourcePatternResolver().getResources(path + "/**/*.class"))
- .filter(resource -> {
- try {
- return !resource.getURI().toString().contains("$");
- } catch (Exception e) {
- throw new CitrusRuntimeException("Unable to retrieve URL from resource!");
- }
- }
- ).map(Arguments::arguments);
- }
-
- /*
- * NOTE: when changes have been performed to mustache templates, the expected files need to be updated.
- * Be aware that file content may change according to IDE formatting rules if the files are copied via IDE.
- * Files should therefore be copied using a file explorer which ensures that content of files does not change.
- */
- private void assertFileContent(File file, String apiDir) throws IOException {
- assertThat(file).exists();
-
- String expectedFilePath = BASE_PACKAGE + "/JavaCitrusCodegenIT/expectedgen/" + file.getAbsolutePath().substring(file.getAbsolutePath().indexOf(apiDir));
- ClassPathResource classPathResource = new ClassPathResource(expectedFilePath);
-
- String actualContent = readString(file.toPath());
- String expectedContent = readString(classPathResource.getFile().toPath());
-
- // Replace "Generated" with a placeholder
- String generatedAnnotationPattern = "@jakarta\\.annotation\\.Generated\\(.*?\\)";
- String placeholder = "@jakarta.annotation.Generated(value = \"org.citrusframework.openapi.generator.JavaCitrusCodegen\", date = \"TIMESTAMP\", comments = \"Generator version: VERSION\")";
-
- actualContent = actualContent.replaceAll(generatedAnnotationPattern, placeholder);
- expectedContent = expectedContent.replaceAll(generatedAnnotationPattern, placeholder);
-
- assertThat(actualContent).isEqualTo(expectedContent);
- }
+// static Stream getResourcesForRest() throws IOException {
+// return geClassResourcesIgnoringInnerClasses("org/citrusframework/openapi/generator/rest");
+// }
+//
+// @ParameterizedTest
+// @MethodSource("getResourcesForRest")
+// void testGeneratedFiles(Resource resource) throws IOException {
+// File classFile = resource.getFile();
+// String absolutePath = classFile.getAbsolutePath();
+// String javaFilePath = absolutePath.replace("test-classes", "generated-test-sources")
+// .replace(".class", ".java");
+//
+// assertFileContent(new File(javaFilePath), "rest");
+// }
+//
+// static Stream getResourcesForSoap() throws IOException {
+// return geClassResourcesIgnoringInnerClasses(
+// "org/citrusframework/openapi/generator/soap/bookservice");
+// }
+//
+// @ParameterizedTest
+// @MethodSource("getResourcesForSoap")
+// void testGeneratedSoapFiles(Resource resource) throws IOException {
+// File classFile = resource.getFile();
+// String absolutePath = classFile.getAbsolutePath();
+//
+// String javaFilePath = absolutePath.replace("test-classes", "generated-test-sources")
+// .replace(".class", ".java");
+//
+// assertFileContent(new File(javaFilePath), "soap");
+// }
+//
+// private static Stream geClassResourcesIgnoringInnerClasses(String path)
+// throws IOException {
+// return Streams.of(new PathMatchingResourcePatternResolver().getResources(
+// path + "/**/*.class")).filter(resource -> {
+// try {
+// return !resource.getURI().toString().contains("$");
+// } catch (Exception e) {
+// throw new CitrusRuntimeException("Unable to retrieve URL from resource!");
+// }
+// }).map(Arguments::arguments);
+// }
+//
+// private void assertFileContent(File file, String apiDir) throws IOException {
+// assertThat(file).exists();
+// String expectedFilePath =
+// "org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/"
+// + file.getAbsolutePath().substring(file.getAbsolutePath().indexOf(apiDir));
+//
+// ClassPathResource classPathResource = new ClassPathResource(expectedFilePath);
+//
+// /*
+// * NOTE: when changes have been performed to mustache templates, the expected files need to be updated.
+// * Be aware that file content may change according to IDE formatting rules if the files are copied via IDE.
+// * Files should therefore be copied using a file explorer which ensures that content of files does not change.
+// */
+// assertThat(file).hasSameTextualContentAs(classPathResource.getFile());
+// }
}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java
index f3860de3b4..394839c407 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java
@@ -5,7 +5,6 @@
import java.io.File;
import java.io.IOException;
-import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
@@ -33,31 +32,6 @@
class JavaCitrusCodegenTest {
- /**
- * Get the absolute path to the test resources directory.
- *
- * @param pathToFileInTestResources The file within {@code src/test/resources} to look for
- * @return the absolute path to the file
- */
- static String getAbsoluteTestResourcePath(String pathToFileInTestResources) {
- URL resourceUrl = JavaCitrusCodegenTest.class.getClassLoader().getResource(pathToFileInTestResources);
- assert resourceUrl != null;
- File inputSpecFile = new File(resourceUrl.getFile());
- return inputSpecFile.getAbsolutePath();
- }
-
- /**
- * Get the absolute path to the project's target directory.
- *
- * @param pathToFileInTargetDirectory The file within {@code target} to look for
- * @return the absolute path to the file
- */
- static String getAbsoluteTargetDirectoryPath(String pathToFileInTargetDirectory) {
- String projectBaseDir = System.getProperty("user.dir"); // Base directory of the project
- File outputDirFile = new File(projectBaseDir, "target/" + pathToFileInTargetDirectory);
- return outputDirFile.getAbsolutePath();
- }
-
@Test
void retrieveGeneratorBsSpi() {
JavaCitrusCodegen codegen = (JavaCitrusCodegen) CodegenConfigLoader.forName("java-citrus");
@@ -107,113 +81,72 @@ void areAdditionalPropertiesProcessedTest() {
assertThat(codegen.getTargetXmlnsNamespace()).isEqualTo(targetXmlnsNamespace);
}
- @Test
- void areReservedWordsEscapedTest() throws IOException {
- String absoluteInputSpecPath = getAbsoluteTestResourcePath("apis/petstore_reservedWords.yaml");
- String absoluteOutputDirPath = getAbsoluteTargetDirectoryPath("JavaCitrusCodegenTest/petstore_escapedWords");
-
- final CodegenConfigurator configurator = new CodegenConfigurator()
- .setGeneratorName(CODEGEN_NAME)
- .setInputSpec(absoluteInputSpecPath)
- .setOutputDir(absoluteOutputDirPath);
-
- final ClientOptInput clientOptInput = configurator.toClientOptInput();
- DefaultGenerator generator = new DefaultGenerator();
- List outputFiles = generator.opts(clientOptInput).generate();
-
- Optional file = outputFiles.stream()
- .filter(x -> "PetApi.java".equals(x.getName()))
- .findFirst();
-
- assertThat(file).isPresent();
-
- List lines = Files.readAllLines(file.get().toPath(), StandardCharsets.UTF_8);
-
- // "name" is a reserved word, so it should be escaped with an underline for the second parameter
- assertThat(
- lines.stream()
- .filter(x -> x.contains("\"name\", this._name"))
- .count())
- .isEqualTo(1L);
- }
-
- @Test
- void arePathParamsFieldsPresent() throws IOException {
- String absoluteInputSpecPath = getAbsoluteTestResourcePath("apis/petstore.yaml");
- String absoluteOutputDirPath = getAbsoluteTargetDirectoryPath("JavaCitrusCodegenTest/petstore");
-
- final CodegenConfigurator configurator = new CodegenConfigurator()
- .setGeneratorName(CODEGEN_NAME)
- .setInputSpec(absoluteInputSpecPath)
- .setOutputDir(absoluteOutputDirPath);
-
- final ClientOptInput clientOptInput = configurator.toClientOptInput();
- DefaultGenerator generator = new DefaultGenerator();
- List outputFiles = generator.opts(clientOptInput).generate();
-
- Optional file = outputFiles.stream()
- .filter(x -> "PetApi.java".equals(x.getName()))
- .findFirst();
-
- assertThat(file).isPresent();
-
- List lines = Files.readAllLines(file.get().toPath(), StandardCharsets.UTF_8);
-
- // "name" is a reserved word, so it should be escaped with an underline for the second parameter
- assertThat(
- lines.stream()
- .filter(x -> x.contains("private String petId;"))
- .count())
- .isEqualTo(4L);
- assertThat(
- lines.stream()
- .filter(x -> x.contains(
- "endpoint = endpoint.replace(\"{\" + \"petId\" + \"}\", petId);"))
- .count())
- .isEqualTo(4L);
- }
-
- @Test
- void areBasicAuthFieldsPresent() throws IOException {
- String absoluteInputSpecPath = getAbsoluteTestResourcePath("apis/petstore.yaml");
- String absoluteOutputDirPath = getAbsoluteTargetDirectoryPath("JavaCitrusCodegenTest/petstore");
-
- final CodegenConfigurator configurator = new CodegenConfigurator()
- .setGeneratorName(CODEGEN_NAME)
- .setInputSpec(absoluteInputSpecPath)
- .setOutputDir(absoluteOutputDirPath);
-
- final ClientOptInput clientOptInput = configurator.toClientOptInput();
- DefaultGenerator generator = new DefaultGenerator();
- List outputFiles = generator.opts(clientOptInput).generate();
-
- Optional file = outputFiles.stream()
- .filter(x -> "PetApi.java".equals(x.getName()))
- .findFirst();
-
- assertThat(file).isPresent();
-
- List lines = Files.readAllLines(file.get().toPath(), StandardCharsets.UTF_8);
-
- // "name" is a reserved word, so it should be escaped with an underline for the second parameter
- assertThat(
- lines.stream()
- .filter(x -> x.contains("@Value(\"${\" + \"apiEndpoint.basic.username:#{null}}\")"))
- .count())
- .isEqualTo(1L);
- assertThat(
- lines.stream()
- .filter(x -> x.contains("private String basicUsername;"))
- .count())
- .isEqualTo(1L);
- assertThat(
- lines.stream()
- .filter(x ->
- x.contains(
- "messageBuilderSupport.header(\"Authorization\", \"Basic \" + Base64.getEncoder().encodeToString((context.replaceDynamicContentInString(basicUsername)+\":\"+context.replaceDynamicContentInString(basicPassword)).getBytes()));"
- )
- )
- .count())
- .isEqualTo(1L);
- }
+// @Test
+// void areReservedWordsEscapedTest() throws IOException {
+// final CodegenConfigurator configurator = new CodegenConfigurator()
+// .setGeneratorName(CODEGEN_NAME)
+// .setInputSpec("src/test/resources/apis/petstore_reservedWords.yaml")
+// .setOutputDir("target/JavaCitrusCodegenTest/petstore_escapedWords");
+//
+// final ClientOptInput clientOptInput = configurator.toClientOptInput();
+// DefaultGenerator generator = new DefaultGenerator();
+// List outputFiles = generator.opts(clientOptInput).generate();
+//
+// Optional file = outputFiles.stream().filter(x -> "PetApi.java".equals(x.getName()))
+// .findFirst();
+//
+// assertThat(file).isPresent();
+//
+// List lines = Files.readAllLines(file.get().toPath(), StandardCharsets.UTF_8);
+//
+// // "name" is a reserved word, so it should be escaped with an underline for the second parameter
+// assertThat(lines.stream().filter(x -> x.contains("\"name\", this._name")).count()).isEqualTo(1L);
+// }
+//
+// @Test
+// void arePathParamsFieldsPresent() {
+// var fixture = new JavaCitrusCodegen();
+// String inputSpec = "src\\test\\resources\\apis\\petstore.yaml";
+// fixture.setInputSpec(inputSpec);
+//
+// fixture.processOpts();
+//
+// assertThat(fixture.additionalProperties()).containsEntry("inputSpecRelative", "src/test/resources/apis/petstore.yaml");
+// }
+//
+// @Test
+// void areBasicAuthFieldsPresent() throws IOException {
+// final CodegenConfigurator configurator = new CodegenConfigurator()
+// .setGeneratorName(CODEGEN_NAME)
+// .setInputSpec("src/test/resources/apis/petstore.yaml")
+// .setOutputDir("target/JavaCitrusCodegenTest/petstore");
+//
+// final ClientOptInput clientOptInput = configurator.toClientOptInput();
+// DefaultGenerator generator = new DefaultGenerator();
+// List outputFiles = generator.opts(clientOptInput).generate();
+//
+// Optional file = outputFiles.stream().filter(x -> "PetApi.java".equals(x.getName()))
+// .findFirst();
+//
+// assertThat(file).isPresent();
+//
+// List lines = Files.readAllLines(file.get().toPath(), StandardCharsets.UTF_8);
+//
+// // "name" is a reserved word, so it should be escaped with an underline for the second parameter
+// assertThat(lines.stream()
+// .filter(x -> x.contains("@Value(\"${\" + \"apiEndpoint.basic.username:#{null}}\")"))
+// .count()).isEqualTo(1L);
+// assertThat(
+// lines.stream().filter(x -> x.contains("private String basicUsername;")).count()).isEqualTo(1L);
+// assertThat(
+// lines
+// .stream()
+// .filter(x ->
+// x.contains(
+// "messageBuilderSupport.header(\"Authorization\", \"Basic \" + Base64.getEncoder().encodeToString((context.replaceDynamicContentInString(basicUsername)+\":\"+context.replaceDynamicContentInString(basicPassword)).getBytes()));"
+// )
+// )
+// .count()
+// ).isEqualTo(1L);
+// }
}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java
index 419cea9ade..6b17f01f13 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java
@@ -5,8 +5,8 @@
import java.util.List;
import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
-import org.citrusframework.openapi.generator.util.TestApiActionBuilderCustomizer;
import org.citrusframework.testapi.ApiActionBuilderCustomizerService;
+import org.citrusframework.openapi.generator.util.TestApiActionBuilderCustomizer;
import org.junit.jupiter.api.Test;
class ServiceLoaderTest {
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/util/TestApiActionBuilderCustomizer.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/util/TestApiActionBuilderCustomizer.java
index 1b0b8824a7..0aaa9761ab 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/util/TestApiActionBuilderCustomizer.java
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/util/TestApiActionBuilderCustomizer.java
@@ -1,6 +1,7 @@
package org.citrusframework.openapi.generator.util;
import org.citrusframework.TestAction;
+import org.citrusframework.TestActionBuilder;
import org.citrusframework.actions.SendMessageAction.SendMessageActionBuilder;
import org.citrusframework.context.TestContext;
import org.citrusframework.testapi.ApiActionBuilderCustomizerService;
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/petstore.yaml b/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/petstore.yaml
index 79249f26ed..5524ac3c41 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/petstore.yaml
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/petstore.yaml
@@ -164,6 +164,16 @@ paths:
required: true
type: integer
format: int64
+ - name: verbose
+ description: Output details
+ in: query
+ required: false
+ type: boolean
+ - name: correlationIds
+ description: ID to trace a request
+ in: header
+ required: false
+ type: string
responses:
'200':
description: successful operation
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json
index b68ed32a5e..27d38acb91 100644
--- a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/GeneratedApiTest/payloads/getPetByIdControlMessage1.json
@@ -1,6 +1,11 @@
{
- "id": 12,
+ "id": 2002,
"name": "Snoopy",
- "tags": ["comic dog"],
- "photoUrls": ["url1", "url2"]
-}
+ "tags": [],
+ "photoUrls": [],
+ "category": {
+ "name": "a name",
+ "id": 112233
+ },
+ "status": "available"
+}
\ No newline at end of file
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java
new file mode 100644
index 0000000000..478a8e8742
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.multiparttest.citrus;
+
+
+import static org.springframework.util.CollectionUtils.isEmpty;
+
+import jakarta.annotation.Generated;
+import jakarta.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import javax.sql.DataSource;
+import org.citrusframework.actions.AbstractTestAction;
+import org.citrusframework.actions.ReceiveMessageAction;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.http.actions.HttpActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder;
+import org.citrusframework.http.actions.HttpClientResponseActionBuilder;
+import org.citrusframework.http.actions.HttpClientResponseActionBuilder.HttpMessageBuilderSupport;
+import org.citrusframework.http.client.HttpClient;
+import org.citrusframework.message.Message;
+import org.citrusframework.testapi.ApiActionBuilderCustomizerService;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.validation.DelegatingPayloadVariableExtractor;
+import org.citrusframework.validation.PathExpressionValidationContext;
+import org.citrusframework.validation.json.JsonMessageValidationContext;
+import org.citrusframework.validation.script.ScriptValidationContext;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public abstract class MultipartTestAbstractTestRequest extends AbstractTestAction {
+
+ protected final Marker coverageMarker = MarkerFactory.getMarker("MULTIPARTTEST-API-COVERAGE");
+
+ @Autowired
+ @Qualifier("multipartTestEndpoint")
+ protected HttpClient httpClient;
+
+ @Autowired(required = false)
+ protected DataSource dataSource;
+
+ @Autowired(required = false)
+ private List actionBuilderCustomizerServices;
+
+ // attributes of differentNodes
+ protected boolean schemaValidation;
+ protected String schema;
+ protected String bodyContentType;
+ protected String bodyLiteralContentType;
+ protected String bodyFile;
+ protected String bodyLiteral;
+ protected String responseAcceptType = "*/*";
+ protected String responseType = "json";
+ protected int responseStatus = 200;
+ protected String responseReasonPhrase = "OK";
+ protected String responseVersion = "HTTP/1.1";
+
+ // children of response element
+ protected String resource;
+ protected Map responseVariable; // Contains the 'JSON-PATH' as key and the 'VARIABLE NAME' as value
+ protected Map responseValue; // Contains the 'JSON-PATH' as key and the 'VALUE TO BE VALIDATED' as value
+ protected Map cookies;
+ protected Map headers;
+ protected String script;
+ protected String type; // default script type is groovy - supported types see com.consol.citrus.script.ScriptTypes
+
+ @Override
+ public void doExecute(TestContext context) {
+ sendRequest(context);
+ recieveResponse(context);
+ }
+
+ /**
+ * This method receives the HTTP-Response.
+ *
+ * @deprecated use {@link MultipartTestAbstractTestRequest#receiveResponse(TestContext)} instead.
+ */
+ public ReceiveMessageAction recieveResponse(TestContext context) {
+
+ HttpClientResponseActionBuilder httpClientResponseActionBuilder = new HttpActionBuilder().client(httpClient).receive().response();
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientResponseActionBuilder.getMessageBuilderSupport();
+
+ messageBuilderSupport
+ .statusCode(responseStatus)
+ .reasonPhrase(responseReasonPhrase)
+ .version(responseVersion)
+ .validate(new JsonMessageValidationContext.Builder().schemaValidation(schemaValidation).schema(schema));
+
+ if (resource != null) {
+ messageBuilderSupport.body(Resources.create(resource));
+ }
+
+ if (!isEmpty(responseVariable)) {
+ DelegatingPayloadVariableExtractor.Builder extractorBuilder = new DelegatingPayloadVariableExtractor.Builder();
+ responseVariable.forEach(extractorBuilder::expression);
+ messageBuilderSupport.extract(extractorBuilder);
+ }
+
+ if (!isEmpty(responseValue)) {
+ PathExpressionValidationContext.Builder validationContextBuilder = new PathExpressionValidationContext.Builder();
+ responseValue.forEach(validationContextBuilder::expression);
+ messageBuilderSupport.validate(validationContextBuilder);
+ }
+
+ if (script != null) {
+ ScriptValidationContext.Builder scriptValidationContextBuilder = new ScriptValidationContext.Builder();
+ if (type != null) {
+ scriptValidationContextBuilder.scriptType(type);
+ }
+ scriptValidationContextBuilder.script(script);
+ messageBuilderSupport.validate(scriptValidationContextBuilder);
+ }
+
+ messageBuilderSupport.type(responseType);
+ httpClientResponseActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ var responseAction = httpClientResponseActionBuilder.build();
+
+ responseAction.execute(context);
+
+ return responseAction;
+ }
+
+ public @Nullable Message receiveResponse(TestContext context) {
+ var responseAction = recieveResponse(context);
+
+ var messageStore = context.getMessageStore();
+ return messageStore.getMessage(messageStore.constructMessageName(responseAction, httpClient));
+ }
+
+ public abstract void sendRequest(TestContext context);
+
+ public void setSchemaValidation(boolean schemaValidation) {
+ this.schemaValidation = schemaValidation;
+ }
+
+ public void setSchema(String schema) {
+ this.schema = schema;
+ }
+
+ public void setBodyLiteral(String bodyLiteral) {
+ this.bodyLiteral = bodyLiteral;
+ }
+
+ public void setBodyContentType(String bodyContentType) {
+ this.bodyContentType = bodyContentType;
+ }
+
+ public void setBodyLiteralContentType(String bodyLiteralContentType) {
+ this.bodyLiteralContentType = bodyLiteralContentType;
+ }
+
+ public void setResponseAcceptType(String responseAcceptType) {
+ this.responseAcceptType = responseAcceptType;
+ }
+
+ public void setCookie(Map cookies) {
+ this.cookies = cookies;
+ }
+
+ public void setHeader(Map headers) {
+ this.headers = headers;
+ }
+
+ public void setBodyFile(String bodyFile) {
+ this.bodyFile = bodyFile;
+ }
+
+ public void setResponseType(String responseType) {
+ this.responseType = responseType;
+ }
+
+ public void setResponseStatus(int responseStatus) {
+ this.responseStatus = responseStatus;
+ }
+
+ public void setResponseReasonPhrase(String responseReasonPhrase) {
+ this.responseReasonPhrase = responseReasonPhrase;
+ }
+
+ public void setResponseVersion(String responseVersion) {
+ this.responseVersion = responseVersion;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public void setResponseVariable(Map responseVariable) {
+ this.responseVariable = responseVariable;
+ }
+
+ public void setResponseValue(Map responseValue) {
+ this.responseValue = responseValue;
+ }
+
+ public void setScript(String script) {
+ this.script = script;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ protected HttpClientRequestActionBuilder customizeBuilder(GeneratedApi generatedApi,
+ TestContext context, HttpClientRequestActionBuilder httpClientRequestActionBuilder) {
+
+ httpClientRequestActionBuilder = customizeByBeans(generatedApi, context,
+ httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder = customizeBySpi(generatedApi, context, httpClientRequestActionBuilder);
+
+ return httpClientRequestActionBuilder;
+ }
+
+ private HttpClientRequestActionBuilder customizeBySpi(GeneratedApi generatedApi, TestContext context,
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder) {
+ ServiceLoader serviceLoader = ServiceLoader.load(
+ ApiActionBuilderCustomizerService.class, ApiActionBuilderCustomizerService.class.getClassLoader());
+ for (ApiActionBuilderCustomizerService service :serviceLoader) {
+ httpClientRequestActionBuilder = service.build(generatedApi, this, context, httpClientRequestActionBuilder);
+ }
+ return httpClientRequestActionBuilder;
+ }
+
+ private HttpClientRequestActionBuilder customizeByBeans(
+ GeneratedApi generatedApi, TestContext context,
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder) {
+ if (actionBuilderCustomizerServices != null) {
+ for (ApiActionBuilderCustomizerService apiActionBuilderCustomizer : actionBuilderCustomizerServices) {
+ httpClientRequestActionBuilder = apiActionBuilderCustomizer.build(generatedApi, this,
+ context, httpClientRequestActionBuilder);
+ }
+ }
+ return httpClientRequestActionBuilder;
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestBeanDefinitionParser.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestBeanDefinitionParser.java
new file mode 100644
index 0000000000..1ca5480c9e
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestBeanDefinitionParser.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.multiparttest.citrus;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.processing.Generated;
+
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.core.Conventions;
+import org.springframework.util.Assert;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class MultipartTestBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String COOKIE = "cookie";
+ private static final String HEADER = "header";
+ private static final String SOAP_HEADER = "soapHeader";
+ private static final String MIME_HEADER = "mimeHeader";
+ private static final String NAME = "name";
+ private static final String REQUEST_BODY = "body";
+ private static final String REQUEST_BODY_LITERAL = "bodyLiteral";
+ private static final String MULTIPART_BODY = "multipartBody";
+ private static final String RESPONSE = "response";
+ private static final String RESPONSE_JSONPATH = "json-path";
+ private static final String RESPONSE_XPATH = "xpath";
+ private static final String EXPRESSION = "expression";
+ private static final String VALUE = "value";
+ private static final String RESPONSE_RESOURCE = "resource";
+ private static final String FILE = "file";
+ private static final String RESPONSE_VARIABLE = "responseVariable";
+ private static final String RESPONSE_VALUE = "responseValue";
+ private static final String SCRIPT = "script";
+ private static final String TYPE = "type";
+ private static final String SQL = "sql";
+ private static final String COLUMN = "column";
+ private static final String VARIABLE = "variable";
+ // new
+ private static final String SCHEMA = "schema";
+ // new
+ private static final String SCHEMA_VALIDATION = "schemaValidation";
+
+ private final Class> beanClass;
+
+ public MultipartTestBeanDefinitionParser(Class> beanClass) {
+ this.beanClass = beanClass;
+ }
+
+ public BeanDefinition parse(Element element) {
+ return parse(element, null);
+ }
+
+ /**
+ * Note: The {@link MultipartTestBeanDefinitionParser#parse(Element element)} allows access direct
+ * access without the {@link org.springframework.beans.factory.xml.ParserContext} for convenience.
+ */
+ @Override
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
+ retrieveRootNodeAttributes(element, builder);
+ retrieveOptionalNodeAttributes(element, REQUEST_BODY, builder);
+ retrieveTextContentAndNodeAttributes(element, REQUEST_BODY_LITERAL, builder);
+ retrieveOptionalNodeAttributes(element, RESPONSE, builder);
+ retrieveParamNodeData(element, builder, COOKIE);
+ retrieveParamNodeData(element, builder, HEADER);
+ retrieveParamNodeData(element, builder, SOAP_HEADER);
+ retrieveParamNodeData(element, builder, MIME_HEADER);
+ retrieveOptionalNodeAttributes(element, SCHEMA, builder);
+ retrieveOptionalNodeAttributes(element, SCHEMA_VALIDATION, builder);
+ retrieveOptionalMultipartElements(element, builder);
+ retrieveResponseNodeData(element, builder);
+ builder.addPropertyValue("name", element.getTagName());
+ return builder.getBeanDefinition();
+ }
+
+ private void retrieveOptionalMultipartElements(Element element, BeanDefinitionBuilder builder) {
+ var multipartBodyElement = DomUtils.getChildElementByTagName(element, MULTIPART_BODY);
+ if (multipartBodyElement != null) {
+ var multipartBodyChildElements = DomUtils.getChildElements(multipartBodyElement);
+ for(int i = 0; i < multipartBodyChildElements.size(); i++){
+ var multipartBodyChildElement = multipartBodyChildElements.get(i);
+ String propertyName = Conventions.attributeNameToPropertyName(multipartBodyChildElement.getLocalName());
+ builder.addPropertyValue(propertyName, multipartBodyChildElement.getTextContent());
+ }
+ }
+ }
+
+ private void retrieveRootNodeAttributes(Element element, BeanDefinitionBuilder builder) {
+ NamedNodeMap attributes = element.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName), "Illegal property name returned, it must not be null or empty.");
+ builder.addPropertyValue(propertyName, attribute.getValue());
+ }
+ }
+
+ private void retrieveOptionalNodeAttributes(Element element, String elementName, BeanDefinitionBuilder builder) {
+ if (!DomUtils.getChildElementsByTagName(element, elementName).isEmpty()) {
+ Element el = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ NamedNodeMap attributes = el.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName), "Illegal property name returned, it must not be null or empty.");
+ String variableName = el.getLocalName() + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
+ builder.addPropertyValue(variableName, attribute.getValue());
+ }
+ }
+ }
+
+ private void retrieveTextContentAndNodeAttributes(Element element, String elementName, BeanDefinitionBuilder builder) {
+ if (!DomUtils.getChildElementsByTagName(element, elementName).isEmpty()) {
+ Element el1 = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ NamedNodeMap attributes = el1.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName1 = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName1), "Illegal property name returned, it must not be null or empty.");
+ String variableName = el1.getLocalName() + propertyName1.substring(0, 1).toUpperCase() + propertyName1.substring(1);
+ builder.addPropertyValue(variableName, attribute.getValue());
+ }
+ Element el = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ builder.addPropertyValue(elementName, el.getTextContent());
+ }
+ }
+
+ private void retrieveParamNodeData(Element element, BeanDefinitionBuilder builder, String paramType) {
+ if (!DomUtils.getChildElementsByTagName(element, paramType).isEmpty()) {
+ Map params = new HashMap<>();
+ List elements = DomUtils.getChildElementsByTagName(element, paramType);
+ elements.forEach(e -> {
+ String name = e.getAttribute(NAME);
+ String value = e.getAttribute(VALUE);
+
+ Assert.state(StringUtils.isNotBlank(name), "Illegal attribute value returned. The 'name' attribute must not be null or empty.");
+ Assert.state(StringUtils.isNotBlank(value), "Illegal attribute value returned. The 'value' attribute must not be null or empty.");
+
+ params.put(name, value);
+ });
+ builder.addPropertyValue(paramType, params);
+ }
+ }
+
+ private void retrieveResponseNodeData(Element element, BeanDefinitionBuilder builder) {
+
+ if (!DomUtils.getChildElementsByTagName(element, RESPONSE).isEmpty()) {
+ Element response = DomUtils.getChildElementsByTagName(element, RESPONSE).get(0);
+ List elements = DomUtils.getChildElements(response);
+
+ Map responseVariable = new HashMap<>();
+ Map responseValue = new HashMap<>();
+
+ for (int i = 0; i < elements.size(); i++) {
+ Element e = elements.get(i);
+
+ if (e.getTagName().contains(RESPONSE_JSONPATH) || e.getTagName().contains(RESPONSE_XPATH)) {
+ String expression = e.getAttribute(EXPRESSION);
+ String value = e.getAttribute(VALUE);
+
+ Assert.state(StringUtils.isNotBlank(expression), "Illegal attribute value returned. The 'expression' attribute must not be null or empty.");
+ Assert.state(StringUtils.isNotBlank(value), "Illegal attribute value returned. The 'value' attribute must not be null or empty.");
+
+ // variable to save @variable('ebid')@ else value to validate
+ if (value.matches("\\@variable\\('.*'\\)\\@")) {
+ Matcher match = Pattern.compile("\\'(.*?)\\'").matcher(value);
+ if (match.find()) {
+ responseVariable.put(expression, value.substring(match.start() + 1, match.end() - 1));
+ }
+ } else {
+ responseValue.put(expression, value);
+ }
+ } else if (e.getTagName().contains(SCRIPT)) {
+ String script = e.getTextContent();
+ Assert.state(StringUtils.isNotBlank(script), "Illegal attribute value returned. The 'script' attribute must not be null or empty.");
+ builder.addPropertyValue(SCRIPT, script);
+
+ if (!e.getAttribute(TYPE).isEmpty()) {
+ String type = e.getAttribute(TYPE);
+ Assert.state(StringUtils.isNotBlank(type), "Illegal attribute value returned. The 'type' attribute must not be null or empty.");
+ builder.addPropertyValue(TYPE, type);
+ }
+ } else if (e.getTagName().contains(RESPONSE_RESOURCE)) {
+ String filePath = e.getAttribute(FILE);
+ Assert.state(StringUtils.isNotBlank(filePath), "Illegal attribute value returned. The 'file' attribute must not be null or empty.");
+ builder.addPropertyValue(RESPONSE_RESOURCE, filePath);
+ }
+
+ }
+
+ builder.addPropertyValue(RESPONSE_VARIABLE, responseVariable);
+ builder.addPropertyValue(RESPONSE_VALUE, responseValue);
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/extension/MultipartTestNamespaceHandler.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/extension/MultipartTestNamespaceHandler.java
new file mode 100644
index 0000000000..9f36ba2472
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/extension/MultipartTestNamespaceHandler.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.multiparttest.citrus.extension;
+
+import org.citrusframework.openapi.generator.rest.multiparttest.request.MultiparttestControllerApi;
+import org.citrusframework.openapi.generator.rest.multiparttest.citrus.MultipartTestBeanDefinitionParser;
+
+import javax.annotation.processing.Generated;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class MultipartTestNamespaceHandler extends NamespaceHandlerSupport {
+
+ @Override
+ public void init() {
+ registerBeanDefinitionParser("deleteObjectRequest", new MultipartTestBeanDefinitionParser(MultiparttestControllerApi.DeleteObjectRequest.class));
+ registerBeanDefinitionParser("fileExistsRequest", new MultipartTestBeanDefinitionParser(MultiparttestControllerApi.FileExistsRequest.class));
+ registerBeanDefinitionParser("generateReportRequest", new MultipartTestBeanDefinitionParser(MultiparttestControllerApi.GenerateReportRequest.class));
+ registerBeanDefinitionParser("multipleDatatypesRequest", new MultipartTestBeanDefinitionParser(MultiparttestControllerApi.MultipleDatatypesRequest.class));
+ registerBeanDefinitionParser("postFileRequest", new MultipartTestBeanDefinitionParser(MultiparttestControllerApi.PostFileRequest.class));
+ registerBeanDefinitionParser("postRandomRequest", new MultipartTestBeanDefinitionParser(MultiparttestControllerApi.PostRandomRequest.class));
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/model/Metadata.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/model/Metadata.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/model/Metadata.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/model/PutObjectResult.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/model/PutObjectResult.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/model/PutObjectResult.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/request/MultiparttestControllerApi.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/request/MultiparttestControllerApi.java
new file mode 100644
index 0000000000..bde720eb16
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/request/MultiparttestControllerApi.java
@@ -0,0 +1,766 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.multiparttest.request;
+
+import jakarta.annotation.Generated;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.testapi.GeneratedApiRequest;
+import jakarta.servlet.http.Cookie;
+import org.apache.commons.lang3.StringUtils;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.http.actions.HttpActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder.HttpMessageBuilderSupport;
+import org.citrusframework.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import org.citrusframework.openapi.generator.rest.multiparttest.citrus.MultipartTestAbstractTestRequest;
+
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class MultiparttestControllerApi implements GeneratedApi
+{
+
+ public static final MultiparttestControllerApi INSTANCE = new MultiparttestControllerApi();
+
+ public String getApiTitle() {
+ return "multiparttest API";
+ }
+
+ public String getApiVersion() {
+ return "2.0.0";
+ }
+
+ public String getApiPrefix() {
+ return "MultipartTest";
+ }
+
+ public Map getApiInfoExtensions() {
+ Map infoExtensionMap = new HashMap<>();
+ infoExtensionMap.put("x-citrus-api-name", "multiparttest-rest-resource");
+ infoExtensionMap.put("x-citrus-app", "MPT");
+ return infoExtensionMap;
+ }
+
+ /** deleteObject (DELETE /api/v2/multitest-file/{bucket}/{filename})
+ Delete file.
+
+ **/
+ public static class DeleteObjectRequest extends MultipartTestAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/api/v2/multitest-file/{bucket}/{filename}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(DeleteObjectRequest.class);
+
+ private String bucket;
+
+ private String filename;
+
+
+ public DeleteObjectRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("MultipartTest".toLowerCase() + ":deleteObjectRequestType");
+ }
+
+ public String getOperationName() {
+ return "deleteObject";
+ }
+
+ public String getMethod() {
+ return "DELETE";
+ }
+
+ public String getPath() {
+ return "/api/v2/multitest-file/{bucket}/{filename}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .delete(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "deleteObject;DELETE;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = filename;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "bucket" + "}", bucket);endpoint = endpoint.replace("{" + "filename" + "}", filename);
+ return endpoint;
+ }
+ }
+ /** fileExists (GET /api/v2/multitest-file/{bucket}/{filename}/exists)
+ Checks if file exist.
+
+ **/
+ public static class FileExistsRequest extends MultipartTestAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/api/v2/multitest-file/{bucket}/{filename}/exists";
+ private final Logger coverageLogger = LoggerFactory.getLogger(FileExistsRequest.class);
+
+ private String bucket;
+
+ private String filename;
+
+
+ public FileExistsRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("MultipartTest".toLowerCase() + ":fileExistsRequestType");
+ }
+
+ public String getOperationName() {
+ return "fileExists";
+ }
+
+ public String getMethod() {
+ return "GET";
+ }
+
+ public String getPath() {
+ return "/api/v2/multitest-file/{bucket}/{filename}/exists";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .get(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "fileExists;GET;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = filename;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "bucket" + "}", bucket);endpoint = endpoint.replace("{" + "filename" + "}", filename);
+ return endpoint;
+ }
+ }
+ /** generateReport (POST /api/v2/multitest-reportgeneration)
+ summary
+
+ **/
+ public static class GenerateReportRequest extends MultipartTestAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/api/v2/multitest-reportgeneration";
+ private final Logger coverageLogger = LoggerFactory.getLogger(GenerateReportRequest.class);
+
+ private String template;
+
+ private String additionalData;
+
+ private String _schema;
+
+
+ public GenerateReportRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("MultipartTest".toLowerCase() + ":generateReportRequestType");
+ }
+
+ public String getOperationName() {
+ return "generateReport";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/api/v2/multitest-reportgeneration";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ MultiValueMap multiValues = new LinkedMultiValueMap<>();
+ if(StringUtils.isBlank(template)) {
+ throw new CitrusRuntimeException(String.format("Required attribute '%s' is not specified", "template"));
+ }
+ if (StringUtils.isNotBlank(template)) {
+ // first try to load from resource
+ ClassPathResource resource = null;
+ try {
+ resource = new ClassPathResource(template);
+ }
+ catch(Exception ignore) {
+ // Use plain text instead of resource
+ }
+
+ if(resource != null && resource.exists()){
+ multiValues.add("template", resource);
+ } else {
+ multiValues.add("template", template);
+ }
+ bodyLog += template.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+ if (StringUtils.isNotBlank(additionalData)) {
+ // first try to load from resource
+ ClassPathResource resource = null;
+ try {
+ resource = new ClassPathResource(additionalData);
+ }
+ catch(Exception ignore) {
+ // Use plain text instead of resource
+ }
+
+ if(resource != null && resource.exists()){
+ multiValues.add("additionalData", resource);
+ } else {
+ multiValues.add("additionalData", additionalData);
+ }
+ bodyLog += additionalData.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+ if (StringUtils.isNotBlank(_schema)) {
+ // first try to load from resource
+ ClassPathResource resource = null;
+ try {
+ resource = new ClassPathResource(_schema);
+ }
+ catch(Exception ignore) {
+ // Use plain text instead of resource
+ }
+
+ if(resource != null && resource.exists()){
+ multiValues.add("_schema", resource);
+ } else {
+ multiValues.add("_schema", _schema);
+ }
+ bodyLog += _schema.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+
+ bodyLog += "\";\"" + MediaType.MULTIPART_FORM_DATA_VALUE + "\"";
+ messageBuilderSupport.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
+ .body(multiValues);
+
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "generateReport;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setTemplate(String template) {
+ this.template = template;
+ }
+
+ public void setAdditionalData(String additionalData) {
+ this.additionalData = additionalData;
+ }
+
+ public void set_schema(String _schema) {
+ this._schema = _schema;
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** multipleDatatypes (POST /api/v2/multitest-multipledatatypes)
+ summary
+
+ **/
+ public static class MultipleDatatypesRequest extends MultipartTestAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/api/v2/multitest-multipledatatypes";
+ private final Logger coverageLogger = LoggerFactory.getLogger(MultipleDatatypesRequest.class);
+
+ private String stringData;
+
+ private String booleanData;
+
+ private String integerData;
+
+
+ public MultipleDatatypesRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("MultipartTest".toLowerCase() + ":multipleDatatypesRequestType");
+ }
+
+ public String getOperationName() {
+ return "multipleDatatypes";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/api/v2/multitest-multipledatatypes";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ MultiValueMap multiValues = new LinkedMultiValueMap<>();
+ if (StringUtils.isNotBlank(stringData)) {
+ // first try to load from resource
+ ClassPathResource resource = null;
+ try {
+ resource = new ClassPathResource(stringData);
+ }
+ catch(Exception ignore) {
+ // Use plain text instead of resource
+ }
+
+ if(resource != null && resource.exists()){
+ multiValues.add("stringData", resource);
+ } else {
+ multiValues.add("stringData", stringData);
+ }
+ bodyLog += stringData.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+ if (StringUtils.isNotBlank(booleanData)) {
+ // first try to load from resource
+ ClassPathResource resource = null;
+ try {
+ resource = new ClassPathResource(booleanData);
+ }
+ catch(Exception ignore) {
+ // Use plain text instead of resource
+ }
+
+ if(resource != null && resource.exists()){
+ multiValues.add("booleanData", resource);
+ } else {
+ multiValues.add("booleanData", booleanData);
+ }
+ bodyLog += booleanData.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+ if (StringUtils.isNotBlank(integerData)) {
+ // first try to load from resource
+ ClassPathResource resource = null;
+ try {
+ resource = new ClassPathResource(integerData);
+ }
+ catch(Exception ignore) {
+ // Use plain text instead of resource
+ }
+
+ if(resource != null && resource.exists()){
+ multiValues.add("integerData", resource);
+ } else {
+ multiValues.add("integerData", integerData);
+ }
+ bodyLog += integerData.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+
+ bodyLog += "\";\"" + MediaType.MULTIPART_FORM_DATA_VALUE + "\"";
+ messageBuilderSupport.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
+ .body(multiValues);
+
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "multipleDatatypes;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setStringData(String stringData) {
+ this.stringData = stringData;
+ }
+
+ public void setBooleanData(String booleanData) {
+ this.booleanData = booleanData;
+ }
+
+ public void setIntegerData(String integerData) {
+ this.integerData = integerData;
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** postFile (POST /api/v2/multitest-file/{bucket}/{filename})
+ Uploads file.
+
+ **/
+ public static class PostFileRequest extends MultipartTestAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/api/v2/multitest-file/{bucket}/{filename}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(PostFileRequest.class);
+
+ private String bucket;
+
+ private String filename;
+
+ private String multipartFile;
+
+
+ public PostFileRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("MultipartTest".toLowerCase() + ":postFileRequestType");
+ }
+
+ public String getOperationName() {
+ return "postFile";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/api/v2/multitest-file/{bucket}/{filename}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ MultiValueMap multiValues = new LinkedMultiValueMap<>();
+ if (StringUtils.isNotBlank(multipartFile)) {
+ multiValues.add("multipartFile", new ClassPathResource(multipartFile));
+ bodyLog += multipartFile.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") +",";
+ }
+
+ bodyLog += "\";\"" + MediaType.MULTIPART_FORM_DATA_VALUE + "\"";
+ messageBuilderSupport.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
+ .body(multiValues);
+
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "postFile;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = filename;
+ }
+
+ public void setMultipartFile(String multipartFile) {
+ this.multipartFile = multipartFile;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "bucket" + "}", bucket);endpoint = endpoint.replace("{" + "filename" + "}", filename);
+ return endpoint;
+ }
+ }
+ /** postRandom (POST /api/v2/multitest-file/{bucket}/{filename}/random)
+ Uploads random file.
+
+ **/
+ public static class PostRandomRequest extends MultipartTestAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/api/v2/multitest-file/{bucket}/{filename}/random";
+ private final Logger coverageLogger = LoggerFactory.getLogger(PostRandomRequest.class);
+
+ private String bucket;
+
+ private String filename;
+
+
+ public PostRandomRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("MultipartTest".toLowerCase() + ":postRandomRequestType");
+ }
+
+ public String getOperationName() {
+ return "postRandom";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/api/v2/multitest-file/{bucket}/{filename}/random";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "postRandom;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = filename;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "bucket" + "}", bucket);endpoint = endpoint.replace("{" + "filename" + "}", filename);
+ return endpoint;
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/spring/MultipartTestBeanConfiguration.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/spring/MultipartTestBeanConfiguration.java
new file mode 100644
index 0000000000..d93b11f104
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/spring/MultipartTestBeanConfiguration.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.multiparttest.spring;
+
+import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
+
+import org.citrusframework.openapi.generator.rest.multiparttest.request.MultiparttestControllerApi;
+import javax.annotation.processing.Generated;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class MultipartTestBeanConfiguration {
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public MultiparttestControllerApi.DeleteObjectRequest deleteObjectRequest() {
+ return new MultiparttestControllerApi.DeleteObjectRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public MultiparttestControllerApi.FileExistsRequest fileExistsRequest() {
+ return new MultiparttestControllerApi.FileExistsRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public MultiparttestControllerApi.GenerateReportRequest generateReportRequest() {
+ return new MultiparttestControllerApi.GenerateReportRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public MultiparttestControllerApi.MultipleDatatypesRequest multipleDatatypesRequest() {
+ return new MultiparttestControllerApi.MultipleDatatypesRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public MultiparttestControllerApi.PostFileRequest postFileRequest() {
+ return new MultiparttestControllerApi.PostFileRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public MultiparttestControllerApi.PostRandomRequest postRandomRequest() {
+ return new MultiparttestControllerApi.PostRandomRequest();
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/PetStoreAbstractTestRequest.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/PetStoreAbstractTestRequest.java
new file mode 100644
index 0000000000..1e9282b44b
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/PetStoreAbstractTestRequest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.petstore.citrus;
+
+
+import static org.springframework.util.CollectionUtils.isEmpty;
+
+import jakarta.annotation.Generated;
+import jakarta.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import javax.sql.DataSource;
+import org.citrusframework.actions.AbstractTestAction;
+import org.citrusframework.actions.ReceiveMessageAction;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.http.actions.HttpActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder;
+import org.citrusframework.http.actions.HttpClientResponseActionBuilder;
+import org.citrusframework.http.actions.HttpClientResponseActionBuilder.HttpMessageBuilderSupport;
+import org.citrusframework.http.client.HttpClient;
+import org.citrusframework.message.Message;
+import org.citrusframework.testapi.ApiActionBuilderCustomizerService;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.validation.DelegatingPayloadVariableExtractor;
+import org.citrusframework.validation.PathExpressionValidationContext;
+import org.citrusframework.validation.json.JsonMessageValidationContext;
+import org.citrusframework.validation.script.ScriptValidationContext;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public abstract class PetStoreAbstractTestRequest extends AbstractTestAction {
+
+ protected final Marker coverageMarker = MarkerFactory.getMarker("PETSTORE-API-COVERAGE");
+
+ @Autowired
+ @Qualifier("petStoreEndpoint")
+ protected HttpClient httpClient;
+
+ @Autowired(required = false)
+ protected DataSource dataSource;
+
+ @Autowired(required = false)
+ private List actionBuilderCustomizerServices;
+
+ // attributes of differentNodes
+ protected boolean schemaValidation;
+ protected String schema;
+ protected String bodyContentType;
+ protected String bodyLiteralContentType;
+ protected String bodyFile;
+ protected String bodyLiteral;
+ protected String responseAcceptType = "*/*";
+ protected String responseType = "json";
+ protected int responseStatus = 200;
+ protected String responseReasonPhrase = "OK";
+ protected String responseVersion = "HTTP/1.1";
+
+ // children of response element
+ protected String resource;
+ protected Map responseVariable; // Contains the 'JSON-PATH' as key and the 'VARIABLE NAME' as value
+ protected Map responseValue; // Contains the 'JSON-PATH' as key and the 'VALUE TO BE VALIDATED' as value
+ protected Map cookies;
+ protected Map headers;
+ protected String script;
+ protected String type; // default script type is groovy - supported types see com.consol.citrus.script.ScriptTypes
+
+ @Override
+ public void doExecute(TestContext context) {
+ sendRequest(context);
+ recieveResponse(context);
+ }
+
+ /**
+ * This method receives the HTTP-Response.
+ *
+ * @deprecated use {@link PetStoreAbstractTestRequest#receiveResponse(TestContext)} instead.
+ */
+ public ReceiveMessageAction recieveResponse(TestContext context) {
+
+ HttpClientResponseActionBuilder httpClientResponseActionBuilder = new HttpActionBuilder().client(httpClient).receive().response();
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientResponseActionBuilder.getMessageBuilderSupport();
+
+ messageBuilderSupport
+ .statusCode(responseStatus)
+ .reasonPhrase(responseReasonPhrase)
+ .version(responseVersion)
+ .validate(new JsonMessageValidationContext.Builder().schemaValidation(schemaValidation).schema(schema));
+
+ if (resource != null) {
+ messageBuilderSupport.body(Resources.create(resource));
+ }
+
+ if (!isEmpty(responseVariable)) {
+ DelegatingPayloadVariableExtractor.Builder extractorBuilder = new DelegatingPayloadVariableExtractor.Builder();
+ responseVariable.forEach(extractorBuilder::expression);
+ messageBuilderSupport.extract(extractorBuilder);
+ }
+
+ if (!isEmpty(responseValue)) {
+ PathExpressionValidationContext.Builder validationContextBuilder = new PathExpressionValidationContext.Builder();
+ responseValue.forEach(validationContextBuilder::expression);
+ messageBuilderSupport.validate(validationContextBuilder);
+ }
+
+ if (script != null) {
+ ScriptValidationContext.Builder scriptValidationContextBuilder = new ScriptValidationContext.Builder();
+ if (type != null) {
+ scriptValidationContextBuilder.scriptType(type);
+ }
+ scriptValidationContextBuilder.script(script);
+ messageBuilderSupport.validate(scriptValidationContextBuilder);
+ }
+
+ messageBuilderSupport.type(responseType);
+ httpClientResponseActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ var responseAction = httpClientResponseActionBuilder.build();
+
+ responseAction.execute(context);
+
+ return responseAction;
+ }
+
+ public @Nullable Message receiveResponse(TestContext context) {
+ var responseAction = recieveResponse(context);
+
+ var messageStore = context.getMessageStore();
+ return messageStore.getMessage(messageStore.constructMessageName(responseAction, httpClient));
+ }
+
+ public abstract void sendRequest(TestContext context);
+
+ public void setSchemaValidation(boolean schemaValidation) {
+ this.schemaValidation = schemaValidation;
+ }
+
+ public void setSchema(String schema) {
+ this.schema = schema;
+ }
+
+ public void setBodyLiteral(String bodyLiteral) {
+ this.bodyLiteral = bodyLiteral;
+ }
+
+ public void setBodyContentType(String bodyContentType) {
+ this.bodyContentType = bodyContentType;
+ }
+
+ public void setBodyLiteralContentType(String bodyLiteralContentType) {
+ this.bodyLiteralContentType = bodyLiteralContentType;
+ }
+
+ public void setResponseAcceptType(String responseAcceptType) {
+ this.responseAcceptType = responseAcceptType;
+ }
+
+ public void setCookie(Map cookies) {
+ this.cookies = cookies;
+ }
+
+ public void setHeader(Map headers) {
+ this.headers = headers;
+ }
+
+ public void setBodyFile(String bodyFile) {
+ this.bodyFile = bodyFile;
+ }
+
+ public void setResponseType(String responseType) {
+ this.responseType = responseType;
+ }
+
+ public void setResponseStatus(int responseStatus) {
+ this.responseStatus = responseStatus;
+ }
+
+ public void setResponseReasonPhrase(String responseReasonPhrase) {
+ this.responseReasonPhrase = responseReasonPhrase;
+ }
+
+ public void setResponseVersion(String responseVersion) {
+ this.responseVersion = responseVersion;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public void setResponseVariable(Map responseVariable) {
+ this.responseVariable = responseVariable;
+ }
+
+ public void setResponseValue(Map responseValue) {
+ this.responseValue = responseValue;
+ }
+
+ public void setScript(String script) {
+ this.script = script;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ protected HttpClientRequestActionBuilder customizeBuilder(GeneratedApi generatedApi,
+ TestContext context, HttpClientRequestActionBuilder httpClientRequestActionBuilder) {
+
+ httpClientRequestActionBuilder = customizeByBeans(generatedApi, context,
+ httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder = customizeBySpi(generatedApi, context, httpClientRequestActionBuilder);
+
+ return httpClientRequestActionBuilder;
+ }
+
+ private HttpClientRequestActionBuilder customizeBySpi(GeneratedApi generatedApi, TestContext context,
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder) {
+ ServiceLoader serviceLoader = ServiceLoader.load(
+ ApiActionBuilderCustomizerService.class, ApiActionBuilderCustomizerService.class.getClassLoader());
+ for (ApiActionBuilderCustomizerService service :serviceLoader) {
+ httpClientRequestActionBuilder = service.build(generatedApi, this, context, httpClientRequestActionBuilder);
+ }
+ return httpClientRequestActionBuilder;
+ }
+
+ private HttpClientRequestActionBuilder customizeByBeans(
+ GeneratedApi generatedApi, TestContext context,
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder) {
+ if (actionBuilderCustomizerServices != null) {
+ for (ApiActionBuilderCustomizerService apiActionBuilderCustomizer : actionBuilderCustomizerServices) {
+ httpClientRequestActionBuilder = apiActionBuilderCustomizer.build(generatedApi, this,
+ context, httpClientRequestActionBuilder);
+ }
+ }
+ return httpClientRequestActionBuilder;
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/PetStoreBeanDefinitionParser.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/PetStoreBeanDefinitionParser.java
new file mode 100644
index 0000000000..b52f5b5f42
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/PetStoreBeanDefinitionParser.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.petstore.citrus;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.processing.Generated;
+
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.core.Conventions;
+import org.springframework.util.Assert;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class PetStoreBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String COOKIE = "cookie";
+ private static final String HEADER = "header";
+ private static final String SOAP_HEADER = "soapHeader";
+ private static final String MIME_HEADER = "mimeHeader";
+ private static final String NAME = "name";
+ private static final String REQUEST_BODY = "body";
+ private static final String REQUEST_BODY_LITERAL = "bodyLiteral";
+ private static final String MULTIPART_BODY = "multipartBody";
+ private static final String RESPONSE = "response";
+ private static final String RESPONSE_JSONPATH = "json-path";
+ private static final String RESPONSE_XPATH = "xpath";
+ private static final String EXPRESSION = "expression";
+ private static final String VALUE = "value";
+ private static final String RESPONSE_RESOURCE = "resource";
+ private static final String FILE = "file";
+ private static final String RESPONSE_VARIABLE = "responseVariable";
+ private static final String RESPONSE_VALUE = "responseValue";
+ private static final String SCRIPT = "script";
+ private static final String TYPE = "type";
+ private static final String SQL = "sql";
+ private static final String COLUMN = "column";
+ private static final String VARIABLE = "variable";
+ // new
+ private static final String SCHEMA = "schema";
+ // new
+ private static final String SCHEMA_VALIDATION = "schemaValidation";
+
+ private final Class> beanClass;
+
+ public PetStoreBeanDefinitionParser(Class> beanClass) {
+ this.beanClass = beanClass;
+ }
+
+ public BeanDefinition parse(Element element) {
+ return parse(element, null);
+ }
+
+ /**
+ * Note: The {@link PetStoreBeanDefinitionParser#parse(Element element)} allows access direct
+ * access without the {@link org.springframework.beans.factory.xml.ParserContext} for convenience.
+ */
+ @Override
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
+ retrieveRootNodeAttributes(element, builder);
+ retrieveOptionalNodeAttributes(element, REQUEST_BODY, builder);
+ retrieveTextContentAndNodeAttributes(element, REQUEST_BODY_LITERAL, builder);
+ retrieveOptionalNodeAttributes(element, RESPONSE, builder);
+ retrieveParamNodeData(element, builder, COOKIE);
+ retrieveParamNodeData(element, builder, HEADER);
+ retrieveParamNodeData(element, builder, SOAP_HEADER);
+ retrieveParamNodeData(element, builder, MIME_HEADER);
+ retrieveOptionalNodeAttributes(element, SCHEMA, builder);
+ retrieveOptionalNodeAttributes(element, SCHEMA_VALIDATION, builder);
+ retrieveOptionalMultipartElements(element, builder);
+ retrieveResponseNodeData(element, builder);
+ builder.addPropertyValue("name", element.getTagName());
+ return builder.getBeanDefinition();
+ }
+
+ private void retrieveOptionalMultipartElements(Element element, BeanDefinitionBuilder builder) {
+ var multipartBodyElement = DomUtils.getChildElementByTagName(element, MULTIPART_BODY);
+ if (multipartBodyElement != null) {
+ var multipartBodyChildElements = DomUtils.getChildElements(multipartBodyElement);
+ for(int i = 0; i < multipartBodyChildElements.size(); i++){
+ var multipartBodyChildElement = multipartBodyChildElements.get(i);
+ String propertyName = Conventions.attributeNameToPropertyName(multipartBodyChildElement.getLocalName());
+ builder.addPropertyValue(propertyName, multipartBodyChildElement.getTextContent());
+ }
+ }
+ }
+
+ private void retrieveRootNodeAttributes(Element element, BeanDefinitionBuilder builder) {
+ NamedNodeMap attributes = element.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName), "Illegal property name returned, it must not be null or empty.");
+ builder.addPropertyValue(propertyName, attribute.getValue());
+ }
+ }
+
+ private void retrieveOptionalNodeAttributes(Element element, String elementName, BeanDefinitionBuilder builder) {
+ if (!DomUtils.getChildElementsByTagName(element, elementName).isEmpty()) {
+ Element el = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ NamedNodeMap attributes = el.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName), "Illegal property name returned, it must not be null or empty.");
+ String variableName = el.getLocalName() + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
+ builder.addPropertyValue(variableName, attribute.getValue());
+ }
+ }
+ }
+
+ private void retrieveTextContentAndNodeAttributes(Element element, String elementName, BeanDefinitionBuilder builder) {
+ if (!DomUtils.getChildElementsByTagName(element, elementName).isEmpty()) {
+ Element el1 = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ NamedNodeMap attributes = el1.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName1 = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName1), "Illegal property name returned, it must not be null or empty.");
+ String variableName = el1.getLocalName() + propertyName1.substring(0, 1).toUpperCase() + propertyName1.substring(1);
+ builder.addPropertyValue(variableName, attribute.getValue());
+ }
+ Element el = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ builder.addPropertyValue(elementName, el.getTextContent());
+ }
+ }
+
+ private void retrieveParamNodeData(Element element, BeanDefinitionBuilder builder, String paramType) {
+ if (!DomUtils.getChildElementsByTagName(element, paramType).isEmpty()) {
+ Map params = new HashMap<>();
+ List elements = DomUtils.getChildElementsByTagName(element, paramType);
+ elements.forEach(e -> {
+ String name = e.getAttribute(NAME);
+ String value = e.getAttribute(VALUE);
+
+ Assert.state(StringUtils.isNotBlank(name), "Illegal attribute value returned. The 'name' attribute must not be null or empty.");
+ Assert.state(StringUtils.isNotBlank(value), "Illegal attribute value returned. The 'value' attribute must not be null or empty.");
+
+ params.put(name, value);
+ });
+ builder.addPropertyValue(paramType, params);
+ }
+ }
+
+ private void retrieveResponseNodeData(Element element, BeanDefinitionBuilder builder) {
+
+ if (!DomUtils.getChildElementsByTagName(element, RESPONSE).isEmpty()) {
+ Element response = DomUtils.getChildElementsByTagName(element, RESPONSE).get(0);
+ List elements = DomUtils.getChildElements(response);
+
+ Map responseVariable = new HashMap<>();
+ Map responseValue = new HashMap<>();
+
+ for (int i = 0; i < elements.size(); i++) {
+ Element e = elements.get(i);
+
+ if (e.getTagName().contains(RESPONSE_JSONPATH) || e.getTagName().contains(RESPONSE_XPATH)) {
+ String expression = e.getAttribute(EXPRESSION);
+ String value = e.getAttribute(VALUE);
+
+ Assert.state(StringUtils.isNotBlank(expression), "Illegal attribute value returned. The 'expression' attribute must not be null or empty.");
+ Assert.state(StringUtils.isNotBlank(value), "Illegal attribute value returned. The 'value' attribute must not be null or empty.");
+
+ // variable to save @variable('ebid')@ else value to validate
+ if (value.matches("\\@variable\\('.*'\\)\\@")) {
+ Matcher match = Pattern.compile("\\'(.*?)\\'").matcher(value);
+ if (match.find()) {
+ responseVariable.put(expression, value.substring(match.start() + 1, match.end() - 1));
+ }
+ } else {
+ responseValue.put(expression, value);
+ }
+ } else if (e.getTagName().contains(SCRIPT)) {
+ String script = e.getTextContent();
+ Assert.state(StringUtils.isNotBlank(script), "Illegal attribute value returned. The 'script' attribute must not be null or empty.");
+ builder.addPropertyValue(SCRIPT, script);
+
+ if (!e.getAttribute(TYPE).isEmpty()) {
+ String type = e.getAttribute(TYPE);
+ Assert.state(StringUtils.isNotBlank(type), "Illegal attribute value returned. The 'type' attribute must not be null or empty.");
+ builder.addPropertyValue(TYPE, type);
+ }
+ } else if (e.getTagName().contains(RESPONSE_RESOURCE)) {
+ String filePath = e.getAttribute(FILE);
+ Assert.state(StringUtils.isNotBlank(filePath), "Illegal attribute value returned. The 'file' attribute must not be null or empty.");
+ builder.addPropertyValue(RESPONSE_RESOURCE, filePath);
+ }
+
+ }
+
+ builder.addPropertyValue(RESPONSE_VARIABLE, responseVariable);
+ builder.addPropertyValue(RESPONSE_VALUE, responseValue);
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/extension/PetStoreNamespaceHandler.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/extension/PetStoreNamespaceHandler.java
new file mode 100644
index 0000000000..1382acba99
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/citrus/extension/PetStoreNamespaceHandler.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.petstore.citrus.extension;
+
+import org.citrusframework.openapi.generator.rest.petstore.request.StoreApi;
+import org.citrusframework.openapi.generator.rest.petstore.request.UserApi;
+import org.citrusframework.openapi.generator.rest.petstore.citrus.PetStoreBeanDefinitionParser;
+
+import javax.annotation.processing.Generated;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class PetStoreNamespaceHandler extends NamespaceHandlerSupport {
+
+ @Override
+ public void init() {
+ registerBeanDefinitionParser("addPetRequest", new PetStoreBeanDefinitionParser(PetApi.AddPetRequest.class));
+ registerBeanDefinitionParser("deletePetRequest", new PetStoreBeanDefinitionParser(PetApi.DeletePetRequest.class));
+ registerBeanDefinitionParser("findPetsByStatusRequest", new PetStoreBeanDefinitionParser(PetApi.FindPetsByStatusRequest.class));
+ registerBeanDefinitionParser("findPetsByTagsRequest", new PetStoreBeanDefinitionParser(PetApi.FindPetsByTagsRequest.class));
+ registerBeanDefinitionParser("getPetByIdRequest", new PetStoreBeanDefinitionParser(PetApi.GetPetByIdRequest.class));
+ registerBeanDefinitionParser("updatePetRequest", new PetStoreBeanDefinitionParser(PetApi.UpdatePetRequest.class));
+ registerBeanDefinitionParser("updatePetWithFormRequest", new PetStoreBeanDefinitionParser(PetApi.UpdatePetWithFormRequest.class));
+ registerBeanDefinitionParser("uploadFileRequest", new PetStoreBeanDefinitionParser(PetApi.UploadFileRequest.class));
+ registerBeanDefinitionParser("deleteOrderRequest", new PetStoreBeanDefinitionParser(StoreApi.DeleteOrderRequest.class));
+ registerBeanDefinitionParser("getInventoryRequest", new PetStoreBeanDefinitionParser(StoreApi.GetInventoryRequest.class));
+ registerBeanDefinitionParser("getOrderByIdRequest", new PetStoreBeanDefinitionParser(StoreApi.GetOrderByIdRequest.class));
+ registerBeanDefinitionParser("placeOrderRequest", new PetStoreBeanDefinitionParser(StoreApi.PlaceOrderRequest.class));
+ registerBeanDefinitionParser("createUserRequest", new PetStoreBeanDefinitionParser(UserApi.CreateUserRequest.class));
+ registerBeanDefinitionParser("createUsersWithArrayInputRequest", new PetStoreBeanDefinitionParser(UserApi.CreateUsersWithArrayInputRequest.class));
+ registerBeanDefinitionParser("createUsersWithListInputRequest", new PetStoreBeanDefinitionParser(UserApi.CreateUsersWithListInputRequest.class));
+ registerBeanDefinitionParser("deleteUserRequest", new PetStoreBeanDefinitionParser(UserApi.DeleteUserRequest.class));
+ registerBeanDefinitionParser("getUserByNameRequest", new PetStoreBeanDefinitionParser(UserApi.GetUserByNameRequest.class));
+ registerBeanDefinitionParser("loginUserRequest", new PetStoreBeanDefinitionParser(UserApi.LoginUserRequest.class));
+ registerBeanDefinitionParser("logoutUserRequest", new PetStoreBeanDefinitionParser(UserApi.LogoutUserRequest.class));
+ registerBeanDefinitionParser("updateUserRequest", new PetStoreBeanDefinitionParser(UserApi.UpdateUserRequest.class));
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Category.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Category.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Category.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/ModelApiResponse.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/ModelApiResponse.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/ModelApiResponse.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Order.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Order.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Order.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Pet.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Pet.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Pet.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Tag.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Tag.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/Tag.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/User.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/User.java
new file mode 100644
index 0000000000..d5341fea2c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/model/User.java
@@ -0,0 +1 @@
+// not in use
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/PetApi.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/PetApi.java
new file mode 100644
index 0000000000..92a8b3fe96
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/PetApi.java
@@ -0,0 +1,93 @@
+package org.citrusframework.openapi.generator.rest.petstore.request;
+
+import org.citrusframework.endpoint.Endpoint;
+import org.citrusframework.http.client.HttpClient;
+import org.citrusframework.openapi.OpenApiSpecification;
+import org.citrusframework.openapi.actions.OpenApiClientActionBuilder;
+import org.citrusframework.openapi.actions.OpenApiClientActionBuilder.OpenApiOperationBuilder;
+import org.citrusframework.openapi.actions.OpenApiClientRequestActionBuilder;
+import org.citrusframework.openapi.actions.OpenApiClientResponseActionBuilder;
+
+import java.util.function.UnaryOperator;
+
+import static org.citrusframework.spi.Resources.create;
+
+public class PetApi {
+ private static final OpenApiSpecification petstoreSpec = OpenApiSpecification.from(
+ create("src/test/resources/apis/petstore.yaml")
+ );
+
+ public static PetApi openapiPetstore(HttpClient httpClient) {
+ return new PetApi(httpClient);
+ }
+
+ private final HttpClient httpClient;
+
+ private PetApi(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+ public PetstoreAction getPetById() {
+ return petstoreAction(new GetPetByIdRequest());
+ }
+
+ private PetstoreAction petstoreAction(B requestBuilder) {
+ return new PetstoreAction<>(httpClient, petstoreSpec, requestBuilder);
+ }
+
+ /**
+ * getPetById (GET /pet/{petId})
+ * Find pet by ID
+ **/
+ public static class GetPetByIdRequest extends OperationRequestBuilder {
+ @Override
+ public String getOperationId() {
+ return "getPetById";
+ }
+
+ public GetPetByIdRequest withPetId(String petId) {
+ openApiOperation.withParameter("petId", petId);
+ return this;
+ }
+
+ public GetPetByIdRequest withCorrelationIds(String correlationIds) {
+ openApiOperation.withParameter("correlationIds", correlationIds);
+ return this;
+ }
+
+ public GetPetByIdRequest withVerbose(boolean verbose) {
+ openApiOperation.withParameter("verbose", verbose);
+ return this;
+ }
+ }
+
+ public static abstract class OperationRequestBuilder {
+ protected final OpenApiOperationBuilder openApiOperation = OpenApiOperationBuilder.operation(getOperationId());
+
+ public abstract String getOperationId();
+
+ public OpenApiOperationBuilder build() {
+ return openApiOperation;
+ }
+ }
+
+ public static class PetstoreAction extends OpenApiClientActionBuilder {
+ private final T operation;
+
+ private PetstoreAction(Endpoint httpClient, OpenApiSpecification specification, T operation) {
+ super(httpClient, specification);
+ this.operation = operation;
+ }
+
+ public OpenApiClientRequestActionBuilder send(UnaryOperator builderProvider) {
+ var builder = builderProvider.apply(operation);
+ var send = send(builder.build());
+ send.fork(true);
+ return send;
+ }
+
+ public OpenApiClientResponseActionBuilder receive() {
+ return receive(operation.getOperationId(), "200");
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/StoreApi.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/StoreApi.java
new file mode 100644
index 0000000000..e8062b4fb0
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/StoreApi.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.petstore.request;
+
+import jakarta.annotation.Generated;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.testapi.GeneratedApiRequest;
+import jakarta.servlet.http.Cookie;
+import org.apache.commons.lang3.StringUtils;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.http.actions.HttpActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder.HttpMessageBuilderSupport;
+import org.citrusframework.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import org.citrusframework.openapi.generator.rest.petstore.citrus.PetStoreAbstractTestRequest;
+
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class StoreApi implements GeneratedApi
+{
+
+ public static final StoreApi INSTANCE = new StoreApi();
+
+ public String getApiTitle() {
+ return "OpenAPI Petstore";
+ }
+
+ public String getApiVersion() {
+ return "1.0.0";
+ }
+
+ public String getApiPrefix() {
+ return "PetStore";
+ }
+
+ public Map getApiInfoExtensions() {
+ Map infoExtensionMap = new HashMap<>();
+ infoExtensionMap.put("x-citrus-api-name", "petstore");
+ infoExtensionMap.put("x-citrus-app", "PETS");
+ return infoExtensionMap;
+ }
+
+ /** deleteOrder (DELETE /store/order/{order_id})
+ Delete purchase order by ID
+
+ **/
+ public static class DeleteOrderRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/store/order/{order_id}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(DeleteOrderRequest.class);
+
+ private String orderId;
+
+
+ public DeleteOrderRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":deleteOrderRequestType");
+ }
+
+ public String getOperationName() {
+ return "deleteOrder";
+ }
+
+ public String getMethod() {
+ return "DELETE";
+ }
+
+ public String getPath() {
+ return "/store/order/{order_id}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .delete(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "deleteOrder;DELETE;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "order_id" + "}", orderId);
+ return endpoint;
+ }
+ }
+ /** getInventory (GET /store/inventory)
+ Returns pet inventories by status
+
+ **/
+ public static class GetInventoryRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/store/inventory";
+ private final Logger coverageLogger = LoggerFactory.getLogger(GetInventoryRequest.class);
+
+
+ public GetInventoryRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":getInventoryRequestType");
+ }
+
+ public String getOperationName() {
+ return "getInventory";
+ }
+
+ public String getMethod() {
+ return "GET";
+ }
+
+ public String getPath() {
+ return "/store/inventory";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .get(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "getInventory;GET;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** getOrderById (GET /store/order/{order_id})
+ Find purchase order by ID
+
+ **/
+ public static class GetOrderByIdRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/store/order/{order_id}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(GetOrderByIdRequest.class);
+
+ private String orderId;
+
+
+ public GetOrderByIdRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":getOrderByIdRequestType");
+ }
+
+ public String getOperationName() {
+ return "getOrderById";
+ }
+
+ public String getMethod() {
+ return "GET";
+ }
+
+ public String getPath() {
+ return "/store/order/{order_id}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .get(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "getOrderById;GET;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "order_id" + "}", orderId);
+ return endpoint;
+ }
+ }
+ /** placeOrder (POST /store/order)
+ Place an order for a pet
+
+ **/
+ public static class PlaceOrderRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/store/order";
+ private final Logger coverageLogger = LoggerFactory.getLogger(PlaceOrderRequest.class);
+
+
+ public PlaceOrderRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":placeOrderRequestType");
+ }
+
+ public String getOperationName() {
+ return "placeOrder";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/store/order";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "placeOrder;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/UserApi.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/UserApi.java
new file mode 100644
index 0000000000..d52e4351f1
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/request/UserApi.java
@@ -0,0 +1,835 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.petstore.request;
+
+import jakarta.annotation.Generated;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.testapi.GeneratedApiRequest;
+import jakarta.servlet.http.Cookie;
+import org.apache.commons.lang3.StringUtils;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.http.actions.HttpActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder.HttpMessageBuilderSupport;
+import org.citrusframework.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import org.citrusframework.openapi.generator.rest.petstore.citrus.PetStoreAbstractTestRequest;
+
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class UserApi implements GeneratedApi
+{
+
+ public static final UserApi INSTANCE = new UserApi();
+
+ public String getApiTitle() {
+ return "OpenAPI Petstore";
+ }
+
+ public String getApiVersion() {
+ return "1.0.0";
+ }
+
+ public String getApiPrefix() {
+ return "PetStore";
+ }
+
+ public Map getApiInfoExtensions() {
+ Map infoExtensionMap = new HashMap<>();
+ infoExtensionMap.put("x-citrus-api-name", "petstore");
+ infoExtensionMap.put("x-citrus-app", "PETS");
+ return infoExtensionMap;
+ }
+
+ /** createUser (POST /user)
+ Create user
+
+ **/
+ public static class CreateUserRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user";
+ private final Logger coverageLogger = LoggerFactory.getLogger(CreateUserRequest.class);
+
+
+ public CreateUserRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":createUserRequestType");
+ }
+
+ public String getOperationName() {
+ return "createUser";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/user";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "createUser;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** createUsersWithArrayInput (POST /user/createWithArray)
+ Creates list of users with given input array
+
+ **/
+ public static class CreateUsersWithArrayInputRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/createWithArray";
+ private final Logger coverageLogger = LoggerFactory.getLogger(CreateUsersWithArrayInputRequest.class);
+
+
+ public CreateUsersWithArrayInputRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":createUsersWithArrayInputRequestType");
+ }
+
+ public String getOperationName() {
+ return "createUsersWithArrayInput";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/user/createWithArray";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "createUsersWithArrayInput;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** createUsersWithListInput (POST /user/createWithList)
+ Creates list of users with given input array
+
+ **/
+ public static class CreateUsersWithListInputRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/createWithList";
+ private final Logger coverageLogger = LoggerFactory.getLogger(CreateUsersWithListInputRequest.class);
+
+
+ public CreateUsersWithListInputRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":createUsersWithListInputRequestType");
+ }
+
+ public String getOperationName() {
+ return "createUsersWithListInput";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/user/createWithList";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .post(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "createUsersWithListInput;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** deleteUser (DELETE /user/{username})
+ Delete user
+
+ **/
+ public static class DeleteUserRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/{username}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(DeleteUserRequest.class);
+
+ private String username;
+
+
+ public DeleteUserRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":deleteUserRequestType");
+ }
+
+ public String getOperationName() {
+ return "deleteUser";
+ }
+
+ public String getMethod() {
+ return "DELETE";
+ }
+
+ public String getPath() {
+ return "/user/{username}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .delete(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "deleteUser;DELETE;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "username" + "}", username);
+ return endpoint;
+ }
+ }
+ /** getUserByName (GET /user/{username})
+ Get user by user name
+
+ **/
+ public static class GetUserByNameRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/{username}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(GetUserByNameRequest.class);
+
+ private String username;
+
+
+ public GetUserByNameRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":getUserByNameRequestType");
+ }
+
+ public String getOperationName() {
+ return "getUserByName";
+ }
+
+ public String getMethod() {
+ return "GET";
+ }
+
+ public String getPath() {
+ return "/user/{username}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .get(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "getUserByName;GET;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "username" + "}", username);
+ return endpoint;
+ }
+ }
+ /** loginUser (GET /user/login)
+ Logs user into the system
+
+ **/
+ public static class LoginUserRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/login";
+ private final Logger coverageLogger = LoggerFactory.getLogger(LoginUserRequest.class);
+
+ private String username;
+
+ private String password;
+
+
+ public LoginUserRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":loginUserRequestType");
+ }
+
+ public String getOperationName() {
+ return "loginUser";
+ }
+
+ public String getMethod() {
+ return "GET";
+ }
+
+ public String getPath() {
+ return "/user/login";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .get(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+
+ if (StringUtils.isNotBlank(this.username)) {
+ queryParams.put("username", context.replaceDynamicContentInString(this.username));
+ httpClientRequestActionBuilder.queryParam("username", this.username);
+ }
+
+
+ if (StringUtils.isNotBlank(this.password)) {
+ queryParams.put("password", context.replaceDynamicContentInString(this.password));
+ httpClientRequestActionBuilder.queryParam("password", this.password);
+ }
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "loginUser;GET;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** logoutUser (GET /user/logout)
+ Logs out current logged in user session
+
+ **/
+ public static class LogoutUserRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/logout";
+ private final Logger coverageLogger = LoggerFactory.getLogger(LogoutUserRequest.class);
+
+
+ public LogoutUserRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":logoutUserRequestType");
+ }
+
+ public String getOperationName() {
+ return "logoutUser";
+ }
+
+ public String getMethod() {
+ return "GET";
+ }
+
+ public String getPath() {
+ return "/user/logout";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .get(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "logoutUser;GET;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ private String replacePathParams(String endpoint) {
+
+ return endpoint;
+ }
+ }
+ /** updateUser (PUT /user/{username})
+ Updated user
+
+ **/
+ public static class UpdateUserRequest extends PetStoreAbstractTestRequest implements GeneratedApiRequest {
+
+ private static final String ENDPOINT = "/user/{username}";
+ private final Logger coverageLogger = LoggerFactory.getLogger(UpdateUserRequest.class);
+
+ private String username;
+
+
+ public UpdateUserRequest() {
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("PetStore".toLowerCase() + ":updateUserRequestType");
+ }
+
+ public String getOperationName() {
+ return "updateUser";
+ }
+
+ public String getMethod() {
+ return "PUT";
+ }
+
+ public String getPath() {
+ return "/user/{username}";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+ HttpClientRequestActionBuilder httpClientRequestActionBuilder = new HttpActionBuilder().client(httpClient).send()
+ .put(replacePathParams(ENDPOINT));
+
+ HttpMessageBuilderSupport messageBuilderSupport = httpClientRequestActionBuilder.getMessageBuilderSupport();
+ messageBuilderSupport.accept(responseAcceptType);
+
+ if (cookies != null) {
+ cookies.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ }
+
+ if (headers != null) {
+ headers.forEach((k, v) -> messageBuilderSupport.cookie(new Cookie(k, v)));
+ headers.forEach(messageBuilderSupport::header);
+ }
+
+ String bodyLog = "";
+ String payload = null;
+ String payloadType = null;
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ bodyLog = body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"";
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ httpClientRequestActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ httpClientRequestActionBuilder = customizeBuilder(INSTANCE, context, httpClientRequestActionBuilder);
+
+ httpClientRequestActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "updateUser;PUT;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ bodyLog);
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ private String replacePathParams(String endpoint) {
+ endpoint = endpoint.replace("{" + "username" + "}", username);
+ return endpoint;
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/spring/PetStoreBeanConfiguration.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/spring/PetStoreBeanConfiguration.java
new file mode 100644
index 0000000000..66dce7320c
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/petstore/spring/PetStoreBeanConfiguration.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.rest.petstore.spring;
+
+import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
+
+import org.citrusframework.openapi.generator.rest.petstore.request.StoreApi;
+import org.citrusframework.openapi.generator.rest.petstore.request.UserApi;
+import javax.annotation.processing.Generated;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class PetStoreBeanConfiguration {
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.AddPetRequest addPetRequest() {
+ return new PetApi.AddPetRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.DeletePetRequest deletePetRequest() {
+ return new PetApi.DeletePetRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.FindPetsByStatusRequest findPetsByStatusRequest() {
+ return new PetApi.FindPetsByStatusRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.FindPetsByTagsRequest findPetsByTagsRequest() {
+ return new PetApi.FindPetsByTagsRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.GetPetByIdRequest getPetByIdRequest() {
+ return new PetApi.GetPetByIdRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.UpdatePetRequest updatePetRequest() {
+ return new PetApi.UpdatePetRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.UpdatePetWithFormRequest updatePetWithFormRequest() {
+ return new PetApi.UpdatePetWithFormRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public PetApi.UploadFileRequest uploadFileRequest() {
+ return new PetApi.UploadFileRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public StoreApi.DeleteOrderRequest deleteOrderRequest() {
+ return new StoreApi.DeleteOrderRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public StoreApi.GetInventoryRequest getInventoryRequest() {
+ return new StoreApi.GetInventoryRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public StoreApi.GetOrderByIdRequest getOrderByIdRequest() {
+ return new StoreApi.GetOrderByIdRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public StoreApi.PlaceOrderRequest placeOrderRequest() {
+ return new StoreApi.PlaceOrderRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.CreateUserRequest createUserRequest() {
+ return new UserApi.CreateUserRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.CreateUsersWithArrayInputRequest createUsersWithArrayInputRequest() {
+ return new UserApi.CreateUsersWithArrayInputRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.CreateUsersWithListInputRequest createUsersWithListInputRequest() {
+ return new UserApi.CreateUsersWithListInputRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.DeleteUserRequest deleteUserRequest() {
+ return new UserApi.DeleteUserRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.GetUserByNameRequest getUserByNameRequest() {
+ return new UserApi.GetUserByNameRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.LoginUserRequest loginUserRequest() {
+ return new UserApi.LoginUserRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.LogoutUserRequest logoutUserRequest() {
+ return new UserApi.LogoutUserRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public UserApi.UpdateUserRequest updateUserRequest() {
+ return new UserApi.UpdateUserRequest();
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/OpenApiFromWsdlAbstractTestRequest.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/OpenApiFromWsdlAbstractTestRequest.java
new file mode 100644
index 0000000000..4e493250fc
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/OpenApiFromWsdlAbstractTestRequest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.soap.bookservice.citrus;
+
+import jakarta.annotation.Generated;
+import java.util.List;
+import java.util.ServiceLoader;
+import org.citrusframework.actions.AbstractTestAction;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.http.actions.HttpClientRequestActionBuilder;
+import org.citrusframework.testapi.ApiActionBuilderCustomizerService;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.validation.DelegatingPayloadVariableExtractor;
+import org.citrusframework.validation.PathExpressionValidationContext;
+import org.citrusframework.validation.script.ScriptValidationContext;
+import org.citrusframework.ws.actions.ReceiveSoapMessageAction;
+import org.citrusframework.ws.actions.ReceiveSoapMessageAction.SoapMessageBuilderSupport;
+import org.citrusframework.ws.actions.SendSoapMessageAction;
+import org.citrusframework.ws.actions.SoapActionBuilder;
+import org.citrusframework.ws.client.WebServiceClient;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.util.CollectionUtils;
+
+import javax.sql.DataSource;
+import java.util.Map;
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public abstract class OpenApiFromWsdlAbstractTestRequest extends AbstractTestAction {
+
+ protected final Marker coverageMarker = MarkerFactory.getMarker("OPENAPIFROMWSDL-API-COVERAGE");
+
+ @Autowired
+ @Qualifier("soapSampleEndpoint")
+ protected WebServiceClient wsClient;
+
+ @Autowired(required = false)
+ protected DataSource dataSource;
+
+ @Autowired(required = false)
+ private List actionBuilderCustomizerServices;
+
+ // attributes of differentNodes
+ protected String bodyContentType;
+ protected String bodyLiteralContentType;
+ protected String bodyFile;
+ protected String bodyLiteral;
+
+ // children of response element
+ protected String resource;
+ protected Map responseVariable; // Contains the 'XPATH' as key and the 'VARIABLE NAME' as value
+ protected Map responseValue; // Contains the 'XPATH' as key and the 'VALUE TO BE VALIDATED' as value
+ protected String script;
+ protected String type; // default script type is groovy - supported types see com.consol.citrus.script.ScriptTypes
+ protected Map soapHeaders;
+ protected Map mimeHeaders;
+
+ @Override
+ public void doExecute(TestContext context) {
+ sendRequest(context);
+ receiveResponse(context);
+ }
+
+ /**
+ * This method receives the HTTP-Response
+ */
+ public void receiveResponse(TestContext context) {
+
+ ReceiveSoapMessageAction.Builder soapReceiveMessageActionBuilder = new SoapActionBuilder().client(wsClient).receive();
+ SoapMessageBuilderSupport messageBuilderSupport = soapReceiveMessageActionBuilder.getMessageBuilderSupport();
+
+ if (resource != null) {
+ messageBuilderSupport.body(Resources.create(resource));
+ }
+
+ if (!CollectionUtils.isEmpty(responseVariable)) {
+ DelegatingPayloadVariableExtractor.Builder extractorBuilder = new DelegatingPayloadVariableExtractor.Builder();
+ responseVariable.forEach(extractorBuilder::expression);
+ messageBuilderSupport.extract(extractorBuilder);
+ }
+
+ if (!CollectionUtils.isEmpty(responseValue)) {
+ PathExpressionValidationContext.Builder validationContextBuilder = new PathExpressionValidationContext.Builder();
+ responseValue.forEach(validationContextBuilder::expression);
+ messageBuilderSupport.validate(validationContextBuilder);
+ }
+
+ if (script != null) {
+ ScriptValidationContext.Builder scriptValidationContextBuilder = new ScriptValidationContext.Builder();
+ if (type != null) {
+ scriptValidationContextBuilder.scriptType(type);
+ }
+ scriptValidationContextBuilder.script(script);
+ messageBuilderSupport.validate(scriptValidationContextBuilder);
+ }
+
+ soapReceiveMessageActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ soapReceiveMessageActionBuilder.build().execute(context);
+ }
+
+ public abstract void sendRequest(TestContext context);
+
+ public void setBodyLiteral(String bodyLiteral) {
+ this.bodyLiteral = bodyLiteral;
+ }
+ public void setBodyContentType(String bodyContentType) {
+ this.bodyContentType = bodyContentType;
+ }
+
+ public void setBodyLiteralContentType(String bodyLiteralContentType) {
+ this.bodyLiteralContentType = bodyLiteralContentType;
+ }
+
+ public void setBodyFile(String bodyFile) {
+ this.bodyFile = bodyFile;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public void setResponseVariable(Map responseVariable) {
+ this.responseVariable = responseVariable;
+ }
+
+ public void setResponseValue(Map responseValue) {
+ this.responseValue = responseValue;
+ }
+
+ public void setScript(String script) {
+ this.script = script;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public void setSoapHeader(Map soapHeaders) {
+ this.soapHeaders = soapHeaders;
+ }
+
+ public void setMimeHeader(Map mimeHeaders) {
+ this.mimeHeaders = mimeHeaders;
+ }
+
+ protected SendSoapMessageAction.Builder customizeBuilder(GeneratedApi generatedApi,
+ TestContext context, SendSoapMessageAction.Builder sendSoapMessageActionBuilder) {
+
+ sendSoapMessageActionBuilder = customizeByBeans(generatedApi, context, sendSoapMessageActionBuilder);
+
+ sendSoapMessageActionBuilder = customizeBySpi(generatedApi, context, sendSoapMessageActionBuilder);
+
+ return sendSoapMessageActionBuilder;
+ }
+
+ private SendSoapMessageAction.Builder customizeBySpi(GeneratedApi generatedApi, TestContext context,
+ SendSoapMessageAction.Builder sendSoapMessageActionBuilder) {
+
+ ServiceLoader serviceLoader = ServiceLoader.load(
+ ApiActionBuilderCustomizerService.class, ApiActionBuilderCustomizerService.class.getClassLoader());
+ for (ApiActionBuilderCustomizerService service :serviceLoader) {
+ sendSoapMessageActionBuilder = service.build(generatedApi, this, context, sendSoapMessageActionBuilder);
+ }
+
+ return sendSoapMessageActionBuilder;
+ }
+
+ private SendSoapMessageAction.Builder customizeByBeans(
+ GeneratedApi generatedApi, TestContext context, SendSoapMessageAction.Builder sendSoapMessageActionBuilder) {
+
+ if (actionBuilderCustomizerServices != null) {
+ for (ApiActionBuilderCustomizerService apiActionBuilderCustomizer : actionBuilderCustomizerServices) {
+ sendSoapMessageActionBuilder = apiActionBuilderCustomizer.build(generatedApi, this,
+ context, sendSoapMessageActionBuilder);
+ }
+ }
+
+ return sendSoapMessageActionBuilder;
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/OpenApiFromWsdlBeanDefinitionParser.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/OpenApiFromWsdlBeanDefinitionParser.java
new file mode 100644
index 0000000000..e59e1bc033
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/OpenApiFromWsdlBeanDefinitionParser.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.soap.bookservice.citrus;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.processing.Generated;
+
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.core.Conventions;
+import org.springframework.util.Assert;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class OpenApiFromWsdlBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String COOKIE = "cookie";
+ private static final String HEADER = "header";
+ private static final String SOAP_HEADER = "soapHeader";
+ private static final String MIME_HEADER = "mimeHeader";
+ private static final String NAME = "name";
+ private static final String REQUEST_BODY = "body";
+ private static final String REQUEST_BODY_LITERAL = "bodyLiteral";
+ private static final String MULTIPART_BODY = "multipartBody";
+ private static final String RESPONSE = "response";
+ private static final String RESPONSE_JSONPATH = "json-path";
+ private static final String RESPONSE_XPATH = "xpath";
+ private static final String EXPRESSION = "expression";
+ private static final String VALUE = "value";
+ private static final String RESPONSE_RESOURCE = "resource";
+ private static final String FILE = "file";
+ private static final String RESPONSE_VARIABLE = "responseVariable";
+ private static final String RESPONSE_VALUE = "responseValue";
+ private static final String SCRIPT = "script";
+ private static final String TYPE = "type";
+ private static final String SQL = "sql";
+ private static final String COLUMN = "column";
+ private static final String VARIABLE = "variable";
+ // new
+ private static final String SCHEMA = "schema";
+ // new
+ private static final String SCHEMA_VALIDATION = "schemaValidation";
+
+ private final Class> beanClass;
+
+ public OpenApiFromWsdlBeanDefinitionParser(Class> beanClass) {
+ this.beanClass = beanClass;
+ }
+
+ public BeanDefinition parse(Element element) {
+ return parse(element, null);
+ }
+
+ /**
+ * Note: The {@link OpenApiFromWsdlBeanDefinitionParser#parse(Element element)} allows access direct
+ * access without the {@link org.springframework.beans.factory.xml.ParserContext} for convenience.
+ */
+ @Override
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
+ retrieveRootNodeAttributes(element, builder);
+ retrieveOptionalNodeAttributes(element, REQUEST_BODY, builder);
+ retrieveTextContentAndNodeAttributes(element, REQUEST_BODY_LITERAL, builder);
+ retrieveOptionalNodeAttributes(element, RESPONSE, builder);
+ retrieveParamNodeData(element, builder, COOKIE);
+ retrieveParamNodeData(element, builder, HEADER);
+ retrieveParamNodeData(element, builder, SOAP_HEADER);
+ retrieveParamNodeData(element, builder, MIME_HEADER);
+ retrieveOptionalNodeAttributes(element, SCHEMA, builder);
+ retrieveOptionalNodeAttributes(element, SCHEMA_VALIDATION, builder);
+ retrieveOptionalMultipartElements(element, builder);
+ retrieveResponseNodeData(element, builder);
+ builder.addPropertyValue("name", element.getTagName());
+ return builder.getBeanDefinition();
+ }
+
+ private void retrieveOptionalMultipartElements(Element element, BeanDefinitionBuilder builder) {
+ var multipartBodyElement = DomUtils.getChildElementByTagName(element, MULTIPART_BODY);
+ if (multipartBodyElement != null) {
+ var multipartBodyChildElements = DomUtils.getChildElements(multipartBodyElement);
+ for(int i = 0; i < multipartBodyChildElements.size(); i++){
+ var multipartBodyChildElement = multipartBodyChildElements.get(i);
+ String propertyName = Conventions.attributeNameToPropertyName(multipartBodyChildElement.getLocalName());
+ builder.addPropertyValue(propertyName, multipartBodyChildElement.getTextContent());
+ }
+ }
+ }
+
+ private void retrieveRootNodeAttributes(Element element, BeanDefinitionBuilder builder) {
+ NamedNodeMap attributes = element.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName), "Illegal property name returned, it must not be null or empty.");
+ builder.addPropertyValue(propertyName, attribute.getValue());
+ }
+ }
+
+ private void retrieveOptionalNodeAttributes(Element element, String elementName, BeanDefinitionBuilder builder) {
+ if (!DomUtils.getChildElementsByTagName(element, elementName).isEmpty()) {
+ Element el = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ NamedNodeMap attributes = el.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName), "Illegal property name returned, it must not be null or empty.");
+ String variableName = el.getLocalName() + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
+ builder.addPropertyValue(variableName, attribute.getValue());
+ }
+ }
+ }
+
+ private void retrieveTextContentAndNodeAttributes(Element element, String elementName, BeanDefinitionBuilder builder) {
+ if (!DomUtils.getChildElementsByTagName(element, elementName).isEmpty()) {
+ Element el1 = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ NamedNodeMap attributes = el1.getAttributes();
+ for (int x = 0; x < attributes.getLength(); x++) {
+ Attr attribute = (Attr) attributes.item(x);
+ String propertyName1 = Conventions.attributeNameToPropertyName(attribute.getLocalName());
+ Assert.state(StringUtils.isNotBlank(propertyName1), "Illegal property name returned, it must not be null or empty.");
+ String variableName = el1.getLocalName() + propertyName1.substring(0, 1).toUpperCase() + propertyName1.substring(1);
+ builder.addPropertyValue(variableName, attribute.getValue());
+ }
+ Element el = DomUtils.getChildElementsByTagName(element, elementName).get(0);
+ builder.addPropertyValue(elementName, el.getTextContent());
+ }
+ }
+
+ private void retrieveParamNodeData(Element element, BeanDefinitionBuilder builder, String paramType) {
+ if (!DomUtils.getChildElementsByTagName(element, paramType).isEmpty()) {
+ Map params = new HashMap<>();
+ List elements = DomUtils.getChildElementsByTagName(element, paramType);
+ elements.forEach(e -> {
+ String name = e.getAttribute(NAME);
+ String value = e.getAttribute(VALUE);
+
+ Assert.state(StringUtils.isNotBlank(name), "Illegal attribute value returned. The 'name' attribute must not be null or empty.");
+ Assert.state(StringUtils.isNotBlank(value), "Illegal attribute value returned. The 'value' attribute must not be null or empty.");
+
+ params.put(name, value);
+ });
+ builder.addPropertyValue(paramType, params);
+ }
+ }
+
+ private void retrieveResponseNodeData(Element element, BeanDefinitionBuilder builder) {
+
+ if (!DomUtils.getChildElementsByTagName(element, RESPONSE).isEmpty()) {
+ Element response = DomUtils.getChildElementsByTagName(element, RESPONSE).get(0);
+ List elements = DomUtils.getChildElements(response);
+
+ Map responseVariable = new HashMap<>();
+ Map responseValue = new HashMap<>();
+
+ for (int i = 0; i < elements.size(); i++) {
+ Element e = elements.get(i);
+
+ if (e.getTagName().contains(RESPONSE_JSONPATH) || e.getTagName().contains(RESPONSE_XPATH)) {
+ String expression = e.getAttribute(EXPRESSION);
+ String value = e.getAttribute(VALUE);
+
+ Assert.state(StringUtils.isNotBlank(expression), "Illegal attribute value returned. The 'expression' attribute must not be null or empty.");
+ Assert.state(StringUtils.isNotBlank(value), "Illegal attribute value returned. The 'value' attribute must not be null or empty.");
+
+ // variable to save @variable('ebid')@ else value to validate
+ if (value.matches("\\@variable\\('.*'\\)\\@")) {
+ Matcher match = Pattern.compile("\\'(.*?)\\'").matcher(value);
+ if (match.find()) {
+ responseVariable.put(expression, value.substring(match.start() + 1, match.end() - 1));
+ }
+ } else {
+ responseValue.put(expression, value);
+ }
+ } else if (e.getTagName().contains(SCRIPT)) {
+ String script = e.getTextContent();
+ Assert.state(StringUtils.isNotBlank(script), "Illegal attribute value returned. The 'script' attribute must not be null or empty.");
+ builder.addPropertyValue(SCRIPT, script);
+
+ if (!e.getAttribute(TYPE).isEmpty()) {
+ String type = e.getAttribute(TYPE);
+ Assert.state(StringUtils.isNotBlank(type), "Illegal attribute value returned. The 'type' attribute must not be null or empty.");
+ builder.addPropertyValue(TYPE, type);
+ }
+ } else if (e.getTagName().contains(RESPONSE_RESOURCE)) {
+ String filePath = e.getAttribute(FILE);
+ Assert.state(StringUtils.isNotBlank(filePath), "Illegal attribute value returned. The 'file' attribute must not be null or empty.");
+ builder.addPropertyValue(RESPONSE_RESOURCE, filePath);
+ }
+
+ }
+
+ builder.addPropertyValue(RESPONSE_VARIABLE, responseVariable);
+ builder.addPropertyValue(RESPONSE_VALUE, responseValue);
+ }
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/extension/OpenApiFromWsdlNamespaceHandler.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/extension/OpenApiFromWsdlNamespaceHandler.java
new file mode 100644
index 0000000000..b844e884ca
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/citrus/extension/OpenApiFromWsdlNamespaceHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.soap.bookservice.citrus.extension;
+
+import org.citrusframework.openapi.generator.soap.bookservice.request.BookServiceSoapApi;
+import org.citrusframework.openapi.generator.soap.bookservice.citrus.OpenApiFromWsdlBeanDefinitionParser;
+
+import javax.annotation.processing.Generated;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class OpenApiFromWsdlNamespaceHandler extends NamespaceHandlerSupport {
+
+ @Override
+ public void init() {
+ registerBeanDefinitionParser("addBookRequest", new OpenApiFromWsdlBeanDefinitionParser(BookServiceSoapApi.AddBookRequest.class));
+ registerBeanDefinitionParser("getAllBooksRequest", new OpenApiFromWsdlBeanDefinitionParser(BookServiceSoapApi.GetAllBooksRequest.class));
+ registerBeanDefinitionParser("getBookRequest", new OpenApiFromWsdlBeanDefinitionParser(BookServiceSoapApi.GetBookRequest.class));
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/request/BookServiceSoapApi.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/request/BookServiceSoapApi.java
new file mode 100644
index 0000000000..f253418eec
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/request/BookServiceSoapApi.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.soap.bookservice.request;
+
+import jakarta.annotation.Generated;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.citrusframework.context.TestContext;
+import org.citrusframework.exceptions.CitrusRuntimeException;
+import org.citrusframework.testapi.GeneratedApi;
+import org.citrusframework.testapi.GeneratedApiRequest;
+import org.citrusframework.openapi.generator.soap.bookservice.citrus.OpenApiFromWsdlAbstractTestRequest;
+import org.citrusframework.spi.Resources;
+import org.citrusframework.util.FileUtils;
+import org.citrusframework.ws.actions.SendSoapMessageAction;
+import org.citrusframework.ws.actions.SendSoapMessageAction.Builder.SendSoapMessageBuilderSupport;
+import org.citrusframework.ws.actions.SoapActionBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+
+import org.citrusframework.openapi.generator.soap.bookservice.citrus.OpenApiFromWsdlAbstractTestRequest;
+
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class BookServiceSoapApi implements GeneratedApi
+{
+ public static final BookServiceSoapApi INSTANCE = new BookServiceSoapApi();
+
+ public String getApiTitle() {
+ return "Generated api from wsdl";
+ }
+
+ public String getApiVersion() {
+ return "1.0.0";
+ }
+
+ public String getApiPrefix() {
+ return "OpenApiFromWsdl";
+ }
+
+ public Map getApiInfoExtensions() {
+ Map infoExtensionMap = new HashMap<>();
+ return infoExtensionMap;
+ }
+
+ /**
+ addBook (POST /AddBook)
+
+
+ **/
+ public static class AddBookRequest extends OpenApiFromWsdlAbstractTestRequest implements GeneratedApiRequest {
+
+ private final Logger coverageLogger = LoggerFactory.getLogger(AddBookRequest.class);
+
+ // Query params
+
+
+ public AddBookRequest(){
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("OpenApiFromWsdl".toLowerCase() + ":addBookRequestType");
+ }
+
+ public String getOperationName() {
+ return "addBook";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/AddBook";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+
+ SendSoapMessageAction.Builder soapSendMessageActionBuilder = new SoapActionBuilder().client(wsClient).send();
+ SendSoapMessageBuilderSupport messageBuilderSupport = soapSendMessageActionBuilder.getMessageBuilderSupport();
+
+ messageBuilderSupport.soapAction("addBook");
+
+ String payload = null;
+ String payloadType = null;
+
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ if (!CollectionUtils.isEmpty(soapHeaders)) {
+ for (Entry entry : soapHeaders.entrySet()) {
+ messageBuilderSupport = messageBuilderSupport.header(entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ if (!CollectionUtils.isEmpty(mimeHeaders)) {
+ for (Entry entry : mimeHeaders.entrySet()) {
+ messageBuilderSupport = messageBuilderSupport.header("citrus_http_" + entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ soapSendMessageActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ soapSendMessageActionBuilder = customizeBuilder(INSTANCE, context, soapSendMessageActionBuilder);
+
+ soapSendMessageActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "addBook;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"");
+ }
+
+
+ }
+ /**
+ getAllBooks (POST /GetAllBooks)
+
+
+ **/
+ public static class GetAllBooksRequest extends OpenApiFromWsdlAbstractTestRequest implements GeneratedApiRequest {
+
+ private final Logger coverageLogger = LoggerFactory.getLogger(GetAllBooksRequest.class);
+
+ // Query params
+
+
+ public GetAllBooksRequest(){
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("OpenApiFromWsdl".toLowerCase() + ":getAllBooksRequestType");
+ }
+
+ public String getOperationName() {
+ return "getAllBooks";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/GetAllBooks";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+
+ SendSoapMessageAction.Builder soapSendMessageActionBuilder = new SoapActionBuilder().client(wsClient).send();
+ SendSoapMessageBuilderSupport messageBuilderSupport = soapSendMessageActionBuilder.getMessageBuilderSupport();
+
+ messageBuilderSupport.soapAction("getAllBooks");
+
+ String payload = null;
+ String payloadType = null;
+
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ if (!CollectionUtils.isEmpty(soapHeaders)) {
+ for (Entry entry : soapHeaders.entrySet()) {
+ messageBuilderSupport = messageBuilderSupport.header(entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ if (!CollectionUtils.isEmpty(mimeHeaders)) {
+ for (Entry entry : mimeHeaders.entrySet()) {
+ messageBuilderSupport = messageBuilderSupport.header("citrus_http_" + entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ soapSendMessageActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ soapSendMessageActionBuilder = customizeBuilder(INSTANCE, context, soapSendMessageActionBuilder);
+
+ soapSendMessageActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "getAllBooks;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"");
+ }
+
+
+ }
+ /**
+ getBook (POST /GetBook)
+
+
+ **/
+ public static class GetBookRequest extends OpenApiFromWsdlAbstractTestRequest implements GeneratedApiRequest {
+
+ private final Logger coverageLogger = LoggerFactory.getLogger(GetBookRequest.class);
+
+ // Query params
+
+
+ public GetBookRequest(){
+ // The name will be overwritten with the tag name using the actual namespace as prefix, when the class is loaded from xml
+ setName("OpenApiFromWsdl".toLowerCase() + ":getBookRequestType");
+ }
+
+ public String getOperationName() {
+ return "getBook";
+ }
+
+ public String getMethod() {
+ return "POST";
+ }
+
+ public String getPath() {
+ return "/GetBook";
+ }
+
+ /**
+ * This method sends the HTTP-Request
+ */
+ public void sendRequest(TestContext context) {
+
+ SendSoapMessageAction.Builder soapSendMessageActionBuilder = new SoapActionBuilder().client(wsClient).send();
+ SendSoapMessageBuilderSupport messageBuilderSupport = soapSendMessageActionBuilder.getMessageBuilderSupport();
+
+ messageBuilderSupport.soapAction("getBook");
+
+ String payload = null;
+ String payloadType = null;
+
+ if (StringUtils.isNotBlank(this.bodyFile)) {
+ try {
+ payload = FileUtils.readToString(Resources.create(this.bodyFile), FileUtils.getDefaultCharset());
+ } catch (IOException e) {
+ throw new CitrusRuntimeException("Failed to read payload resource", e);
+ }
+ payloadType = this.bodyContentType;
+ } else if (StringUtils.isNotBlank(this.bodyLiteral)) {
+ payload = this.bodyLiteral;
+ payloadType = this.bodyLiteralContentType;
+ }
+
+ String body = "";
+ String bodyType = "";
+ if(payload != null && payloadType != null) {
+ messageBuilderSupport.body(payload).contentType(payloadType);
+ body = context.replaceDynamicContentInString(payload);
+ bodyType = context.replaceDynamicContentInString(payloadType);
+ }
+
+ if (!CollectionUtils.isEmpty(soapHeaders)) {
+ for (Entry entry : soapHeaders.entrySet()) {
+ messageBuilderSupport = messageBuilderSupport.header(entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ if (!CollectionUtils.isEmpty(mimeHeaders)) {
+ for (Entry entry : mimeHeaders.entrySet()) {
+ messageBuilderSupport = messageBuilderSupport.header("citrus_http_" + entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ Map queryParams = new HashMap<>();
+
+ String query = queryParams.entrySet().stream().map(e -> "\"" + e.getKey() + "\":\"" + e.getValue() + "\"").collect(Collectors.joining(",", "{", "}"));
+
+ soapSendMessageActionBuilder.withReferenceResolver(context.getReferenceResolver());
+ soapSendMessageActionBuilder = customizeBuilder(INSTANCE, context, soapSendMessageActionBuilder);
+
+ soapSendMessageActionBuilder.build().execute(context);
+
+ coverageLogger.trace(coverageMarker, "getBook;POST;\"" +
+ query.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" +
+ body.replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\"\"") + "\";\"" + bodyType + "\"");
+ }
+
+
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/spring/OpenApiFromWsdlBeanConfiguration.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/spring/OpenApiFromWsdlBeanConfiguration.java
new file mode 100644
index 0000000000..919d03669b
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/soap/bookservice/spring/OpenApiFromWsdlBeanConfiguration.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * ==================================================
+ * GENERATED CLASS, ALL CHANGES WILL BE LOST
+ * ==================================================
+ */
+
+package org.citrusframework.openapi.generator.soap.bookservice.spring;
+
+import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
+
+import org.citrusframework.openapi.generator.soap.bookservice.request.BookServiceSoapApi;
+import javax.annotation.processing.Generated;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+@Generated(value = "org.citrusframework.openapi.generator.JavaCitrusCodegen")
+public class OpenApiFromWsdlBeanConfiguration {
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public BookServiceSoapApi.AddBookRequest addBookRequest() {
+ return new BookServiceSoapApi.AddBookRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public BookServiceSoapApi.GetAllBooksRequest getAllBooksRequest() {
+ return new BookServiceSoapApi.GetAllBooksRequest();
+ }
+
+ @Bean
+ @Scope(SCOPE_PROTOTYPE)
+ public BookServiceSoapApi.GetBookRequest getBookRequest() {
+ return new BookServiceSoapApi.GetBookRequest();
+ }
+}
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml b/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml
index 134d44aee9..defd001b40 100644
--- a/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml
@@ -36,12 +36,17 @@
+
org.citrusframework
citrus-test-api-generator-core
${project.version}
+
+ org.openapitools
+ openapi-generator
+
org.openapitools
openapi-generator-maven-plugin
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java
index 5b1d088727..9413a61a17 100644
--- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java
@@ -18,7 +18,9 @@
import static java.lang.String.format;
import static org.citrusframework.openapi.generator.JavaCitrusCodegen.CODEGEN_NAME;
+import static java.lang.String.format;
+import org.citrusframework.openapi.generator.JavaCitrusCodegen;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@@ -96,4 +98,5 @@ private void setPrivateField(String fieldName, Object fieldValue) throws MojoExe
format("Could not reflectively set field value '%s' for field '%s'", fieldValue, fieldName));
}
}
+
}
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java
index 4cccffe386..8026cbc03a 100644
--- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java
@@ -12,6 +12,7 @@
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.springframework.test.util.ReflectionTestUtils.getField;
+import jakarta.annotation.Nonnull;
import jakarta.validation.constraints.NotNull;
import java.io.File;
import java.io.FileWriter;
@@ -36,9 +37,10 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
-class TestApiGeneratorMojoIntegrationTest extends AbstractMojoTestCase {
+public class TestApiGeneratorMojoIntegrationTest extends AbstractMojoTestCase {
public static final String OTHER_META_FILE_CONTENT = "somenamespace=somevalue";
@@ -48,17 +50,17 @@ class TestApiGeneratorMojoIntegrationTest extends AbstractMojoTestCase {
* Array containing path templates for each generated file, specified with tokens. Tokens can be replaced with values of the respective
* testing scenario.
*/
- private static final String[] STANDARD_FILE_PATH_TEMPLATES = new String[]{
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/extension/%CAMEL_PREFIX%NamespaceHandler.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%AbstractTestRequest.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%BeanDefinitionParser.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/spring/%CAMEL_PREFIX%BeanConfiguration.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingReqType.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingRespType.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PingApi.java",
- "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PungApi.java",
- "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%SCHEMA_FOLDER%/%LOWER_PREFIX%-api.xsd",
- "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%LOWER_PREFIX%-api-model.csv"
+ private static final String[] STANDARD_FILE_PATH_TEMPLATES = new String[]{
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/extension/%CAMEL_PREFIX%NamespaceHandler.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%AbstractTestRequest.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%BeanDefinitionParser.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/spring/%CAMEL_PREFIX%BeanConfiguration.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingReqType.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingRespType.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PingApi.java",
+ "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PungApi.java",
+ "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%SCHEMA_FOLDER%/%LOWER_PREFIX%-api.xsd",
+ "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%LOWER_PREFIX%-api-model.csv"
};
/**
@@ -66,8 +68,8 @@ class TestApiGeneratorMojoIntegrationTest extends AbstractMojoTestCase {
* testing scenario.
*/
private static final String[] SPRING_META_FILE_TEMPLATES = new String[]{
- "%BASE_FOLDER%/%META_INF_FOLDER%/spring.handlers",
- "%BASE_FOLDER%/%META_INF_FOLDER%/spring.schemas"
+ "%BASE_FOLDER%/%META_INF_FOLDER%/spring.handlers",
+ "%BASE_FOLDER%/%META_INF_FOLDER%/spring.schemas"
};
private TestApiGeneratorMojo fixture;
@@ -78,31 +80,27 @@ void beforeEachSetup() throws Exception {
setUp();
}
- static Stream executeMojoWithConfigurations() {
+ public static Stream executeMojoWithConfigurations() {
return Stream.of(
- arguments("pom-missing-prefix",
- new MojoExecutionException("Required parameter 'prefix' not set for api at index '0'!")),
- arguments("pom-missing-source",
- new MojoExecutionException("Required parameter 'source' not set for api at index '0'!")),
- arguments("pom-minimal-config", null),
- arguments("pom-minimal-with-version-config", null),
- arguments("pom-multi-config", null),
- arguments("pom-full-config", null),
- arguments("pom-full-with-version-config", null),
- arguments("pom-soap-config", null)
+ arguments("pom-missing-prefix",
+ new MojoExecutionException("Required parameter 'prefix' not set for api at index '0'!")),
+ arguments("pom-missing-source",
+ new MojoExecutionException("Required parameter 'source' not set for api at index '0'!")),
+ arguments("pom-minimal-config", null),
+ arguments("pom-minimal-with-version-config", null),
+ arguments("pom-multi-config", null),
+ arguments("pom-full-config", null),
+ arguments("pom-full-with-version-config", null),
+ arguments("pom-soap-config", null)
);
}
@ParameterizedTest
@MethodSource
- void executeMojoWithConfigurations(String configName, Exception expectedException)
- throws Exception {
+ public void executeMojoWithConfigurations(String configName, Exception expectedException)
+ throws Exception {
- try {
- fixture = fixtureFromPom(configName);
- } catch (MojoExecutionException | MojoFailureException e) {
- Assertions.fail("Test setup failed!", e);
- }
+ fixture = fixtureFromPom(configName);
@SuppressWarnings("unchecked")
List apiConfigs = (List) getField(fixture, "apis");
@@ -124,10 +122,33 @@ void executeMojoWithConfigurations(String configName, Exception expectedExceptio
} else {
// When/Then
assertThatThrownBy(() -> fixture.execute()).isInstanceOf(expectedException.getClass())
- .hasMessage(expectedException.getMessage());
+ .hasMessage(expectedException.getMessage());
}
}
+ @ParameterizedTest
+ @CsvSource({
+ "api/PetApi.java"
+ })
+ public void testGenerateAndCompare(String fileName) throws Exception {
+ fixture = fixtureFromPom("pom-minimal-petstore");
+
+ fixture.execute();
+
+ assertThat(getGeneratedFile(fileName))
+ .isFile()
+ .exists()
+ .hasSameTextualContentAs(getExpectedFile(fileName));
+ }
+
+ private static File getGeneratedFile(String file) {
+ return new File("target/pom-minimal-pet/target/generated-test-sources/org/citrusframework/automation/minimal/" + file);
+ }
+
+ private static File getExpectedFile(String file) {
+ return new File("src/test/resources/expected/" + file);
+ }
+
/**
* Writes values to spring meta files, to make sure existing non generated and existing generated values are treated properly.
*/
@@ -197,7 +218,7 @@ private void assertSchemasInSpringSchemas(ApiConfig apiConfig) throws IOExceptio
String targetNamespace = replaceDynamicVarsToLowerCase(apiConfig.getTargetXmlnsNamespace(), apiConfig.getPrefix(), apiConfig.getVersion());
targetNamespace = targetNamespace.replace(":", "\\:");
- String schemaPath = replaceDynamicVarsToLowerCase((String)getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion());
+ String schemaPath = replaceDynamicVarsToLowerCase((String) getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion());
String text = String.format("%s.xsd=%s/%s-api.xsd", targetNamespace, schemaPath, apiConfig.getPrefix().toLowerCase());
@@ -221,13 +242,13 @@ private void assertApiType(ApiConfig apiConfig) throws IOException {
private void assertTargetNamespace(ApiConfig apiConfig) throws IOException {
assertThat(getContentOfFile(apiConfig, "-api.xsd")).contains(
- String.format("targetNamespace=\"%s\"",
- replaceDynamicVarsToLowerCase(apiConfig.getTargetXmlnsNamespace(), apiConfig.getPrefix(), apiConfig.getVersion())));
+ String.format("targetNamespace=\"%s\"",
+ replaceDynamicVarsToLowerCase(apiConfig.getTargetXmlnsNamespace(), apiConfig.getPrefix(), apiConfig.getVersion())));
}
private void assertEndpointName(ApiConfig apiConfig) throws IOException {
assertThat(getContentOfFile(apiConfig, "AbstractTestRequest")).contains(
- String.format("@Qualifier(\"%s\")", apiConfig.qualifiedEndpoint()));
+ String.format("@Qualifier(\"%s\")", apiConfig.qualifiedEndpoint()));
}
private String getContentOfFile(ApiConfig apiConfig, String fileIdentifier) throws IOException {
@@ -244,8 +265,8 @@ private String getContentOfFile(ApiConfig apiConfig, String fileIdentifier) thro
private String getTemplateContaining(String text) {
return concat(stream(STANDARD_FILE_PATH_TEMPLATES), stream(SPRING_META_FILE_TEMPLATES))
- .filter(path -> path.contains(text)).findFirst()
- .orElseThrow(() -> new AssertionError(String.format("Can't find file template with content: '%s'", text)));
+ .filter(path -> path.contains(text)).findFirst()
+ .orElseThrow(() -> new AssertionError(String.format("Can't find file template with content: '%s'", text)));
}
@NotNull
@@ -257,31 +278,31 @@ private String resolveFilePath(ApiConfig apiConfig, String filePathTemplate) {
String camelCasePrefix = new String(prefixCharArray);
String invokerFolder = toFolder(
- replaceDynamicVarsToLowerCase(apiConfig.getInvokerPackage(), apiConfig.getPrefix(), apiConfig.getVersion()));
+ replaceDynamicVarsToLowerCase(apiConfig.getInvokerPackage(), apiConfig.getPrefix(), apiConfig.getVersion()));
String modelFolder = toFolder(
- replaceDynamicVarsToLowerCase(apiConfig.getModelPackage(), apiConfig.getPrefix(), apiConfig.getVersion()));
+ replaceDynamicVarsToLowerCase(apiConfig.getModelPackage(), apiConfig.getPrefix(), apiConfig.getVersion()));
String requestFolder = toFolder(
- replaceDynamicVarsToLowerCase(apiConfig.getApiPackage(), apiConfig.getPrefix(), apiConfig.getVersion()));
+ replaceDynamicVarsToLowerCase(apiConfig.getApiPackage(), apiConfig.getPrefix(), apiConfig.getVersion()));
String schemaFolder = toFolder(
- replaceDynamicVars((String)getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion()));
+ replaceDynamicVars((String) getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion()));
String generatedSourcesFolder = toFolder(
- replaceDynamicVars((String)getField(fixture, "sourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion()));
+ replaceDynamicVars((String) getField(fixture, "sourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion()));
String generatedResourcesFolder = toFolder(
- replaceDynamicVars((String)getField(fixture, "resourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion()));
+ replaceDynamicVars((String) getField(fixture, "resourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion()));
return filePathTemplate
- .replace("%BASE_FOLDER%", fixture.getMavenProject().getBasedir().getPath())
- .replace("%TARGET_FOLDER%", fixture.getMavenProject().getBuild().getDirectory())
- .replace("%SOURCE_FOLDER%", fixture.getMavenProject().getBuild().getSourceDirectory())
- .replace("%GENERATED_SOURCES_FOLDER%", generatedSourcesFolder)
- .replace("%GENERATED_RESOURCES_FOLDER%", generatedResourcesFolder)
- .replace("%INVOKER_FOLDER%", invokerFolder)
- .replace("%MODEL_FOLDER%", modelFolder)
- .replace("%REQUEST_FOLDER%", requestFolder)
- .replace("%SCHEMA_FOLDER%", schemaFolder)
- .replace("%LOWER_PREFIX%", lowerCasePrefix)
- .replace("%CAMEL_PREFIX%", camelCasePrefix)
- .replace("%META_INF_FOLDER%", toFolder((String) getField(fixture, "metaInfFolder")));
+ .replace("%BASE_FOLDER%", fixture.getMavenProject().getBasedir().getPath())
+ .replace("%TARGET_FOLDER%", fixture.getMavenProject().getBuild().getDirectory())
+ .replace("%SOURCE_FOLDER%", fixture.getMavenProject().getBuild().getSourceDirectory())
+ .replace("%GENERATED_SOURCES_FOLDER%", generatedSourcesFolder)
+ .replace("%GENERATED_RESOURCES_FOLDER%", generatedResourcesFolder)
+ .replace("%INVOKER_FOLDER%", invokerFolder)
+ .replace("%MODEL_FOLDER%", modelFolder)
+ .replace("%REQUEST_FOLDER%", requestFolder)
+ .replace("%SCHEMA_FOLDER%", schemaFolder)
+ .replace("%LOWER_PREFIX%", lowerCasePrefix)
+ .replace("%CAMEL_PREFIX%", camelCasePrefix)
+ .replace("%META_INF_FOLDER%", toFolder((String) getField(fixture, "metaInfFolder")));
}
private String toFolder(String text) {
@@ -293,19 +314,25 @@ private String toFolder(String text) {
return text.replace(".", "/");
}
+ @Nonnull
private TestApiGeneratorMojo fixtureFromPom(String configName) throws Exception {
- String goal = "create-test-api";
+ try {
+ String goal = "create-test-api";
- File pomFile = new File(getBasedir(), String.format("src/test/resources/%s/%s", getClass().getSimpleName(), configName + ".xml"));
- assertThat(pomFile).exists();
+ File pomFile = new File(getBasedir(), String.format("src/test/resources/%s/%s", getClass().getSimpleName(), configName + ".xml"));
+ assertThat(pomFile).exists();
- MavenProject mavenProject = new CitrusOpenApiGeneratorMavenProjectStub(configName);
+ MavenProject mavenProject = new CitrusOpenApiGeneratorMavenProjectStub(configName);
- TestApiGeneratorMojo testApiGeneratorMojo = (TestApiGeneratorMojo) lookupMojo(goal, pomFile);
- testApiGeneratorMojo.setMavenProject(mavenProject);
- testApiGeneratorMojo.setMojoExecution(newMojoExecution(goal));
+ TestApiGeneratorMojo testApiGeneratorMojo = (TestApiGeneratorMojo) lookupMojo(goal, pomFile);
+ testApiGeneratorMojo.setMavenProject(mavenProject);
+ testApiGeneratorMojo.setMojoExecution(newMojoExecution(goal));
- return testApiGeneratorMojo;
+ return testApiGeneratorMojo;
+ } catch (MojoExecutionException | MojoFailureException e) {
+ Assertions.fail("Test setup failed!", e);
+ return new TestApiGeneratorMojo();
+ }
}
}
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java
index 8309b94dcb..1bb8781631 100644
--- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java
@@ -1,7 +1,5 @@
package org.citrusframework.maven.plugin;
-import static java.lang.Boolean.TRUE;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_API_PACKAGE;
import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_API_TYPE;
import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_INVOKER_PACKAGE;
@@ -13,11 +11,16 @@
import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_TARGET_NAMESPACE_TEMPLATE;
import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.replaceDynamicVars;
import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.replaceDynamicVarsToLowerCase;
+import static java.lang.Boolean.TRUE;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.util.ReflectionTestUtils.getField;
import jakarta.validation.constraints.NotNull;
+import org.citrusframework.maven.plugin.TestApiGeneratorMojo;
+import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiConfig;
+import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiType;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@@ -27,8 +30,6 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import org.apache.maven.project.MavenProject;
-import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiConfig;
-import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/TestApiGeneratorMojoIntegrationTest/pom-minimal-petstore.xml b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/TestApiGeneratorMojoIntegrationTest/pom-minimal-petstore.xml
new file mode 100644
index 0000000000..96215c81eb
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/TestApiGeneratorMojoIntegrationTest/pom-minimal-petstore.xml
@@ -0,0 +1,32 @@
+
+ 4.0.0
+
+ minimal-config-petstore
+
+
+
+
+ citrus-test-api-generator-maven-plugin
+
+
+
+ Minimal
+
+
+
+
+
+
+
+ create-test-api
+
+
+
+
+
+
+
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/api/petstore.yaml b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/api/petstore.yaml
new file mode 100644
index 0000000000..0ff3414db5
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/api/petstore.yaml
@@ -0,0 +1,206 @@
+swagger: '2.0'
+info:
+ description: 'This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.'
+ version: 1.0.0
+ x-citrus-app: PETS
+ x-citrus-api-name: petstore
+ title: OpenAPI Petstore
+ license:
+ name: Apache-2.0
+ url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
+host: petstore.swagger.io
+basePath: /v2
+tags:
+ - name: pet
+ description: Everything about your Pets
+ - name: store
+ description: Access to Petstore orders
+ - name: user
+ description: Operations about user
+schemes:
+ - http
+paths:
+ '/pet/{petId}':
+ get:
+ tags:
+ - pet
+ summary: Find pet by ID
+ description: Returns a single pet
+ operationId: getPetById
+ produces:
+# - application/xml
+ - application/json
+ parameters:
+ - name: petId
+ in: path
+ description: ID of pet to return
+ required: true
+ type: integer
+ format: int64
+ - name: verbose
+ description: Output details
+ in: query
+ required: false
+ type: boolean
+ - name: correlationIds
+ description: ID to trace a request
+ in: header
+ required: false
+ type: string
+ responses:
+ '200':
+ description: successful operation
+ schema:
+ $ref: '#/definitions/Pet'
+ '400':
+ description: Invalid ID supplied
+ '404':
+ description: Pet not found
+ security:
+ - api_key: []
+ - basicAuth: []
+securityDefinitions:
+ petstore_auth:
+ type: oauth2
+ authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
+ flow: implicit
+ scopes:
+ 'write:pets': modify pets in your account
+ 'read:pets': read your pets
+ api_key:
+ type: apiKey
+ name: api_key
+ in: header
+ basicAuth:
+ type: basic
+definitions:
+ Order:
+ title: Pet Order
+ description: An order for a pets from the pet store
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ petId:
+ type: integer
+ format: int64
+ quantity:
+ type: integer
+ format: int32
+ shipDate:
+ type: string
+ format: date-time
+ status:
+ type: string
+ description: Order Status
+ enum:
+ - placed
+ - approved
+ - delivered
+ complete:
+ type: boolean
+ default: false
+ xml:
+ name: Order
+ Category:
+ title: Pet category
+ description: A category for a pet
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ name:
+ type: string
+ xml:
+ name: Category
+ User:
+ title: a User
+ description: A User who is purchasing from the pet store
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ username:
+ type: string
+ firstName:
+ type: string
+ lastName:
+ type: string
+ email:
+ type: string
+ password:
+ type: string
+ phone:
+ type: string
+ userStatus:
+ type: integer
+ format: int32
+ description: User Status
+ xml:
+ name: User
+ Tag:
+ title: Pet Tag
+ description: A tag for a pet
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ name:
+ type: string
+ xml:
+ name: Tag
+ Pet:
+ title: a Pet
+ description: A pet for sale in the pet store
+ type: object
+ required:
+ - name
+ - photoUrls
+ properties:
+ id:
+ type: integer
+ format: int64
+ category:
+ $ref: '#/definitions/Category'
+ name:
+ type: string
+ example: doggie
+ photoUrls:
+ type: array
+ xml:
+ name: photoUrl
+ wrapped: true
+ items:
+ type: string
+ tags:
+ type: array
+ xml:
+ name: tag
+ wrapped: true
+ items:
+ $ref: '#/definitions/Tag'
+ status:
+ type: string
+ description: pet status in the store
+ enum:
+ - available
+ - pending
+ - sold
+ xml:
+ name: Pet
+ ApiResponse:
+ title: An uploaded response
+ description: Describes the result of uploading an image resource
+ type: object
+ properties:
+ code:
+ type: integer
+ format: int32
+ type:
+ type: string
+ message:
+ type: string
diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/expected/api/PetApi.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/expected/api/PetApi.java
new file mode 100644
index 0000000000..3ae217d495
--- /dev/null
+++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/resources/expected/api/PetApi.java
@@ -0,0 +1,93 @@
+package org.citrusframework.automation.minimal.api;
+
+import org.citrusframework.endpoint.Endpoint;
+import org.citrusframework.http.client.HttpClient;
+import org.citrusframework.openapi.OpenApiSpecification;
+import org.citrusframework.openapi.actions.OpenApiClientActionBuilder;
+import org.citrusframework.openapi.actions.OpenApiClientActionBuilder.OpenApiOperationBuilder;
+import org.citrusframework.openapi.actions.OpenApiClientRequestActionBuilder;
+import org.citrusframework.openapi.actions.OpenApiClientResponseActionBuilder;
+
+import java.util.function.UnaryOperator;
+
+import static org.citrusframework.spi.Resources.create;
+
+public class PetApi {
+ private static final OpenApiSpecification petstoreSpec = OpenApiSpecification.from(
+ create("api/petstore.yaml")
+ );
+
+ public static PetApi openapiPetstore(HttpClient httpClient) {
+ return new PetApi(httpClient);
+ }
+
+ private final HttpClient httpClient;
+
+ private PetApi(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+ public PetstoreAction getPetById() {
+ return petstoreAction(new GetPetByIdRequest());
+ }
+
+ private PetstoreAction petstoreAction(B requestBuilder) {
+ return new PetstoreAction<>(httpClient, petstoreSpec, requestBuilder);
+ }
+
+ /**
+ * getPetById (GET /pet/{petId})
+ * Find pet by ID
+ **/
+ public static class GetPetByIdRequest extends OperationRequestBuilder {
+ @Override
+ public String getOperationId() {
+ return "getPetById";
+ }
+
+ public GetPetByIdRequest withPetId(Long petId) {
+ openApiOperation.withParameter("petId", petId);
+ return this;
+ }
+
+ public GetPetByIdRequest withVerbose(Boolean verbose) {
+ openApiOperation.withParameter("verbose", verbose);
+ return this;
+ }
+
+ public GetPetByIdRequest withCorrelationIds(String correlationIds) {
+ openApiOperation.withParameter("correlationIds", correlationIds);
+ return this;
+ }
+ }
+
+ public static abstract class OperationRequestBuilder {
+ protected final OpenApiOperationBuilder openApiOperation = OpenApiOperationBuilder.operation(getOperationId());
+
+ public abstract String getOperationId();
+
+ public OpenApiOperationBuilder build() {
+ return openApiOperation;
+ }
+ }
+
+ public static class PetstoreAction extends OpenApiClientActionBuilder {
+ private final T operation;
+
+ private PetstoreAction(Endpoint httpClient, OpenApiSpecification specification, T operation) {
+ super(httpClient, specification);
+ this.operation = operation;
+ }
+
+ public OpenApiClientRequestActionBuilder send(UnaryOperator builderProvider) {
+ var builder = builderProvider.apply(operation);
+ var send = send(builder.build());
+ send.fork(true);
+ return send;
+ }
+
+ public OpenApiClientResponseActionBuilder receive() {
+ return receive(operation.getOperationId(), "200");
+ }
+ }
+}
diff --git a/test-api-generator/readme.md b/test-api-generator/readme.md
new file mode 100644
index 0000000000..f4552f36b6
--- /dev/null
+++ b/test-api-generator/readme.md
@@ -0,0 +1,81 @@
+# TAT-1291
+
+## Possible solution
+
+```java
+
+@CitrusTest
+public void getPetById() {
+// variable("petId", "1001");
+ // native
+ when(openapi(petstoreSpec)
+ .client(httpClient)
+ .withParameter("petId", "1001") // TODO: to be implemented
+ .send("getPetById")
+ .fork(true));
+ // generated - TODO: to be implemented
+ when(openapiPetstore()
+ .client(httpClient)
+ .getPetById()
+ .withPetId("1001")
+ .send() // maybe obsolete?
+ .fork(true));
+}
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```