Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generators/jaxrs-cxf-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|licenseName|The name of the license| |Unlicense|
|licenseUrl|The URL of the license| |http://unlicense.org|
|modelPackage|package for generated models| |org.openapitools.model|
|oas3|Generate Swagger annotations in version 3 instead of version 2.| |false|
|openApiNullable|Enable OpenAPI Jackson Nullable library. Not supported by `microprofile` library.| |true|
|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,17 @@ public class JavaCXFClientCodegen extends AbstractJavaCodegen

public static final String USE_ABSTRACTION_FOR_FILES = "useAbstractionForFiles";

public static final String OAS3 = "oas3";

@Getter protected boolean useGenericResponse = false;

@Getter protected boolean useGzipFeatureForTests = false;

@Getter protected boolean useLoggingFeatureForTests = false;

@Setter protected boolean useAbstractionForFiles = false;

@Setter protected boolean oas3 = false;

public JavaCXFClientCodegen() {
super();
Expand Down Expand Up @@ -93,6 +97,7 @@ public JavaCXFClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_LOGGING_FEATURE_FOR_TESTS, "Use Logging Feature for tests"));
cliOptions.add(CliOption.newBoolean(USE_GENERIC_RESPONSE, "Use generic response"));
cliOptions.add(CliOption.newBoolean(USE_ABSTRACTION_FOR_FILES, "Use alternative types instead of java.io.File to allow passing bytes without a file on disk."));
cliOptions.add(CliOption.newBoolean(OAS3, "Generate Swagger annotations in version 3 instead of version 2."));
}

