Releases: openapi-processor/openapi-processor-base
2025.2
(openapi-processor/openapi-processor-spring#328) support endpoint with different responses for different status codes
For the example below, versions before 2025.2 would pick Bar
(the last response) as the return type for the getFooApplicationJson()
endpoint method. This doesn't work because the method must be able to return Foo
or Bar
too.
To make this work it will now use Object
as return type.
openapi: 3.1.0
info:
title: test multiple success responses
version: 1.0.0
paths:
/foo:
get:
description: endpoint with multiple success responses
responses:
'200':
description: success
content:
application/json:
schema:
$ref: '#/components/schemas/Foo'
'202':
description: another success
content:
application/json:
schema:
$ref: '#/components/schemas/Bar'
components:
schemas:
Foo:
type: object
properties:
foo:
type: string
Bar:
type: object
properties:
bar:
type: string
(#247) marker interface for responses
openapi-processor/openapi-processor-spring#328 handles multiple response objects by using Object
as result type. An Object return type is obviously not very descriptive. It is impossible to know from the interface which results are possible.
To improve on that situation the processor can generate a marker interface that is more descriptive and helps with navigation in the IDE.
Generation of the marker interface is enabled by adding the response-interface
option:
openapi-processor-mapping: v12
options:
package-name: ...
# ...
response-interface: true
The marker interface is an empty interface and its name is derived from the http method, path and content type to create a unique name.
If the response type (e.g. Foo from the above example OpenAPI) is used on multiple endpoints with multiple success response status it will implement multiple marker interfaces.
package generated.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
@Generated(value = "openapi-processor-core", version = "test")
public class Foo implements GetFooApplicationJsonResponse /* , .. more interfaces if Foo is used on multiple endpoints */ {
@JsonProperty("foo")
private String foo;
// ...
}
That way it is possible to find the possible result type by navigating to the implementations of the marker interface.
parse drop mapping (openapi-processor/openapi-processor-spring#327) drop OpenAPI parameter
It is now possible to drop a parameter given in the OpenAPI description from the generated code. This may be useful if a parameter is for example handled by a request filter and therefore is not needed in the endpoint method anymore.
To drop a parameter add a parameters/drop
entry with the name of the parameter to drop it:
openapi-processor-mapping: v12
options:
package-name: generated
map:
paths:
/foo:
parameters:
- drop: foo
Even if it is possible to add it at the global level, it is best used at the endpoint level.
(#253) result-style
the result-style
option is now handled on all levels (global, endpoint, http method) and not just on the global level.
(openapi-processor/openapi-processor-spring#331) formatter selection
the processor didn't use the new formatter selection, it does now properly handle google
& eclipse
(no need to for extra jdk configuration) values.
openapi-processor-mapping: v12
options:
package-name: # ...
format-code: false # disable code formatter
format-code: true # use default google code formatter
format-code: google # use google code formatter, i.e. the same as "true"
format-code: eclipse # use eclipse code formatter
2025.1.1
(#237) fix mapping.yaml
json schema
format-code
did restrict the type to boolean
which does not work for the allowed values google
& eclipse
. this caused a warning on processing.
(#238) javadoc
javadoc @param
generation would use a wrong parameter name if the property name was not a valid java identifier.
/**
* this is the <em>Foo</em> schema description
*
* @param fooBar <em>property</em> description
- * @param enum enum <em>property</em> description
+ * @param aEnum enum <em>property</em> description
*/
@Generated(value = "openapi-processor-core", version = "test")
public record Foo(
@JsonProperty("foo-bar")
String fooBar,
@JsonProperty("enum")
FooEnum aEnum
) {}
2025.1
(#230) do not generate accessors of pojos
It is now possible to disable generation of accessor methods on pojo dtos. The properties are still private
. This is only useful in combination with an object annotation mapping that adds the accessors. For example lombok.Getter
& lombok.Setter
.
openapi-processor-mapping: v11
options:
package-name: generated
model-type: default # i.e. pojo
model-accessors: false # only used if model-type is default
map:
types:
- type: object @ lombok.Getter
- type: object @ lombok.Setter
package io.openapiprocessor.openapi.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.openapiprocessor.openapi.support.Generated;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Generated(value = "openapi-processor-spring")
public class Foo {
@JsonProperty("id")
private UUID id;
}
(#225) schema mappings
It is now possible to restrict annotation mappings to schema properties by using schema level mappings. Schema mappings are only supported at the global level:
openapi-processor-mapping: v11
options:
package-name: generated
format-code: false
map:
types:
- type: integer:year => java.time.Year
schemas:
- type: integer:year @ com.fasterxml.jackson.annotation.JsonFormat(shape = com.fasterxml.jackson.annotation.JsonFormat.Shape.NUMBER_INT)
The schema mapping will tell the processor to apply the annotation only on dto properties:
package generated.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
import java.time.Year;
@Generated(value = "openapi-processor-core", version = "latest")
public class Foo {
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
@JsonProperty("year")
private Year year;
// ...
}
and not to the api endpoint method parameter:
package generated.api;
import generated.model.Foo;
import generated.support.Generated;
import java.time.Year;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Generated(value = "openapi-processor-core", version = "test")
public interface Api {
@GetMapping(path = "/foo", produces = {"application/json"})
Foo getFoo(@RequestParam(name = "year", required = false) Year year);
}
(#8) alternative code formatter
experimental (whatever is the use of formatting the generated code anyway.. ;-)
the current code formatter google-java-format uses internal java classes which requires additional configuration.
To avoid this additional configuration openapi-processor now supports the eclipse code formatter.
To support this the format-code
option accepts two new values: google
and eclipse
.
openapi-processor-mapping: v11
options:
package-name: # ...
format-code: false # disable code formatter
format-code: true # use default google code formatter
format-code: google # use google code formatter, i.e. the same as "true"
format-code: eclipse # use eclipse code formatter
(openapi-processor/openapi-processor-spring#323) null pointer with enum in record with javadoc
fixed a null pointer exception generating javadoc for an enum type property.
javadoc improvement
improved javadoc generation for $ref
with description
.
# OpenAPI document
components:
schemas:
Foo:
description: >
this is the *Foo* schema description
type: object
properties:
foo-bar:
description: >
*property* description
type: string
enum:
description: > # <1>
enum *property* description
$ref: '#/components/schemas/FooEnum'
FooEnum:
description: "this is an *enum* description"
type: string
enum: ['foo', 'bar']
javadoc generation now handles a description
(<1>) at $ref
elements.
For the given OpenAPI description above the pojo for Foo
will now look like this
package generated.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
/**
* this is the <em>Foo</em> schema description
*/
@Generated(value = "openapi-processor-core", version = "test")
public class Foo {
/**
* <em>property</em> description
*/
@JsonProperty("foo-bar")
private String fooBar;
/**
* enum <em>property</em> description
*/
@JsonProperty("enum")
private FooEnum aEnum;
// ...
}
And for the record variant:
package generated.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
/**
* this is the <em>Foo</em> schema description
*
* @param fooBar <em>property</em> description
* @param enum enum <em>property</em> description
*/
@Generated(value = "openapi-processor-core", version = "test")
public record Foo(
@JsonProperty("foo-bar")
String fooBar,
@JsonProperty("enum")
FooEnum aEnum
) {}
2024.7
(#9) trace mapping lookup
the processor can now create a log of the mapping lookup. It may help to understand failing mappings.
It adds two new options to control the logging.
openapi-processor-mapping: v10
options:
package-name: # ...
map:
# ...
logging:
mapping: true
mapping-target: stdout
logging.mapping
enables the logging of the mapping lookups. mapping-target
set the output channel. Simplest is to use stdout
. The other possible value is logger
. See the logging documentation for a more detailed description.
(#188) minimum/maximum and their exclusive version did not work for OpenAPI 3.1
actually that was an issue in the OpenAPI parser openapi-processor/openapi-parser#114
2024.6.1
2024.6
(#176) support for servers/server/url
it is now possible to tell the processor to generate a properties resource file with the path of a selected OpenAPI servers/server/url
.
Given an OpenAPI description with a servers
key:
openapi: 3.1.0
info:
title: server url example
version: 1.0.0
servers:
- url: "https://openapiprocessor.io/{api}"
variables:
path:
default: api
and a mapping
openapi-processor-mapping: v9
options:
base-path:
# false/true=0,1,2,... (default false)
server-url: true
it will generate a properties file api.properties
openapi.base.path = /api
that can be used to configure the (Spring) context-path
:
# application.properties
#spring.config.import = api.properties
server.servlet.context-path=${openapi.base.path}
Take a look at the documentation for more details.
(openapi-processor/openapi-processor-spring#288) javadoc of record
a record should have its javadoc at the record using @param
s to describe the record properties.
Instead of
/**
* this is the <em>Foo</em> schema description
*/
@Generated(value = "openapi-processor-core", version = "test")
public record Foo(
/**
* <em>property</em> description
*/
@JsonProperty("foo-bar")
String fooBar
) {}
the processor now generates:
/**
* this is the <em>Foo</em> schema description
*
* @param fooBar <em>property</em> description
*/
@Generated(value = "openapi-processor-core", version = "test")
public record Foo(
@JsonProperty("foo-bar")
String fooBar
) {}
(openapi-processor/openapi-processor-spring#287) warn on endpoint without success response
the processor ignores endpoints that have no success response (i.e. 2xx response code). To detect this "error" at compile time the processor will now print a warning with the effected endpoint.
(#158) type annotation mapping ignored with model-name-suffix
using a mapping like this:
openapi-processor-mapping: v9
options:
model-name-suffix: Resource
maps:
types:
- type: Foo @ io.openapiprocessor.Annotation()
did not add the annotation because of the model-name-suffix
.
dependency updates
- updated (internal) OpenAPI parser to 2024.4 (was 2024.3)
- updated com.fasterxml.jackson:jackson-bom from 2.17.1 to 2.17.2
- updated com.google.googlejavaformat:google-java-format from 1.22.0 to 1.23.0
2024.5
(#156) add request body description to javadoc
The request body description is added as @param
to the generated javadoc.
openapi: 3.1.0
info:
title: javadoc
version: v1
paths:
/foo:
get:
requestBody:
description: this is the request body
...
(#152) missing @Generated
the generated Values
and ValueValidator
(used by enum-type
string
) were not annotated with @Generated
.
(openapi-processor/openapi-processor-spring#271) (fix) missing import of class annotation parameter
using a .class
parameter in a class annotation mapping did not add the import of the parameter class.
map:
types:
- type: Foo @ io.oap.ClassAnnotation(value = io.oap.Param.class)
In this example the import for Param
was missing.
(openapi-processor/openapi-processor-spring#269) disable @Generated
its is now possible to disable the @Generated
annotation. If it is disabled the processor will not add it to any generated type.
openapi-processor-mapping: v8
options:
# ...
# enable/disable generated annotation, true (default) or false.
generated-annotation: false
(openapi-processor/openapi-processor-spring#268) control @JsonProperty
annotation
By setting the json-property-annotation
option is is possible to control the generation of the @JsonProperty annotation. It allows thre values: always
, auto
or never
.
always
: (the default) adds a@JsonProperty
annotation to all properties.auto
: only adds a@JsonProperty
annotation to a property if it is required, i.e. if the OpenAPI property name is not a valid java identifier or if a property uses thereadOnly
/writeOnly
(OpenAPI) flags.never
: never adds a@JsonProperty
annotation to the properties. This may generated invalid code if the property name is not a valid java identifier.
openapi-processor-mapping: v8
options:
# ...
# control @JsonProperty annotation, always (default), auto, never.
json-property-annotation: auto
2024.4
(openapi-processor/openapi-processor-spring#262) (fix) response $ref did not work
using responses
with $ref
s did not work with all (supported) OpenAPI parsers.
- internal OpenAPI parser did not work (the default parser).
- openapi4j did not work (not maintained anymore).
- Swagger parser worked.
It now works for all 3 (supported) OpenAPI parsers.
(#145) (fix) bad enum creation
the processor did not create a proper enum for an enum description like this:
components:
schemas:
AnEnum:
type: string
enum:
- "1"
- "2"
because 1
and 2
are not valid java identifiers, the processor generated
public enum Enum {
INVALID("1"),
INVALID("2");
...
}
The processor will now prefix invalid identifiers with "v" (value) to avoid this. The enum above will produce
public enum Enum {
V1("1"),
V2("2");
...
}
(#143) (fix) missing constraints with null
mapping
using a null mapping:
openapi-processor-mapping: v7
options:
bean-validation: true
map:
paths:
/foo:
null: org.openapitools.jackson.nullable.JsonNullable
on a property
properties:
bar:
nullable: true
type: string
maxLength: 4
did not add the constraint to the generated property.
dependency updates
- updated (internal) OpenAPI parser to 2024.3 (was 2024.2)
- updated swagger parser to 2.1.22 (was 2.1.21)
2024.3
(#130) (fix) setting the new compatibility options did not work
setting the new compatibility options did not work, it was always using the default values.
(#129) remove extra line feed in javadoc
removed the extra line feed (an empty line) in javadoc comments between summary and description.
(#123) optionally clear output directory
its is now possible to disable clearing of the targetDir
when the processor is writing the generated files.
openapi-processor-mapping: v7
options:
# ...
# enable/disable deletion of targetDir: true (default) or false.
clear-target-dir: false
2024.2
(#92) (new) annotation mapping by OpenAPI extensions
it is now possible to use OpenAPI x-
tensions to add additional annotations to schema properties:
Here is a simple schema that has x-
tensions on the bar
property.
openapi: 3.1.0
# ...
components:
schemas:
Foo:
type: object
properties:
bar:
type: string
x-foo: single
x-bar:
- listA
- listB
we can now map the x-
tensions/values to annotations like this:
openapi-processor-mapping: v6
map:
extensions:
x-foo: single @ io.oap.FooA(value = "any")
x-bar:
- listA @ io.oap.FooB
- listB @ io.oap.FooC
.. which will generate the additional annotations on the property:
package generated.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
import io.oap.FooA;
import io.oap.FooB;
import io.oap.FooC;
@Generated(value = "openapi-processor-core", version = "test")
public class Foo {
@FooA(value = "any")
@FooB
@FooC
@JsonProperty("bar")
private String bar;
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
(new) annotation mapping by parameter name
another small improvement to annotation mapping is that we can add annotations by parameter name:
openapi-processor-mapping: v6
map:
parameters:
- name: foo @ annotation.Foo
(breaking) (openapi-processor/openapi-processor-spring/issues/229) reactive bean validation
the position of the @Valid
annotation on reactive types has changed.
Until now the @Valid
was placed on the generic type of the reactive wrapper, like this:
@Mapping("/foo-flux")
void postFooFlux(@Parameter Flux<@Valid Bar> body);
but validation did not happen with Spring. Spring needs the @Valid
on the reactive wrapper to trigger the validation. Therefore @Valid
is now placed by default on the reactive wrapper:
@Mapping("/foo-flux")
void postFooFlux(@Parameter @Valid Flux<Bar> body);
It should only take a bit annotation clean up on the interface implementations to adapt your code to the new @Valid
position.
keeping the old behavior
To postpone the update, set the bean-validation-valid-on-reactive
option to false
.
openapi-processor-mapping: v6
options:
# ...
compatibility:
# optional, default is true
bean-validation-valid-on-reactive: false
I would like to remove this option in the future. If you still need the old @Valid
position please create an issue to help me understand why the old @Valid
position is still useful.
(breaking) identifier word breaks
the processor does now recognize a change from letter to number as a word break. The improves generation of camel case identifiers.
given an identifier from the OpenAPI description, the processor would generate the following names for different kinds of identifiers:
OpenAPI | camel case | variable | class | enum | |
---|---|---|---|---|---|
new | foo2Bar | foo2Bar | foo2Bar | Foo2Bar | FOO2_BAR |
old | foo2Bar | foo2bar | foo2bar | Foo2bar | FOO2BAR |
keeping the old behavior
To postpone the update, set the identifier-word-break-from-digit-to-letter
option to false
.
openapi-processor-mapping: v6
options:
# ...
compatibility:
# optional, default is true
identifier-word-break-from-digit-to-letter: false
(openapi-processor/openapi-processor-spring#239) Support Mono as result type by @maddingo
previous versions allowed to configure a result wrapper (e.g. Spring ResponseEntity
) and reactive types via single
and multi
mapping.
openapi-processor-mapping: v6
options:
# ...
map:
result: org.springframework.http.ResponseEntity
single: reactor.core.publisher.Mono
multi: reactor.core.publisher.Flux
Using both always wraps the reactive types with the result
type. For example with Spring ResponseEntity
(result type
) and the reactor types Mono
and Flux
as
ResponseEntity<Mono<...>>
ResponseEntity<Flux<...>>
Unfortunately if you need the reactive result to modify the http response, something like this:
// does not work
public ResponseEntity<Mono<Result>> someEndpoint() {
return someBean.getResult()
.map(r -> ResponseEntity
.ok()
.eTag(r.eTag())
.body(Mono.just(r)));
}
it will not work because the final type of the statement is Mono<ResponseEntity<Mono<Result>>>
and not the expected ResponseEntity<Mono<Result>>
.
With this release we can fix that by setting the result
mapping to
openapi-processor-mapping: v6
options:
# ...
map:
# wrap the ResponseEntity with Mono
result: reactor.core.publisher.Mono<org.springframework.http.ResponseEntity>
single: reactor.core.publisher.Mono
multi: reactor.core.publisher.Flux
which will generate the endpoint signature as
public Mono<ResponseEntity<Mono<Result>>> someEndpoint() {
// ...
}
and the above code will now work.
It is recommended to configure this on the endpoint level if you just need this for a few endpoints.
See also Spring ResponseEntity
documentation.