2023 Releases
November 2023
-
openapi-processor-spring/micronaut 2023.6
support different enum styles
it is now possible to (globally) configure different enum types in mapping.yaml:
openapi-processor-mapping: v5
options:
package-name: generated
enum-type: default|string|framework
default, which is default, creates a simple java enum with all uppercase enum values. It will create the same code as previous versions.
string, simply uses String and does not create an enum class. This is useful if automatic conversion of the incoming value to a java enum value does not work. In case bean-validation is enabled the processor adds a (generated) validation annotation that verifies that the string is a valid (OpenAPI) enum value.
public interface FooApi {
@Mapping(path = "/foo", produces = {"application/json"})
Foo postFoo(@Parameter(name = "enum") @Values(values = {"one", "two"}) String aEnum);
}
framework, is a placeholder for framework specific enum generation, only supported by openapi-processor-spring.
It generates a Java enum class similar to the default enum type. In addition, it generates a Spring ConverterFactory that Spring can use to convert incoming enum values to its corresponding java enum value (if passed as a parameter, not as part of the body).
To enable the ConverterFactory, create a configuration class like this:
package io.openapiprocessor.samples;
import {package-name}.spring.StringToEnumConverterFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@SuppressWarnings("rawtypes")
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new StringToEnumConverterFactory());
}
}
This registration is one time task. The converter factory does create an enum converter for all generated enum classes.
There is a sample that is using different enum-type configurations (string & framework).
September 2023
-
openapi-processor-spring/micronaut 2023.4
json schema validation for OpenAPI 3.1
the processor does now run json schema validation on OpenAPI 3.1 documents.
automatically clear output directory
when called, the processor clears the target directory to avoid any left over/obsolete files from previous runs.
accept generic wildcard in mapping
it is now possible to use the generic ? in a mapping.
openapi-processor-mapping: v4
options:
package-name: io.openapiprocessor.generated
map:
parameters:
- add: foo => io.openapiprocessor.GenericType<?>
Spring: missing import
Spring doesn’t have shortcut annotations, e.g. @GetMapping instead of @RequestMapping(…, method = RequestMethod.HEAD) for the http methods HEAD, OPTIONS & TRACE.
The processor does now add the missing import of RequestMethod.
improved json schema of mapping.yaml
when using endpoint specific mappings the processor (sometimes) complained about invalid entries in the mapping.yaml. This was caused by wrong definitions in the corresponding json schema.
don’t request json schema draft
a miss-configuration of the json-schema validator caused an unnecessary network request to download a json schema (draft 7) from https://json-schema.org.
July 2023
-
openapi-processor-spring/micronaut 2023.3
object @ annotation
Using the object keyword it is possible to add an annotation to all generated schema/model classes using a single annotation mapping:
map:
types:
- type: object @ lombok.Builder
The object string represents all generated object classes (i.e. schema/model classes) and will add the given annotation only at the class level:
@Builder
@Generated(...)
public class Foo {
...
}
java records
openapi-processor is now capable of generating java record s instead of pojos for schemas. This is a global setting in the mapping.yaml. It can either have the value default (which is default) to generate pojos or record to generate records.
openapi-processor-mapping: v4
options:
model-type: record
With model-type: record the processor will generate record s like this:
package generated.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
@Generated(value = "openapi-processor-core", version = "test")
public record Foo(
@JsonProperty("bar")
String bar
) {}
and without model-type or model-type: default it will create a simple pojo:
package generated.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;
@Generated(value = "openapi-processor-core", version = "test")
public class Foo {
@JsonProperty("bar")
private String bar;
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
java-format option
openapi-processor uses google-java-format to format the generated files (including javadoc). Unfortunately it depends on internal jdk packages that are strongly encapsulated since JDK 16. It is necessary to tell the jdk to export a few packages.
In theory, it is not hard to configure it but in real life it is a bit fiddly to get this working. To get started without fighting with it, the default is now false instead of true.
To (re-)enable code formatting add the format-code option to the mapping.yaml:
openapi-processor-mapping: v4
options:
format-code: true
June 2023
-
openapi-processor-spring/micronaut 2023.2
nested generic types
It is now possible to create type mappings with nested generics types. Here are a few examples:
openapi-processor-mapping: v3
options:
package-name: generated
map:
types:
- type: Foo => java.util.Map<java.lang.String, java.util.List<java.lang.String>>
paths:
/foo:
responses:
- content: application/json => java.util.Map<java.lang.String, java.lang.String>
/foo2:
responses:
- content: application/json => java.util.Map<java.lang.String, java.util.List<java.lang.String>>
This is useful to map an OpenAPI dictionary description using additionalProperties to a proper java map type:
# a schema the defines a dictionary with string keys and string values
Map:
type: object
additionalProperties:
type: string
annotation mapping allows class parameter
annotation mapping now accepts a java class type as parameter. It is possible to add a mapping like this:
openapi-processor-mapping: v3
map:
types:
- type: string:foo @ io.oap.Annotation (value = io.oap.Bar.class)
improved validation output
schema validation by the internal parser has simpler & better output based on the JSON schema basic output format. It is not perfect but it is getting better.
It will provide better help on where the error is, but it may report multiple ambiguous errors.
If a schema property uses anyOf or oneOf and all possibilities don’t match (e.g. because there is a spelling error) the validator can’t know which one was meant and complains about all of them.
An example:
the error the value does not validate against the 'false' schema at instance … usually means that a property has a spelling error.
If the OpenAPI allows a $ref at the same location the validator reports a second error should have a property '$ref' at instance … because a reference object must have a $ref property.
January 2023
-
openapi-processor-spring/micronaut 2023.1
support requestBody $ref
the processor is now able to resolve $ref s of requestBody (This works with all 3 OpenAPI parsers).
openapi: 3.1.0
info:
title: components requestBodies
version: '1.0'
paths:
/foo:
post:
responses:
'200':
description: ok
content:
application/json:
schema:
type: string
requestBody:
$ref: '#/components/requestBodies/Foo' (1)
components:
requestBodies:
Foo:
content:
application/json:
schema:
type: object
properties:
foo:
type: string
| 1 | $ref is direct child of requestBody. |
annotation mapping support for simple data types
it is now possible to add an annotation mapping for simple data types (format works too):
openapi-processor-mapping: v3
map:
types:
- type: string:uuid => java.util.UUID
- type: string:uuid @ annotation.Bar
openapi-processor will add it on any string:uuid property used in the generated model classes:
@Generated
public class Foo {
@Bar
@JsonProperty("foo")
private UUID foo;
// ....
}
annotation mapping support for mapped types
in the previous version an annotation mapping was lost if the type was mapped at the same time to an existing class. It will now add the annotation to the existing class if possible.
Assume the following mapping:
openapi-processor-mapping: v3
options:
map:
types:
- type: Foo => openapiprocessor.MappedFoo
- type: Foo @ annotation.Bar (1)
parameters:
- type: Foo @ annotation.Bar (2)
MappedFoo is a class that is not generated. Adding an annotation at the parameter level works as expected (mapping <2>). But it is not possible to add the Bar annotation directly at the class (mapping <1>):
@Bar
@Generated
public class Foo {
// ....
}
instead, openapi-processor will add it on any MappedFoo property used in the generated model classes:
@Generated
public class FooBar {
@Bar
@JsonProperty("foo")
private MappedFoo foo;
// ....
}
bean validation v3 support
Spring Boot 3 updates bean validations to v3. In v3 the package name changed from javax to jakarta. It is now possible to select between the v2 & v3 version in the mapping.yaml.
the new mapping schema v3 adds javax and jakarta as possible values for the bean-validation option. true/false will still work as before.
# use v3 for proper validation of the mapping file
openapi-processor-mapping: v3
options:
# no bean validation, as before
bean-validation: false
# enable bean validation, as before (will use `javax...`)
bean-validation: true
# new: enable bean validation with `javax...`
bean-validation: javax
# new: enable bean validation with `jakarta...`
bean-validation: jakarta
bean validation support on mapped data types
openapi-processor now preserves bean validation annotations when the source data type is mapped to an existing class. This is most interesting for the @Valid annotation.
It adds the annotations it would add on the source data type. In previous versions the annotations got lost when the data type was mapped to an existing class. Without`@Valid` the validation would not be triggered on the mapped object.
having this OpenAPI description
openapi: 3.1.0
info:
title: mapped bean validation
version: 1.0.0
paths:
/foo:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Foo'
responses:
204:
description: none
components:
schemas:
Foo:
type: object
properties:
foo:
type: integer
minimum: 0
the endpoint looks like this without a mapping that replaces Foo (ignore the @Mapping/@Parameter annotations, this is pseudocode used by the integration tests):
package generated.api;
import annotation.Mapping;
import annotation.Parameter;
import generated.model.Foo;
import javax.validation.Valid;
public interface Api {
@Mapping("/foo")
void postFoo(@Parameter @Valid Foo body); // has @Valid annotation
}
with a mapping that replaces Foo with Bar
openapi-processor-mapping: v3
options:
package-name: generated
bean-validation: true
map:
types:
- type: Foo => openapiprocessor.Bar
it will now generate the endpoint with a @Valid on the mapped data type.
package generated.api;
import annotation.Mapping;
import annotation.Parameter;
import javax.validation.Valid;
import openapiprocessor.Bar;
public interface Api {
@Mapping("/foo")
void postFoo(@Parameter @Valid Bar body); // new: has @Valid annotation
}