@Override
Expand All @@ -103,6 +108,7 @@ public void processOpts() {
convertPropertyToBooleanAndWriteBack(USE_LOGGING_FEATURE_FOR_TESTS, this::setUseLoggingFeatureForTests);
convertPropertyToBooleanAndWriteBack(JACKSON, this::setJackson);
convertPropertyToBooleanAndWriteBack(USE_ABSTRACTION_FOR_FILES, this::setUseAbstractionForFiles);
convertPropertyToBooleanAndWriteBack(OAS3, this::setOas3);

supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen

Expand Down Expand Up @@ -132,6 +138,13 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
super.postProcessModelProperty(model, property);
model.imports.remove("ApiModelProperty");
model.imports.remove("ApiModel");

if (oas3) {
apiTemplateFiles.remove("api.mustache");
importMapping.remove("ApiModelProperty");
importMapping.remove("ApiModel");
apiTemplateFiles.put("api_oas3.mustache", ".java");
}

if (jackson) {
//Add jackson imports when model has inner enum
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package {{package}};

{{#imports}}import {{import}};
{{/imports}}

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import {{javaxPackage}}.ws.rs.*;
import {{javaxPackage}}.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.MediaType;
import org.apache.cxf.jaxrs.ext.multipart.*;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
{{#useBeanValidation}}
import {{javaxPackage}}.validation.constraints.*;
import {{javaxPackage}}.validation.Valid;
{{/useBeanValidation}}

{{#appName}}
/**
* {{{appName}}}
*
{{#appDescription}}
* <p>{{{.}}}
*
{{/appDescription}}
*/
{{/appName}}
@Path("{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}{{commonPath}}")
{{#addConsumesProducesJson}}
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
{{/addConsumesProducesJson}}
public interface {{classname}} {
{{#operations}}
{{#operation}}

{{#summary}}
/**
* {{summary}}
*
{{#notes}}
* {{.}}
*
{{/notes}}
*/
{{/summary}}
@{{httpMethod}}
{{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}}
{{#hasConsumes}}
@Consumes({ {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} })
{{/hasConsumes}}
{{#hasProduces}}
@Produces({ {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} })
{{/hasProduces}}
@Operation(summary = "{{{summary}}}", tags={ {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} })
{{#implicitHeadersParams.0}}
@Parameters({
{{#implicitHeadersParams}}
@Parameter(name = "{{{baseName}}}", description = "{{{description}}}", {{#required}}required = true,{{/required}} in = ParameterIn.HEADER, content = @Content(schema = @Schema(type = "{{{dataType}}}"))){{^-last}},{{/-last}}
{{/implicitHeadersParams}}
})
{{/implicitHeadersParams.0}}
@ApiResponses(value = { {{#responses}}
@ApiResponse(responseCode = "{{{code}}}", description = "{{{message}}}", content = @Content(mediaType = {{#content}}{{#entrySet}}"{{{key}}}"{{/entrySet}}{{/content}}{{^content}}"*/*"{{/content}}, {{#containerType}}array = @ArraySchema({{/containerType}}schema = @Schema(implementation = {{#isFile}}{{#useAbstractionForFiles}}InputStream{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{baseType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{baseType}}}{{/isFile}}.class){{#containerType}}){{/containerType}})){{^-last}},{{/-last}}{{/responses}} })
public {{>returnTypes}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}});
{{/operation}}
}
{{/operations}}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{{#oas3}}
import io.swagger.v3.oas.annotations.media.Schema;
{{/oas3}}
{{^oas3}}
import io.swagger.annotations.ApiModelProperty;
{{/oas3}}
import java.util.Objects;
{{#withXml}}
import {{javaxPackage}}.xml.bind.annotation.XmlElement;
Expand All @@ -13,9 +18,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;

{{#description}}
/**
* {{{description}}}
* {{{.}}}
**/
@ApiModel(description="{{{description}}}")
{{^oas3}}@ApiModel(description="{{{.}}}"){{/oas3}}
{{/description}}
{{>additionalModelTypeAnnotations}}{{>xmlPojoAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}
{{#vendorExtensions.x-class-extra-annotation}}
Expand All @@ -28,7 +33,7 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}}{{#vendorExtensi
{{#withXml}}
@XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}})
{{/withXml}}
@ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}"){{^isPrimitiveType}}{{^isDate}}{{^isDateTime}}{{^isString}}{{^isFile}}{{#useBeanValidation}}
{{#oas3}} @Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"){{/oas3}}{{^oas3}} @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}"){{/oas3}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime}}{{^isString}}{{^isFile}}{{#useBeanValidation}}
@Valid{{/useBeanValidation}}{{/isFile}}{{/isString}}{{/isDateTime}}{{/isDate}}{{/isPrimitiveType}}
{{#description}}
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,4 +336,59 @@ public void testUseAbstractionForFiles() throws Exception {
"public FilesUploadPost200Response filesUploadPost(InputStream body);"
);
}

@Test
public void testUseOas3Imports() throws Exception {

Map<String, Object> properties = new HashMap<>();
properties.put(CodegenConstants.API_PACKAGE, "xyz.abcdef.api");
properties.put(CodegenConstants.MODEL_PACKAGE, "xyz.abcdef.api");

properties.put(JavaCXFClientCodegen.OAS3, true);

File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();

final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("jaxrs-cxf-client")
.setAdditionalProperties(properties)
.setInputSpec("src/test/resources/3_1/java/issue_19907.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));


DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
files.forEach(File::deleteOnExit);

validateJavaSourceFiles(files);

Path petApi = Paths.get(output + "/src/gen/java/xyz/abcdef/api/PetApi.java");
Path petModel = Paths.get(output + "/src/gen/java/xyz/abcdef/api/Pet.java");

TestUtils.assertFileContains(petApi,
// imports
"import io.swagger.v3.oas.annotations.responses.ApiResponses;",
"import io.swagger.v3.oas.annotations.responses.ApiResponse;",
"import io.swagger.v3.oas.annotations.media.ArraySchema;",
"import io.swagger.v3.oas.annotations.media.Content;",

"@Path(\"/pet/{petId}\")",
"@Produces({ \"application/json\" })",
"@Operation(summary = \"Find pet by ID\", tags={ })",
"@ApiResponse(responseCode = \"200\", description = \"successful operation\", content = @Content(mediaType = \"application/json\", schema = @Schema(implementation = Pet.class))),",
"@ApiResponse(responseCode = \"400\", description = \"Invalid ID supplied\", content = @Content(mediaType = \"*/*\", schema = @Schema(implementation = Void.class))),",
"@ApiResponse(responseCode = \"404\", description = \"Pet not found\", content = @Content(mediaType = \"*/*\", schema = @Schema(implementation = Void.class))) })",
"public Pet getPetById(@PathParam(\"petId\") Long petId);"

);

TestUtils.assertFileNotContains(petModel,
"import io.swagger.annotations.ApiModel;",
"@ApiModel(description=\"A pet for sale in the pet store\")"
);

TestUtils.assertFileContains(petModel,
"@Schema(description = \"\")"
);
}
}
112 changes: 112 additions & 0 deletions modules/openapi-generator/src/test/resources/3_1/java/issue_19907.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
openapi: 3.1.0
servers:
- url: 'http://petstore.swagger.io/v2'
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
title: OpenAPI Petstore
license:
name: Apache-2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
paths:
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
components:
schemas:
Tag:
title: Pet Tag
description: A tag for a pet
type: object
properties:
id:
type: integer
format: int64
name:
type: string
Pet:
title: a Pet
description: A pet for sale in the pet store
type: object
properties:
tags:
type: array
items:
$ref: '#/components/schemas/Tag'
tagsDefaultList:
type: array
default: []
items:
$ref: '#/components/schemas/Tag'
tagsUnique:
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/Tag'
tagsDefaultSet:
type: array
default: [ ]
uniqueItems: true
items:
$ref: '#/components/schemas/Tag'
stringList:
type: array
items:
type: string
stringDefaultList:
type: array
default:
- A
- B
items:
type: string
stringEmptyDefaultList:
type: array
default: []
items:
type: string
stringSet:
type: array
uniqueItems: true
items:
type: string
stringDefaultSet:
type: array
uniqueItems: true
default:
- A
- B
items:
type: string
stringEmptyDefaultSet:
type: array
uniqueItems: true
default: []
items:
type: string