diff --git a/docs/generators/jaxrs-cxf-cdi.md b/docs/generators/jaxrs-cxf-cdi.md index ae4443c496d9..78d31c8573d4 100644 --- a/docs/generators/jaxrs-cxf-cdi.md +++ b/docs/generators/jaxrs-cxf-cdi.md @@ -51,4 +51,5 @@ sidebar_label: jaxrs-cxf-cdi |interfaceOnly|Whether to generate only API interface stubs without the server files.| |false| |returnResponse|Whether generate API interface should return javax.ws.rs.core.Response instead of a deserialized entity. Only useful if interfaceOnly is true.| |false| |useSwaggerAnnotations|Whether to generate Swagger annotations.| |true| +|openApiSpecFileLocation|Location where the file containing the spec will be generated in the output folder. No file generated when set to null or empty string.| |null| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-spec.md b/docs/generators/jaxrs-spec.md index 9ea42071891c..8d338ebfef85 100644 --- a/docs/generators/jaxrs-spec.md +++ b/docs/generators/jaxrs-spec.md @@ -51,3 +51,4 @@ sidebar_label: jaxrs-spec |interfaceOnly|Whether to generate only API interface stubs without the server files.| |false| |returnResponse|Whether generate API interface should return javax.ws.rs.core.Response instead of a deserialized entity. Only useful if interfaceOnly is true.| |false| |useSwaggerAnnotations|Whether to generate Swagger annotations.| |true| +|openApiSpecFileLocation|Location where the file containing the spec will be generated in the output folder. No file generated when set to null or empty string.| |null| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java index 776915734a33..8b7736fce321 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java @@ -37,12 +37,14 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen { public static final String GENERATE_POM = "generatePom"; public static final String USE_SWAGGER_ANNOTATIONS = "useSwaggerAnnotations"; public static final String JACKSON = "jackson"; + public static final String OPEN_API_SPEC_FILE_LOCATION = "openApiSpecFileLocation"; private boolean interfaceOnly = false; private boolean returnResponse = false; private boolean generatePom = true; private boolean useSwaggerAnnotations = true; private boolean useJackson = false; + private String openApiSpecFileLocation = "src/main/openapi/openapi.yaml"; private String primaryResourceName; @@ -91,6 +93,7 @@ public JavaJAXRSSpecServerCodegen() { cliOptions.add(CliOption.newBoolean(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files.").defaultValue(String.valueOf(interfaceOnly))); cliOptions.add(CliOption.newBoolean(RETURN_RESPONSE, "Whether generate API interface should return javax.ws.rs.core.Response instead of a deserialized entity. Only useful if interfaceOnly is true.").defaultValue(String.valueOf(returnResponse))); cliOptions.add(CliOption.newBoolean(USE_SWAGGER_ANNOTATIONS, "Whether to generate Swagger annotations.", useSwaggerAnnotations)); + cliOptions.add(CliOption.newString(OPEN_API_SPEC_FILE_LOCATION, "Location where the file containing the spec will be generated in the output folder. No file generated when set to null or empty string.")); } @Override @@ -114,6 +117,10 @@ public void processOpts() { useSwaggerAnnotations = Boolean.valueOf(additionalProperties.get(USE_SWAGGER_ANNOTATIONS).toString()); } writePropertyBack(USE_SWAGGER_ANNOTATIONS, useSwaggerAnnotations); + if (additionalProperties.containsKey(OPEN_API_SPEC_FILE_LOCATION)) { + openApiSpecFileLocation = additionalProperties.get(OPEN_API_SPEC_FILE_LOCATION).toString(); + } + additionalProperties.put(OPEN_API_SPEC_FILE_LOCATION, openApiSpecFileLocation); useJackson = convertPropertyToBoolean(JACKSON); @@ -134,18 +141,38 @@ public void processOpts() { (sourceFolder + '/' + invokerPackage).replace(".", "/"), "RestApplication.java")); } - supportingFiles.add(new SupportingFile("openapi.mustache", - "src/main/openapi", - "openapi.yaml") - ); + if(StringUtils.isNotEmpty(openApiSpecFileLocation)) { + int index = openApiSpecFileLocation.lastIndexOf('/'); + String fileFolder; + String fileName; + if(index >= 0) { + fileFolder = openApiSpecFileLocation.substring(0, index); + fileName = openApiSpecFileLocation.substring(index + 1); + } else { + fileFolder = ""; + fileName = openApiSpecFileLocation; + } + supportingFiles.add(new SupportingFile("openapi.mustache", fileFolder, fileName)); + } } - @Override public String getName() { return "jaxrs-spec"; } + public String getOpenApiSpecFileLocation() { + return openApiSpecFileLocation; + } + + /** + * Location where the file containing the spec will be generated in the output folder. + * @param location location inside the output folder. No file generated when set to null or empty string. + */ + public void setOpenApiSpecFileLocation(String location) { + this.openApiSpecFileLocation = location; + } + @Override public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map> operations) { String basePath = resourcePath; diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/TestUtils.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/TestUtils.java index 65614c7e51a7..188d7d2b9031 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/TestUtils.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/TestUtils.java @@ -1,5 +1,6 @@ package org.openapitools.codegen; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import io.swagger.parser.OpenAPIParser; @@ -70,4 +71,14 @@ public static void ensureContainsFile(Map generatedFiles, File r } assertTrue(generatedFiles.containsKey(absoluteFilename), "File '" + absoluteFilename + "' was not fould in the list of generated files"); } + + public static void ensureDoesNotContainsFile(Map generatedFiles, File root, String filename) { + File file = new File(root, filename); + String absoluteFilename = file.getAbsolutePath().replace("\\", "/"); + if (generatedFiles.containsKey(absoluteFilename)) { + Assert.fail("File '" + absoluteFilename + "' exists in file in list:\n" + + generatedFiles.keySet().stream().sorted().collect(Collectors.joining(",\n"))); + } + assertFalse(generatedFiles.containsKey(absoluteFilename), "File '" + absoluteFilename + "' was fould in the list of generated files"); + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java index 341d2456f4dd..e5a13ce839d3 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java @@ -1,12 +1,24 @@ package org.openapitools.codegen.java.jaxrs; +import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.servers.Server; + +import org.openapitools.codegen.ClientOptInput; +import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.MockDefaultGenerator; +import org.openapitools.codegen.TestUtils; +import org.openapitools.codegen.config.CodegenConfigurator; +import org.openapitools.codegen.languages.AbstractJavaJAXRSServerCodegen; +import org.openapitools.codegen.languages.JavaClientCodegen; import org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import java.io.File; +import java.nio.file.Files; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,7 +34,79 @@ public class JavaJAXRSSpecServerCodegenTest extends JavaJaxrsBaseTest { public void before() { codegen = new JavaJAXRSSpecServerCodegen(); } - + + @Test + public void testInitialConfigValues() throws Exception { + final JavaJAXRSSpecServerCodegen codegen = new JavaJAXRSSpecServerCodegen(); + codegen.processOpts(); + + OpenAPI openAPI = new OpenAPI(); + openAPI.addServersItem(new Server().url("https://api.abcde.xy:8082/v2")); + codegen.preprocessOpenAPI(openAPI); + + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP), Boolean.FALSE); + Assert.assertEquals(codegen.isHideGenerationTimestamp(), false); + Assert.assertEquals(codegen.modelPackage(), "org.openapitools.model"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.MODEL_PACKAGE), "org.openapitools.model"); + Assert.assertEquals(codegen.apiPackage(), "org.openapitools.api"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.API_PACKAGE), "org.openapitools.api"); + Assert.assertEquals(codegen.getInvokerPackage(), "org.openapitools.api"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.INVOKER_PACKAGE), "org.openapitools.api"); + Assert.assertEquals(codegen.additionalProperties().get(JavaJAXRSSpecServerCodegen.SERVER_PORT), "8082"); + Assert.assertEquals(codegen.getOpenApiSpecFileLocation(), "src/main/openapi/openapi.yaml"); + Assert.assertEquals(codegen.additionalProperties().get(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION), "src/main/openapi/openapi.yaml"); + } + + @Test + public void testSettersForConfigValues() throws Exception { + final JavaJAXRSSpecServerCodegen codegen = new JavaJAXRSSpecServerCodegen(); + codegen.setHideGenerationTimestamp(true); + codegen.setModelPackage("xx.yyyyyyyy.model"); + codegen.setApiPackage("xx.yyyyyyyy.api"); + codegen.setInvokerPackage("xx.yyyyyyyy.invoker"); + codegen.setOpenApiSpecFileLocation("src/main/resources/META-INF/openapi.yaml"); + codegen.processOpts(); + + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP), Boolean.TRUE); + Assert.assertEquals(codegen.isHideGenerationTimestamp(), true); + Assert.assertEquals(codegen.modelPackage(), "xx.yyyyyyyy.model"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.MODEL_PACKAGE), "xx.yyyyyyyy.model"); + Assert.assertEquals(codegen.apiPackage(), "xx.yyyyyyyy.api"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.API_PACKAGE), "xx.yyyyyyyy.api"); + Assert.assertEquals(codegen.getInvokerPackage(), "xx.yyyyyyyy.invoker"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.INVOKER_PACKAGE), "xx.yyyyyyyy.invoker"); + Assert.assertEquals(codegen.getOpenApiSpecFileLocation(), "src/main/resources/META-INF/openapi.yaml"); + Assert.assertEquals(codegen.additionalProperties().get(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION), "src/main/resources/META-INF/openapi.yaml"); + } + + @Test + public void testAdditionalPropertiesPutForConfigValues() throws Exception { + final JavaJAXRSSpecServerCodegen codegen = new JavaJAXRSSpecServerCodegen(); + codegen.additionalProperties().put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true"); + codegen.additionalProperties().put(CodegenConstants.MODEL_PACKAGE, "xyz.yyyyy.mmmmm.model"); + codegen.additionalProperties().put(CodegenConstants.API_PACKAGE, "xyz.yyyyy.aaaaa.api"); + codegen.additionalProperties().put(CodegenConstants.INVOKER_PACKAGE, "xyz.yyyyy.iiii.invoker"); + codegen.additionalProperties().put("serverPort", "8088"); + codegen.additionalProperties().put(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION, "openapi.yml"); + codegen.processOpts(); + + OpenAPI openAPI = new OpenAPI(); + openAPI.addServersItem(new Server().url("https://api.abcde.xy:8082/v2")); + codegen.preprocessOpenAPI(openAPI); + + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP), Boolean.TRUE); + Assert.assertEquals(codegen.isHideGenerationTimestamp(), true); + Assert.assertEquals(codegen.modelPackage(), "xyz.yyyyy.mmmmm.model"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.MODEL_PACKAGE), "xyz.yyyyy.mmmmm.model"); + Assert.assertEquals(codegen.apiPackage(), "xyz.yyyyy.aaaaa.api"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.API_PACKAGE), "xyz.yyyyy.aaaaa.api"); + Assert.assertEquals(codegen.getInvokerPackage(), "xyz.yyyyy.iiii.invoker"); + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.INVOKER_PACKAGE), "xyz.yyyyy.iiii.invoker"); + Assert.assertEquals(codegen.additionalProperties().get(AbstractJavaJAXRSServerCodegen.SERVER_PORT), "8088"); + Assert.assertEquals(codegen.getOpenApiSpecFileLocation(), "openapi.yml"); + Assert.assertEquals(codegen.additionalProperties().get(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION), "openapi.yml"); + } + /** * Test * {@link JavaJAXRSSpecServerCodegen#addOperationToGroup(String, String, Operation, CodegenOperation, Map)} for Resource with path "/" and set tag. @@ -33,14 +117,14 @@ public void testAddOperationToGroupForRootResource() { codegenOperation.operationId = "findPrimaryresource"; Operation operation = new Operation(); Map> operationList = new HashMap<>(); - + codegen.addOperationToGroup("Primaryresource", "/", operation, codegenOperation, operationList); - + Assert.assertEquals(operationList.size(), 1); Assert.assertTrue(operationList.containsKey("")); Assert.assertEquals(codegenOperation.baseName, "Primaryresource"); } - + /** * Test * {@link JavaJAXRSSpecServerCodegen#addOperationToGroup(String, String, Operation, CodegenOperation, Map)} for Resource with path param. @@ -51,14 +135,14 @@ public void testAddOperationToGroupForRootResourcePathParam() { codegenOperation.operationId = "getPrimaryresource"; Operation operation = new Operation(); Map> operationList = new HashMap<>(); - + codegen.addOperationToGroup("Primaryresource", "/{uuid}", operation, codegenOperation, operationList); - + Assert.assertEquals(operationList.size(), 1); Assert.assertTrue(operationList.containsKey("")); Assert.assertEquals(codegenOperation.baseName, "Primaryresource"); } - + /** * Test * {@link JavaJAXRSSpecServerCodegen#addOperationToGroup(String, String, @@ -70,14 +154,14 @@ public void testAddOperationToGroupForSubresource() { codegenOperation.path = "/subresource"; Operation operation = new Operation(); Map> operationList = new HashMap<>(); - + codegen.addOperationToGroup("Default", "/subresource", operation, codegenOperation, operationList); - + Assert.assertEquals(codegenOperation.baseName, "subresource"); Assert.assertEquals(operationList.size(), 1); Assert.assertTrue(operationList.containsKey("subresource")); } - + /** * Test {@link JavaJAXRSSpecServerCodegen#toApiName(String)} with subresource. */ @@ -86,7 +170,7 @@ public void testToApiNameForSubresource() { final String subresource = codegen.toApiName("subresource"); Assert.assertEquals(subresource, "SubresourceApi"); } - + /** * Test {@link JavaJAXRSSpecServerCodegen#toApiName(String)} with primary resource. */ @@ -97,8 +181,103 @@ public void testToApiNameForPrimaryResource() { Operation operation = new Operation(); Map> operationList = new HashMap<>(); codegen.addOperationToGroup("Primaryresource", "/", operation, codegenOperation, operationList); - + final String subresource = codegen.toApiName(""); Assert.assertEquals(subresource, "PrimaryresourceApi"); } + + @Test + public void testGeneratePingDefaultLocation() throws Exception { + Map properties = new HashMap<>(); + properties.put(JavaClientCodegen.JAVA8_MODE, true); + + File output = Files.createTempDirectory("test").toFile(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("jaxrs-spec") + .setAdditionalProperties(properties) + .setInputSpec("src/test/resources/3_0/ping.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(clientOptInput).generate(); + + Map generatedFiles = generator.getFiles(); + TestUtils.ensureContainsFile(generatedFiles, output, "src/main/openapi/openapi.yaml"); + + output.deleteOnExit(); + } + + @Test + public void testGeneratePingNoSpecFile() throws Exception { + Map properties = new HashMap<>(); + properties.put(JavaClientCodegen.JAVA8_MODE, true); + properties.put(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION, ""); + + File output = Files.createTempDirectory("test").toFile(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("jaxrs-spec") + .setAdditionalProperties(properties) + .setInputSpec("src/test/resources/3_0/ping.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(clientOptInput).generate(); + + Map generatedFiles = generator.getFiles(); + TestUtils.ensureDoesNotContainsFile(generatedFiles, output, "src/main/openapi/openapi.yaml"); + + output.deleteOnExit(); + } + + @Test + public void testGeneratePingAlternativeLocation1() throws Exception { + Map properties = new HashMap<>(); + properties.put(JavaClientCodegen.JAVA8_MODE, true); + properties.put(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION, "src/main/resources/META-INF/openapi.yaml"); + + File output = Files.createTempDirectory("test").toFile(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("jaxrs-spec") + .setAdditionalProperties(properties) + .setInputSpec("src/test/resources/3_0/ping.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(clientOptInput).generate(); + + Map generatedFiles = generator.getFiles(); + TestUtils.ensureContainsFile(generatedFiles, output, "src/main/resources/META-INF/openapi.yaml"); + + output.deleteOnExit(); + } + + @Test + public void testGeneratePingAlternativeLocation2() throws Exception { + Map properties = new HashMap<>(); + properties.put(JavaClientCodegen.JAVA8_MODE, true); + properties.put(JavaJAXRSSpecServerCodegen.OPEN_API_SPEC_FILE_LOCATION, "openapi.yml"); + + File output = Files.createTempDirectory("test").toFile(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("jaxrs-spec") + .setAdditionalProperties(properties) + .setInputSpec("src/test/resources/3_0/ping.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(clientOptInput).generate(); + + Map generatedFiles = generator.getFiles(); + TestUtils.ensureContainsFile(generatedFiles, output, "openapi.yml"); + + output.deleteOnExit(); + } }