Skip to content

Releases: openapi-processor/openapi-processor-base

2023.5

22 Oct 16:20

Choose a tag to compare

#59 (new) support primitive types

it is now possible to use primitive types in mapping.yaml:

openapi-processor-mapping: v4

options:
  package-name: generated

map:
  types:
    - type: string:binary => byte[]

dependency updates

  • updated (internal) OpenAPI parser to 2023.5 (was 2023.4)
  • updated swagger parser to 2.1.18 (was 2.1.16)

2023.4

17 Sep 12:38

Choose a tag to compare

json schema validation for OpenAPI 3.1

the processor does now run json schema validation on OpenAPI 3.1 documents.

#42 (new) automatically clear output directory

when called, the processor clears the target directory to avoid any left over/obsolete files from previous runs.

#43 (new) 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<?>

(fix) 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.

(fix) 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.

(improvement) write http operations in original order

the controller endpoint methods for the http operations are written in the same order as in the OpenAPI description.

Unfortunately this doesn't work for with the swagger OpenAPI parser because it doesn't preserve the original order.

dependency updates

  • updated (internal) OpenAPI parser to 2023.4

2023.3

03 Jul 07:29

Choose a tag to compare

#30 (new) object @ annotation

it is now 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 {
   ...
}

#3 (new), java record support

openapi-processor is now capable of generating java records 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;
    }

}

#7 (changed), java-format

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 I have modified the default from true to false.

To (re-) enable code formatting add the format-codeoption to the mapping.yaml:

openapi-processor-mapping: v4

options:
  format-code: true

#33 (fix) add an annotation only to the model class

having an annotation mapping on multiple model classes:

map:
  types:
    - type: Foo1 @ annotation.Bar 
    - type: Foo2 @ annotation.Bar 

where Foo1 has a property of type Foo2 the processor adds the annotation to the Foo2 class only but not on the Foo2 property in Foo1.

Because Foo2 is a generated class, it can put the annotation at the class and it is not necessary to put it on the property too. The annotation will only be placed at the property level if the property type is a mapped type where the class itself can't be modified.

dependency updates

  • updated swagger parser to 2.1.15 (was 2.1.14)
  • update jackson to 2.15.2 (was 2.15.1)

2023.2.2

15 Jun 06:06

Choose a tag to compare

#29 (fix), a property with a java keyword name generates invalid Java code

This was fixed in 2023.2.1 for parameters & properties. This version does no longer generate a getClass() method in a model or interface. getClass() can not and should not be overridden.

2023.2.1

14 Jun 05:35

Choose a tag to compare

#29 (fix), a property with a java keyword name generates invalid Java code

using a parameter/property name that was identical to a java keyword generated invalid Java code. For example, with a parameter and property name class:

openapi: 3.0.3
info:
  title: keyword identifier
  version: 1.0.0

paths:

  /keywords:
    get:
      parameters:
        - name: class
          description: parameter
          in: query
          schema:
            $ref: '#/components/schemas/class'
      responses:
        '200':
          description: the foo result
          content:
            application/json:
                schema:
                  $ref: '#/components/schemas/class'

components:
  schemas:

    class:
      type: object
      properties:
        class:
          type: string

the processor did generate interfaces with an invalid class parameter name and a model class with an invalid property name class.

Now it adds a a prefix if a parameter/property name is identical to any keyword:

package generated.api;

import annotation.Mapping;
import annotation.Parameter;
import generated.model.Class;
import generated.support.Generated;

@Generated(value = "openapi-processor-core", version = "test")
public interface Api {

    @Mapping("/keywords")
    Class getKeywords(@Parameter Class aClass);

}
package generated.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import generated.support.Generated;

@Generated(value = "openapi-processor-core", version = "test")
public class Class {

    @JsonProperty("class")
    private String aClass;

    public String getClass() {
        return aClass;
    }

    public void setClass(String aClass) {
        this.aClass = aClass;
    }

}

#25 (fix), invalid type of enum parameter

an enum parameter name was not properly converted to valid class name. With a name foo-foo

openapi: 3.0.0
info:
  title: sample API
  version: 1.0.0

paths:
  /foo:
    get:
      parameters:
        - name: foo-foo
          description: test parameter
          in: query
          schema:
            type: string
            enum:
              - foo-1
      responses:
        '204':
          description: response

the processor generated a class Foo-foo instead of FooFoo:

public interface Api {

    @GetMapping(path = "/foo")
    void getFoo(@RequestParam(name = "foo-foo", required = false) Foo-foo fooFoo);

}

#24 (fix), doesn't find nested schemas of additionalProperties

using {package-name} with a nested schema of additionalProperties did not find the nested schema.

this prevented mappings like

map:
  types:
    - type: Values => java.util.Map<java.lang.String, {package-name}.model.Value>>
    - type: MultiValues => java.util.Map<java.lang.String, java.util.List<{package-name}.model.Value>>>

assuming Values is nested schema of additionalProperties:

components:
  schemas:

    Values:
      description: key is string, value is a Value object
      type: object
      additionalProperties:
        $ref: '#/components/schemas/Value'

2023.2

01 Jun 06:58

Choose a tag to compare

openapi-processor/openapi-processor-spring#150 (new), type mapping with nested generics

so far openapi-processor did allow only one level of generics. It is now possible to create type mappings with nested generics types.

