I have openapi contract:
openapi: 3.0.1
info:
version: 1.0.0
paths:
/getInteractions:
post:
requestBody:
content:
application/json:
schema:
$ref: scheme/interactionsRq.json
required: true
responses:
"200":
content:
application/json:
schema:
$ref: scheme/mainRs.json
in this structure:
-resources
--GetInteractionController.yaml
--scheme
----interactionsRq.json
----interactionsRs.json
----mainRs.json
In mainRs.json i have some ref to another json like this:
"resultApi": {
"title": "result",
"type": "object",
"properties": {
"interactionList": {
"type": "array",
"minItems": 0,
"maxItems": 100,
"items": {
"$ref": "interactionsRs.json#/definitions/interactionApi"
}
}
}
And when i try to package this with openapi-generator-maven-plugin:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>5.3.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/GetInteractionController.yaml</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>some.api.package</apiPackage>
<modelPackage>some.dto.package</modelPackage>
<supportingFilesToGenerate>ApiUtil.java</supportingFilesToGenerate>
<configOptions>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I get a warning and build error:
[WARNING] Failed to get the schema name: ./scheme/interactionsRs.json#/definitions/interactionApi
Can openapi generate code with refs like i have? Or i need to refactor json schemas and delete this refs? Maybe concatenate this in one file or something like this
Now i understand, that this is an issue with my JSON scheme, but not with openapi-generator.
In JSON scheme i've used an jsonschema2pojo feature "customDateTimePattern" : "yyyy-MM-dd'T'HH:mm:ssZ" and it gives me an error.
When i deleted it everything become fine
Related
I want to generate a Java API using OpenAPI 3.0, but I don't want any return type to be a ResponseEntity.
I have a small .yaml file that generates APIs that look like this (I've removed lots of annotations for brevity):
#GetMapping(value = "/student", produces = { "application/json" })
ResponseEntity<List<Student>> getAllStudents();
It's very straightforward, but my employer wants an API like this:
#GetMapping(value = "/student")
List<Student> getAllStudents();
The trouble is that I can't find a configuration option that would make the code generator dispense with the ResponseEntities.
Is there any way to configure the OpenAPI generator to not use ResponseEntities?
—
Details:
I build with Maven, and I configure my code generation in my pom file like this:
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>5.0.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!--See https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin-->
<inputSpec>${project.basedir}/OpenApi.yaml</inputSpec>
<generatorName>spring</generatorName>
<groupId>com.dummy.example</groupId>
<artifactId>dummy</artifactId>
<artifactVersion>2.0</artifactVersion>
<library>spring-boot</library>
<packageName>com.neptunedreams.configuration</packageName>
<apiPackage>com.neptunedreams.api</apiPackage>
<invokerPackage>com.neptunedreams</invokerPackage>
<modelPackage>com.neptunedreams.model</modelPackage>
<configOptions>
<!--See https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/spring.md -->
<sourceFolder>src/main/java</sourceFolder>
<bigDecimalAsString>true</bigDecimalAsString>
<dateLibrary>java8</dateLibrary>
<interfaceOnly>true</interfaceOnly>
<library>spring-boot</library>
<skipDefaultInterface>true</skipDefaultInterface>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
My yaml file is very basic, if you need to see it:
openapi: 3.0.0
info:
description: StackOverflow ResponseEntity Question
version: 1.0.0
title: ResponseEntity Question
paths:
/student:
get:
summary: Get all students
operationId: getAllStudents
responses:
200:
description: Get all students
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Student'
components:
schemas:
Student:
type: object
properties:
name:
type: string
id:
type: integer
format: int64
required:
- name
- id
Like here How to prevent Mono Request body generation when generating the API interfaces for spring-webflux with open api code generator?
You can override/customize the api.mustache from swagger-codegen template.
Here you can find the original template https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
So you can put your own template inside src/main/java/resource.
openApiGenerate {
generatorName = "spring"
library = "spring-boot"
...
configOptions = [
...
templateDirectory: "src/main/resources/openapi-templates"
...
]
}
Here is the documentation about template https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md
I'm using Open-API to generate java class using yaml file. when i run
mvn clean install
i'm getting this error :
unexpected error in Open-API generation
org.openapitools.codegen.SpecValidationException: There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-validate-spec (CLI).
| Error count: 3, Warning count: 6
Errors:
-attribute paths.'/path/{id}'(delete).operationId is repeated
-attribute paths.'/path/name'(get).operationId is repeated
How can i skeep this validation ?
Try this:
Within your POM.xml -> Plugin -> Find openAPI generation plug-in -> configuration -> configOptions ->
<validateSpec>false</validateSpec>
This should work hopefully ! :)
For me, the correct place of validateSpec was configuration instead of configOptions
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.2.1</version>
<executions>
<execution>
<id>abc-api</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
...
<validateSpec>false</validateSpec>
<skipValidateSpec>true</skipValidateSpec>
<configOptions>
<developerOrganization>ABC</developerOrganization>
...
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
Note: I have to add both validateSpec and skipValidateSpec for version 6.2.1 as per suggestion in an open bug https://github.com/OpenAPITools/openapi-generator/issues/9815
Try to add syntax "schema": {"type": "string"} to *.Json file.
I aslo got the error with respose like that:
There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-validate-spec (CLI).
| Error count: 12, Warning count: 20
Errors:
-attribute paths.'/.../items'(get).responses.304.ETag.type is unexpected
-attribute paths.'/.../items'(get).responses.304.Last-Modified.type is unexpected
-attribute paths.'/.../items'(get).responses.200.ETag.type is unexpected
This is my fix:
enter image description here
enter image description here
"headers": {
"ETag": {
"description": "Used as caching key for future requests.",
"schema": {
"type": "string",
"example": "33a64df551425fcc55e4d42a1466666666666666666"
}
},
"Cache-Control": {
"description": "The Cache-Control header.",
"schema": {
"type": "string",
"example": "max-age=1000000"
}
},
"Last-Modified": {
"description": "The last modified the response.",
"schema": {
"type": "string",
"example": "Sun, 11 Nov 2021 15:30:51 ICT"
}
}
}
I hope this one can help you. You cant read more document with response header here: https://swagger.io/docs/specification/describing-responses/
When using swagger 2.0, the java.util.Currency class got generated as a seperate definition. But when we generate OpenAPI 3.0, we run into the issue that swagger-core generates it as a property.
Generation of the OpenAPI 3.0 specification from the classes
We have f.e. this class:
import java.util.Currency;
public class Wrapper {
private Currency currency;
}
From this code we generate the openapi specification with the following plugin configuration:
<plugin>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>2.0.9</version>
<configuration>
<outputFileName>openapi</outputFileName>
<outputFormat>YAML</outputFormat>
<outputPath>....</outputPath>
<resourcePackages>...</resourcePackages>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>resolve</goal>
</goals>
</execution>
</executions>
</plugin>
When generated this will result in this component definition:
components:
schemas:
Wrapper:
type: "object"
properties:
currency:
type: object
properties:
currencyCode:
type: string
defaultFractionDigits:
type: integer
format: int32
numericCode:
type: integer
format: int32
displayName:
type: string
symbol:
type: string
Generation of the classes from the OpenAPI 3.0 specification
We then then generate the classes in another project with the following plugin:
The code to generate the classes form this openapi specification:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>openapi-generation</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/swagger.yaml</inputSpec>
<language>java</language>
<library>jersey2</library>
<generateSupportingFiles>false</generateSupportingFiles>
<configOptions>
<booleanGetterPrefix>is</booleanGetterPrefix>
<dateLibrary>threetenbp</dateLibrary>
<import-mappings>
Currency=java.util.Currency
</import-mappings>
</configOptions>
<generateApis>false</generateApis>
<generateApiDocumentation>false</generateApiDocumentation>
<generateModelTests>false</generateModelTests>
<generateModelDocumentation>false</generateModelDocumentation>
</configuration>
</execution>
</executions>
</plugin>
This will result in a class named WrapperCurrency. The --import-mappings option does not seem to work since it's a property and not a schema. This would work if the Currency would be generated as a seperate Schema definition.
Desired result
Is there any way to either, annotate the property in such a way that the java.util.Currency will be generated as a schema? something along the lines of:
components:
schemas:
Wrapper:
type: "object"
properties:
currency:
$ref: "components/schemas/Currency"
Currency:
type: object
properties:
currencyCode:
type: string
defaultFractionDigits:
type: integer
format: int32
numericCode:
type: integer
format: int32
displayName:
type: string
symbol:
type: string
Or is there a way to bind the --import-mappings option to a property instead of the object?
Well, you may consider a workaround: adding an annotation #Schema(ref = "Currency") to the currency field will make the plugin skip generating properties. Unfortunately, it won't generate the schema definition for the Currency class either:
components:
schemas:
Wrapper:
type: object
properties:
currency:
$ref: '#/components/schemas/Currency'
I am not sure if it is an issue for you, as you are mapping it back to java.util.Currency anyways. But if it is, there is another hack: you can provide a static file with a partial schema (just the Currency definition) and configure the plugin to merge it with the generated schema (openapiFilePath parameter).
Plugin configuration:
<plugin>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>2.0.9</version>
<configuration>
...
<openapiFilePath>src/main/resources/currency.yaml</openapiFilePath>
...
</configuration>
...
</plugin>
currency.yaml:
components:
schemas:
Currency:
type: object
properties:
currencyCode:
type: string
defaultFractionDigits:
type: integer
format: int32
numericCode:
type: integer
format: int32
displayName:
type: string
symbol:
type: string
It's a hack, I know, but if there are no other options...
I am using the openapi-generator-maven-plugin
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>4.1.3</version>
with the <withXml>true</withXml> option.
In my yaml service definition file to describe my REST actions (XML messages). I have a schema like this :
components:
schemas:
LoginRequest:
type: object
properties:
customerName:
type: string
xml:
name: customerName
attribute: false
wrapped: false
password:
type: string
xml:
name: hello
attribute: false
user:
type: string
xml:
name: user
attribute: false
wrapped: false
title: request
xml:
name: request
attribute: false
and the defined service :
paths:
/session/login:
post:
tags:
- sample-controller
summary: login
operationId: loginUsingPOST
requestBody:
content:
application/xml:
schema:
$ref: "#/components/schemas/LoginRequest"
description: request
required: true
responses:
"200":
description: OK
content:
application/xml:
schema:
$ref: "#/components/schemas/LoginResponse"
And I generate the client code. But when I use it, the XML sent to the http request uses <LoginRequest> has a tag name instead of <request>.
It seems that none of my -xml information are taken in account by the generator.
You will need to put the option inside configOptions, for example
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>4.2.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
<generatorName>java</generatorName>
<configOptions>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
Ref: https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin#usage
Given the following Avro Schema:
{
"namespace": "ro.dspr.coreentities",
"type": "record",
"name": "Organization",
"fields": [
{
"name": "id",
"type": "string",
"logicalType": "uuid"
},
{
"name": "name",
"type": "string"
},
{
"name": "description",
"type": "string"
}
]
}
Running avro-maven-plugin 1.9.0 goal schema, I get:
#org.apache.avro.specific.AvroGenerated
public class Organization extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"Organization\",\"namespace\":\"ro.dspr.coreentities\",\"fields\":[{\"name\":\"id\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"logicalType\":\"uuid\"},{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"description\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}");
// truncated
#Deprecated public java.lang.String id;
#Deprecated public java.lang.String name;
#Deprecated public java.lang.String description;
// truncated
}
I want the generated POJO for Organization to have id UUID, not String (what I have now).
Links I looked at:
I do see the logical type def from Avro and there is the Conversion class I am actually trying to trigger, but I cannot connect the dots.
Other
Relevant Maven pom parts
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>${avro.version}</version>
<configuration>
<sourceDirectory>${avro-files-path}</sourceDirectory>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<stringType>String</stringType>
</configuration>
<executions>
<execution>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${avro-files-path}</sourceDirectory>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Extra info
I actually trying to use Avro to give my Kafka messages a structure. I am also using Confluent Schema Registry and Confluent Avro Kafka Serializer. Nevertheless, I thought I would only have the id as String, but if I try to send messages to Kafka as something non-UUID, it will fail later. However, I found out that there is actually no constraint, and I managed to send any String to Kafka. So, the "logicalType" in Avro is not enforced at all.
The Question
How can I generate Organization.class#id as UUID?
If there is no Avro-support in doing this, what would be the workaround (preferably reusing the org.apache.avro.Conversions.UUIDConversion) ?
Here is a functional example:
Schema:
{
"name": "pk",
"type": {"type": "string", "logicalType": "uuid"}
},
Maven config:
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/../avro/schemas/commands</sourceDirectory>
<outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory>
<!-- TODO Enable this string type once we have 1.10.0 release, or 1.9.2-->
<!--<stringType>String</stringType>-->
<fieldVisibility>PRIVATE</fieldVisibility>
<customConversions>org.apache.avro.Conversions$UUIDConversion</customConversions>
<imports>
<import>${project.basedir}/../avro/schemas/common</import>
<import>${project.basedir}/../avro/schemas/commands/account</import>
<import>${project.basedir}/../avro/schemas/commands/rec</import>
</imports>
</configuration>
</execution>
</executions>
</plugin>
The important thing to note is that there is a conflict between the UUIDConversion and String in the current release of the plugin, as such you either need to choose which is more important, or use 1.10.0-SNAPSHOT which has a fix merged, but not yet released.