openapi-processor-mapping: v2

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

openapi-processor/openapi-processor-spring#161 (new), annotation mapping allows class parameter

annotation mapping now accepts a java class type as parameter. It is now possible to add a mapping like this:

openapi-processor-mapping: v3

map:
  types:
    - type: string:foo @ io.oap.Annotation (value = io.oap.Bar.class)

openapi-processor/openapi-processor-spring#160 (fix), lost javadoc comment with type mapping

having a type mapping on the type of an object property did not write its description as javadoc comment as it does without mapping.

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.

dependency updates

  • updated internal openapi-parser to 2023.2 (was 2023.1)
  • updated swagger parser to 2.1.14 (was 2.0.28)
  • update jackson to 2.15.1 (was 2.14.1)

2023.1.2

23 Jan 07:52

Choose a tag to compare

openapi-processor/openapi-processor-spring#157, bean validation support for mapped types broke additional parameters

the bean validation support on mapped types introduced in 2023.1 did not properly handle additional parameters.

openapi-processor/openapi-processor-spring#156, wrong bean-validation option in mapping json schema

the definition of the bean-validation option in the mapping.yaml expected string "true"/"false" instead of boolean true/false .

2023.1.1

03 Jan 17:16

Choose a tag to compare

this fixes the bad internal openapi-parser dependency that broke 2023.1

See v2023.1 for the changes.

2023.1

02 Jan 16:50

Choose a tag to compare

#2, 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;

     // ....
}

openapi-processor/openapi-processor-spring#152, 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

openapi-processor/openapi-processor-spring#149, 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 pseudo code 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

}

2022.6

23 Dec 10:11

Choose a tag to compare

copied from openapi-processor-core

annotation mapping

annotation mappings allows to add additional annotations to an OpenAPI source type.

(this originates from openapi-processor/openapi-processor-spring#143 advanced validation support, but has changed into a more general solution)

Currently, this is available as

  • global annotation type mapping:

    it adds an annotation to the model class generated for the source type.

  • global & endpoint parameter annotation type mapping:

    it adds an annotation to a parameter of the source type. Since a request body is passed as parameter the mapping will work for it too.

The global annotation mapping should be added to the map/types or map/parameters section in the mapping.yaml.

The endpoint (http method) mapping restricts the mapping to a specific endpoint. This will go to the map/paths/<endpoint-path>/parameters section in the mapping.yaml.

The annotation type mapping is similar to other mappings and is defined like this:

- type: {source type} @ {annotation type}

Here is an examples mapping.yaml that defines additional annotations for two schemas (model classes) Foo & Bar:

openapi-processor-mapping: v2.1 # <1>

options:
  package-name: io.openapiprocessor.openapi
  bean-validation: true

map:
  types:
    - type: Bar @ io.openapiprocessor.samples.validations.Sum(24) # <2>

  parameters:
    - type: Foo @ io.openapiprocessor.samples.validations.Sum(value = 42) # <3>

      # this formats do work too <4>
      # - type: Foo @ annotation.Bar
      # - type: Foo @ annotation.Bar()
      # - type: Foo @ annotation.Bar("bar")
      # - type: Foo @ annotation.Bar(value = "bar", foo = 2)

The Sum annotation in the example is a custom bean validation but the feature itself is not limited to bean validation.

<1> use v2.1 as the mapping version to avoid validation warnings in the mapping file.
<2> the Bar mapping is using a global type annotation mapping, so the annotation is added to the generated Bar class.
<3> the Foo mapping adds the annotation to the parameter of the endpoint methods that use Foo.
<4> this is a list of examples that shows annotation parameters.

The Bar annotation mapping will produce the Bar model class with the additional annotation on the class:

@Sum(24) // <1>
public class Bar { /* ... */ }

The Foo annotation parameter mapping will produce the endpoint with the additional annotation on the Foo parameter:

    @PostMapping(/*...*/)
    Foo postFoo(@RequestBody @Sum(value = 42) @Valid @NotNull Foo body);

The full example is available in the spring validation sample.

openapi-processor/openapi-processor-spring#144, use annotation for generated code instead of comment

the processor now generates a @Generated annotation and adds it to all generated interfaces and classes instead of the text header.

Some tools recognize the @Generated annotation and exclude them from processing. For example, jacoco will automatically exclude the @Generated files from the code coverage.

this will look like this:

package io.openapiprocessor.release;

import io.openapiprocessor.release.support.Generated;
import org.springframework.web.bind.annotation.GetMapping;

@Generated(value = "openapi-processor-spring", version = "2022.6", date = "2022-09-28T18:37:33.250622+02:00")
public interface ReleaseApi {
// ...
}

Because of the longish date the code formatter will probably add a few line breaks.

Generation of the data parameter can be disabled by setting the generated-date option to false:

openapi-processor-mapping: v2.1 # <1>

options:
  package-name: io.openapiprocessor.openapi
  generated-date: false

<1> use v2.1 as the mapping version to avoid validation warnings in the mapping file.

openapi-processor/openapi-processor-spring#140 additional parameter configuration did not working in global context

using an additional parameter in the global context was not implemented.

map:
  parameters:
    - add: request => javax.servlet.http.HttpServletRequest

openapi-processor/openapi-processor-core#99 windows path handling

was broken since 2022.5