<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Martin Hauner</title>
    <description>The latest articles on DEV Community by Martin Hauner (@hauner).</description>
    <link>https://dev.to/hauner</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F395045%2F057516b9-05f5-494d-a621-66c7e2f5a6c5.png</url>
      <title>DEV Community: Martin Hauner</title>
      <link>https://dev.to/hauner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hauner"/>
    <language>en</language>
    <item>
      <title>mapping OpenAPI formats</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Thu, 08 Jun 2023 10:00:00 +0000</pubDate>
      <link>https://dev.to/hauner/mapping-openapi-formats-1h9o</link>
      <guid>https://dev.to/hauner/mapping-openapi-formats-1h9o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;what is &lt;em&gt;openapi-processor&lt;/em&gt;? &lt;a href="https://openapiprocessor.io"&gt;openapi-processor&lt;/a&gt; is an &lt;em&gt;easy-to-use&lt;/em&gt; tool to generate java based (annotated) controller &lt;em&gt;interfaces&lt;/em&gt; and &lt;em&gt;pojos&lt;/em&gt; (model classes) from an OpenAPI yaml description. It supports &lt;em&gt;Spring Boot&lt;/em&gt;, &lt;em&gt;Micronaut&lt;/em&gt; with &lt;em&gt;maven&lt;/em&gt; or &lt;em&gt;gradle&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assume we have this simple (but useless ;-) OpenAPI description. It uses a custom integer &lt;code&gt;format&lt;/code&gt; to specify that the integer parameter and response represents a &lt;em&gt;year&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3.1&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pending API&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;

&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo query parameter with type mapping&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;year&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;the year&lt;/span&gt;
          &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;
            &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;year&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo response&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;text/plain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;
                &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;year&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; the integer type with custom &lt;code&gt;format&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default, openapi-processor-spring does not know what to do with the custom format and simply maps the OpenAPI &lt;code&gt;integer&lt;/code&gt; to a Java &lt;code&gt;Integer&lt;/code&gt;.&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;em&gt;the generated interface code&lt;/em&gt;
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.oap.api&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.oap.support.Generated&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.constraints.NotNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RequestParam&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Generated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openapi-processor-spring"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2023.2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Api&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * echo query parameter with type mapping
     *
     * @return echo response
     */&lt;/span&gt;
    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/query"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;produces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="nf"&gt;getQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"year"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since Java has a &lt;code&gt;java.time.Year&lt;/code&gt; class it could be useful to use it instead of &lt;code&gt;Integer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can &lt;em&gt;easily&lt;/em&gt; help openapi-processor to generate the interface with &lt;code&gt;java.time.Year&lt;/code&gt; by adding a &lt;em&gt;type mapping&lt;/em&gt; to the &lt;code&gt;mapping.yaml&lt;/code&gt; configuration.&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;em&gt;mapping.yaml&lt;/em&gt;
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi-processor-mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v3&lt;/span&gt;

&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;generated-date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.openapiprocessor.oap&lt;/span&gt;
  &lt;span class="na"&gt;bean-validation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;javax&lt;/span&gt;
  &lt;span class="na"&gt;javadoc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer:year =&amp;gt; java.time.Year&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; this is the interesting part of the &lt;code&gt;mapping.yaml&lt;/code&gt;. It tells the processor to map the integer custom format to the &lt;code&gt;java.time.Year&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;The left side of the arrow is the &lt;code&gt;type&lt;/code&gt; : &lt;code&gt;format&lt;/code&gt; combination used in the OpenAPI and on the right side is the fully qualified java class name that is used in the generated code.&lt;/p&gt;

&lt;p&gt;Regenerating the code will now generate the interface like this:&lt;/p&gt;

&lt;h6&gt;
  
  
  the generated interface code
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.oap.api&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.oap.support.Generated&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Year&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.constraints.NotNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RequestParam&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Generated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openapi-processor-spring"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2023.2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Api&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * echo query parameter with type mapping
     *
     * @return echo response
     */&lt;/span&gt;
    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/query"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;produces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="nc"&gt;Year&lt;/span&gt; &lt;span class="nf"&gt;getQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"year"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Year&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; it is now using &lt;code&gt;java.time.Year&lt;/code&gt; instead of &lt;code&gt;Integer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Easy :-)&lt;/p&gt;

&lt;p&gt;If such a custom type is used in a property of an OpenAPI schema, openapi-processor will use the same type mapping definition.&lt;/p&gt;

&lt;p&gt;We can use this simple mechanism for many other types to improve the generated code, for example:&lt;/p&gt;

&lt;h6&gt;
  
  
  type mapping examples
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string:uuid =&amp;gt; java.util.UUID&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string:date-time =&amp;gt; java.time.Instant&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string:offset-date-time =&amp;gt; java.time.OffsetDateTime&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm sure you can find more useful mappings. :-)&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;summary&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This short article described how easy it is to improve the openapi-processor generated code with a type mapping. &lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://openapiprocessor.io"&gt;documentation&lt;/a&gt; for more.&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>java</category>
      <category>springboot</category>
      <category>micronaut</category>
    </item>
    <item>
      <title>annotation mapping &amp; bean-validation</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Sun, 16 Oct 2022 15:44:06 +0000</pubDate>
      <link>https://dev.to/hauner/annotation-mapping-bean-validation-bd</link>
      <guid>https://dev.to/hauner/annotation-mapping-bean-validation-bd</guid>
      <description>&lt;p&gt;The &lt;a href="https://openapiprocessor.io/oap/home/new/spring-2022.5.html"&gt;openapi-processor-spring/micronaut release 2022.5&lt;/a&gt; adds a new &lt;em&gt;annotation type mapping&lt;/em&gt; feature. It provides the possibility to add additional annotations to generated interfaces &amp;amp; classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  what is openapi-processor?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://openapiprocessor.io"&gt;openapi-processor&lt;/a&gt; is a small framework to process OpenAPI yaml files. Currently, openapi-processor provides java code generation for Spring Boot &amp;amp; Micronaut.&lt;/p&gt;

&lt;p&gt;It does support gradle and maven with plugins to convert OpenAPI yaml files to java (controller) interfaces &amp;amp; (payload) pojo classes as part of the build process.&lt;/p&gt;

&lt;p&gt;It generates Java because the controller interface and pojo classes are easily usable from other jvm languages. Usually you will just use them without looking at the generated code.&lt;/p&gt;

&lt;h2&gt;
  
  
  annotation mapping
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;annotation type mapping&lt;/em&gt; allows to add annotations to a generated model class or to an endpoint method parameters of that class.&lt;/p&gt;

&lt;p&gt;Let's look at a contrived example to add a custom bean validation to the pojo model class of a schema.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://openapiprocessor.io/spring/mapping/annotation.html"&gt;annotation mapping&lt;/a&gt; documentation for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  the example api
&lt;/h2&gt;

&lt;p&gt;here is a simple api that takes a Foo schema as request body. The schema has some (useless ;-) number constraints on its properties.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;openapi.yaml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.1.0&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;annotation mapping example&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;

&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;annotation mapping example endpoint.&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;a simple endpoint where an annotation mapping is used on the request body&lt;/span&gt;
      &lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Foo'&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;201'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;empty response&lt;/span&gt;

&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;foo1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
          &lt;span class="na"&gt;minimum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
        &lt;span class="na"&gt;foo2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
          &lt;span class="na"&gt;minimum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  bean validation annotations
&lt;/h2&gt;

&lt;p&gt;Enabling bean validation in the &lt;code&gt;mapping.yaml&lt;/code&gt; (the processor configuration) will generate a &lt;code&gt;Foo&lt;/code&gt; class with bean validation annotations for the property constraints.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;generated file&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.openapi.model&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fasterxml.jackson.annotation.JsonProperty&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.openapi.support.Generated&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.constraints.DecimalMin&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Generated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openapi-processor-spring"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2022.5"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@DecimalMin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
    &lt;span class="nd"&gt;@JsonProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@DecimalMin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-10"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
    &lt;span class="nd"&gt;@JsonProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="nf"&gt;getFoo1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setFoo1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;foo1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="nf"&gt;getFoo2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setFoo2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;foo2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; the bean validation annotations created from the OpenAPI constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  custom bean validation annotation
&lt;/h2&gt;

&lt;p&gt;Now we like to add a validation that checks the sum of the two &lt;code&gt;Integer&lt;/code&gt; properties by writing &lt;code&gt;@Sum(24)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's create the annotation&lt;/p&gt;

&lt;p&gt;&lt;em&gt;manually created custom bean validation annotation&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.samples.validations&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.Constraint&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.Payload&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.lang.annotation.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Constraint&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validatedBy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;FooSumValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt; &lt;span class="o"&gt;({&lt;/span&gt; &lt;span class="nc"&gt;ElementType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ElementType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PARAMETER&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RetentionPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Sum&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;message&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="s"&gt;"invalid sum"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;[]&lt;/span&gt; &lt;span class="n"&gt;groups&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;{};&lt;/span&gt;
    &lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Payload&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;[]&lt;/span&gt; &lt;span class="nf"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;{};&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the validation code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;manually created validation&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.samples.validations&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.openapi.model.Foo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.ConstraintValidator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.ConstraintValidatorContext&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooSumValidator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ConstraintValidator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sum&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Sum&lt;/span&gt; &lt;span class="n"&gt;constraintAnnotation&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constraintAnnotation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt; &lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ConstraintValidatorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFoo1&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFoo2&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  mapping for the custom annotation
&lt;/h2&gt;

&lt;p&gt;Now comes the interesting part, the &lt;em&gt;annotation type mapping&lt;/em&gt; that tells the processor to add our custom annotation to the generated &lt;code&gt;Foo&lt;/code&gt; pojo model class.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;processor configuration mapping.yaml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi-processor-mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2.1&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.openapiprocessor.openapi&lt;/span&gt;
  &lt;span class="na"&gt;bean-validation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# &amp;lt;2&amp;gt;&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Foo @ io.openapiprocessor.samples.validations.Sum(24)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; the new mapping version. Using another version will produce a warning that the mapping is invalid.&lt;/p&gt;

&lt;p&gt;&amp;lt;2&amp;gt; the annotation mapping that tells the processor to @nnotate the &lt;code&gt;Foo&lt;/code&gt; schema (&lt;code&gt;Foo&lt;/code&gt; is the name of the OpenAPI schema) with the given annotation to the pojo model class generated for the &lt;code&gt;Foo&lt;/code&gt; schema. The annotation is given with the fully qualified name (required to create the import) and (optionally) with fixed parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  model class with custom annotation
&lt;/h2&gt;

&lt;p&gt;Now, with the annotation mapping in the configuration the processor will generate &lt;code&gt;Foo&lt;/code&gt; like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;generated file with custom annotation&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.openapi.model&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fasterxml.jackson.annotation.JsonProperty&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.openapi.support.Generated&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.constraints.DecimalMin&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.samples.validations.Sum&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Sum&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;span class="nd"&gt;@Generated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openapi-processor-spring"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2022.5"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@DecimalMin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@JsonProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@DecimalMin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-10"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@JsonProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="nf"&gt;getFoo1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setFoo1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;foo1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="nf"&gt;getFoo2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setFoo2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;foo2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; our custom bean validation annotation.&lt;/p&gt;

&lt;h2&gt;
  
  
  summary
&lt;/h2&gt;

&lt;p&gt;This little article described how to add a custom annotation to a generated class by adding an annotation type mapping to the processor mapping configuration.&lt;/p&gt;

&lt;p&gt;To learn more about openapi-processor and how to generate controller interfaces and model classes from an OpenAPI description take a look at the &lt;a href="https://openapiprocessor.io"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>java</category>
      <category>springboot</category>
      <category>micronaut</category>
    </item>
    <item>
      <title>openapi-processor-spring 2021.4 &amp; micronaut 2021.2</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Mon, 31 May 2021 21:44:00 +0000</pubDate>
      <link>https://dev.to/hauner/openapi-processor-spring-2021-4-micronaut-2021-2-3ila</link>
      <guid>https://dev.to/hauner/openapi-processor-spring-2021-4-micronaut-2021-2-3ila</guid>
      <description>&lt;h1&gt;
  
  
  what is openapi-processor?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.openapiprocessor.io/oap/home/home.html"&gt;openapi-processor&lt;/a&gt; is a small framework to process OpenAPI yaml files. Currently, openapi-processor provides java code generation for Spring Boot, Micronaut and conversion to json.&lt;/p&gt;

&lt;p&gt;It does support &lt;a href="https://docs.openapiprocessor.io/gradle"&gt;gradle&lt;/a&gt; and &lt;a href="https://docs.openapiprocessor.io/maven"&gt;maven&lt;/a&gt; to run any openapi-processor as part of the build process.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://docs.openapiprocessor.io"&gt;documentation&lt;/a&gt; for more. There is also a &lt;a href="https://playground.openapiprocessor.io"&gt;playground&lt;/a&gt; to preview the processors.&lt;/p&gt;

&lt;h1&gt;
  
  
  what is new?
&lt;/h1&gt;

&lt;p&gt;See the &lt;a href="https://github.com/openapi-processor/openapi-processor-spring/releases/tag/v2021.4"&gt;release notes&lt;/a&gt; for the full details (it is the same for spring &amp;amp; micronaut).&lt;/p&gt;

&lt;p&gt;Apart from a couple of bug fixes and improvements for multipart requests and bean-validations, openapi-processor is now able to automatically add a suffix to the generated model classes.&lt;/p&gt;

&lt;p&gt;This is enabled by configuring the &lt;code&gt;model-name-suffix&lt;/code&gt; in the &lt;code&gt;mapping.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi-processor-mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;

&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.openapiprocessor.sample&lt;/span&gt;
  &lt;span class="na"&gt;model-name-suffix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Resource&lt;/span&gt; &lt;span class="c1"&gt;# or Dto or ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;model-name-suffix&lt;/code&gt; option sets a suffix that is automatically appended to all generated model and enum classes.&lt;/p&gt;

&lt;p&gt;The suffix helps to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;avoid duplicate class names in generated code and normal code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;makes it easier to recognize which role or in which context a class is used. Is it a data transfer class or is it a domain class?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keeps the suffix &lt;em&gt;"noise"&lt;/em&gt; out of the OpenAPI description&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usually you will separate the classes by putting them in different packages. This helps to distinguish the classes, but when both are used in the same code, i.e. when converting one format to the other, it is a lot easier to distinguish them by their class name instead of their package name.&lt;/p&gt;

&lt;p&gt;If a schema name from the OpenAPI description already ends with the &lt;code&gt;model-name-suffix&lt;/code&gt;, the processor will not append the suffix. This allows to migrate an existing api with a suffix in the API to &lt;code&gt;model-name-suffix&lt;/code&gt; step by step.&lt;br&gt;
Example:&lt;/p&gt;

&lt;p&gt;OpenAPI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;the foo result&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Foo'&lt;/span&gt; &lt;span class="c1"&gt;# (1)&lt;/span&gt;

&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;Foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;nested&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/BarResource'&lt;/span&gt; &lt;span class="c1"&gt;# (1)&lt;/span&gt;

    &lt;span class="na"&gt;BarResource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mapping.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi-processor-mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;

&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.openapiprocessor.sample&lt;/span&gt;
  &lt;span class="na"&gt;model-name-suffix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Resource&lt;/span&gt; &lt;span class="c1"&gt;# (2)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// interface&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Api&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Mapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/foo"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;FooResource&lt;/span&gt; &lt;span class="nf"&gt;getFoo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// (3)&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// pojos&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// (3)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="nd"&gt;@JsonProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"nested"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BarResource&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BarResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// (4)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;a schema name without suffix&lt;/li&gt;
&lt;li&gt;the suffix configuration&lt;/li&gt;
&lt;li&gt;the class name of the Foo schema got the configured Resource suffix&lt;/li&gt;
&lt;li&gt;the class name of the &lt;code&gt;BarResource&lt;/code&gt; is identical to the original schema name. Since the existing suffix is equal to &lt;code&gt;model-name-suffix&lt;/code&gt; it is ignored. Otherwise, This prevents funny class names like &lt;code&gt;BarResourceResource&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>java</category>
      <category>springboot</category>
      <category>micronaut</category>
    </item>
    <item>
      <title>openapi-processor-spring type mapping</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Fri, 14 Aug 2020 08:45:24 +0000</pubDate>
      <link>https://dev.to/hauner/openapi-processor-spring-type-mapping-4ecj</link>
      <guid>https://dev.to/hauner/openapi-processor-spring-type-mapping-4ecj</guid>
      <description>&lt;h1&gt;
  
  
  what is openapi-processor?
&lt;/h1&gt;

&lt;p&gt;openapi-processor is a small framework to process OpenAPI yaml files. Currently, openapi-processor provides java code generation for Spring Boot and conversion to json.&lt;/p&gt;

&lt;p&gt;It does support gradle and maven to run any openapi-processor as part of the build process.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://docs.openapiprocessor.io"&gt;documentation&lt;/a&gt; for more. There is also a &lt;a href="https://playground.openapiprocessor.io"&gt;playground&lt;/a&gt; to preview the processors.&lt;/p&gt;

&lt;h1&gt;
  
  
  openapi-processor-spring
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.openapiprocessor.io/spring"&gt;openapi-processor-spring&lt;/a&gt; (oap-spring) generates server side Java code for Spring Boot from an OpenAPI description. It generates interfaces for the endpoints with all the required Spring annotations, and it generates model classes (simple POJOs) with Jackson annotations for the OpenAPI schemas used in those endpoints.&lt;/p&gt;

&lt;p&gt;By creating a controller that &lt;code&gt;implements&lt;/code&gt; a generated interface it gets easier to implement the expected endpoints. Spring will automatically pick up all annotations on the generated interface methods. You can concentrate on the implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  what is type mapping?
&lt;/h2&gt;

&lt;p&gt;Code generation is tricky. It is impossible to generate the perfect code just from the OpenAPI description. There are many cases where the generator needs our help to generate the code we like.&lt;/p&gt;

&lt;p&gt;Just think of collections. OpenAPI has a single schema abstraction to describe collections: the &lt;code&gt;*array*&lt;/code&gt;. It does not need more.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;array&lt;/code&gt; (e.g. &lt;code&gt;String[]&lt;/code&gt;) in Java is possible (and that is what oap-spring is using by default) but usually we prefer a more powerful and easier to use collection like &lt;code&gt;List&lt;/code&gt; or &lt;code&gt;Set&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;That is why we need &lt;em&gt;type mapping&lt;/em&gt;. &lt;em&gt;Type mapping&lt;/em&gt; allows us to map an OpenAPI schema to a specific Java class.&lt;/p&gt;

&lt;p&gt;The generator does use the mapping to replace &lt;em&gt;any&lt;/em&gt; occurrence of the given OpenAPI schema in the generated code with the mapped target Java type. It doesn't matter if it is a parameter, response or a property of an object schema.&lt;/p&gt;

&lt;p&gt;If an OpenAPI model schema (which would normally generate a POJO class) gets mapped to an existing Java class oap-spring will not generate a (duplicate) POJO class.&lt;/p&gt;

&lt;h2&gt;
  
  
  where to specify type mappings?
&lt;/h2&gt;

&lt;p&gt;Type mapping is part of the openapi-processor yaml configuration file &lt;code&gt;mapping.yaml&lt;/code&gt;. It should be a sibling of the OpenAPI yaml files (i.e. in the same directory).&lt;/p&gt;

&lt;p&gt;The file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi-processor-mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;io.openapiprocessor.mapping&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;2&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="c1"&gt;# java type mappings # &amp;lt;3&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; sets the configuration file format. It must be present with version 2 to use the mapping format described below.&lt;/p&gt;

&lt;p&gt;&amp;lt;2&amp;gt; sets the Java package for the generated source files.&lt;/p&gt;

&lt;p&gt;&amp;lt;3&amp;gt; &lt;code&gt;map&lt;/code&gt; is the parent key of all type mappings.&lt;/p&gt;

&lt;h2&gt;
  
  
  how to specify a type mapping?
&lt;/h2&gt;

&lt;p&gt;Type mapping uses a simple notation to specify a mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;
  &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;source type&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="s"&gt;=&amp;gt; {target type}&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; this defines the mapping collection. All mappings are grouped into a couple of fixed collections: &lt;code&gt;types&lt;/code&gt;, &lt;code&gt;parameters&lt;/code&gt;, &lt;code&gt;responses&lt;/code&gt; and &lt;code&gt;paths&lt;/code&gt;. A mapping collection can have any number of mappings.&lt;/p&gt;

&lt;p&gt;&amp;lt;2&amp;gt; &lt;code&gt;key&lt;/code&gt; defines what kind of mapping gets defined. For example &lt;code&gt;type&lt;/code&gt; is the key for a global type mapping in the &lt;code&gt;types&lt;/code&gt; collection. The value of the key maps a source type to a destination type by using an &lt;code&gt;\=&amp;gt;&lt;/code&gt; arrow as the &lt;em&gt;mapping operator&lt;/em&gt;. &lt;code&gt;{source type}&lt;/code&gt; is the name of an OpenAPI type and &lt;code&gt;{target type}&lt;/code&gt; is the fully qualified Java class name. Fully qualified because the processor needs the package name to generate an import statement for the target type.&lt;/p&gt;

&lt;p&gt;Let's take a look at a few mapping examples. This is just an introduction and doesn't describe all the possibilities. See the &lt;a href="https://docs.openapiprocessor.io/spring/mapping"&gt;type mapping&lt;/a&gt; documentation for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  type mapping examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  global mapping
&lt;/h3&gt;

&lt;p&gt;The first mapping is the &lt;em&gt;global&lt;/em&gt; type mapping. Remembering the array example from above we can change it globally to &lt;code&gt;java.util.Collection&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;1&amp;gt;&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;array =&amp;gt; java.util.Collection&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;2&amp;gt;&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Foo =&amp;gt; io.openapiprocessor.samples.Foo&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;3&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;1&amp;gt; &lt;code&gt;types&lt;/code&gt; is the list of global type mappings. It is global because it is a direct child of the &lt;code&gt;map&lt;/code&gt; key.&lt;br&gt;
&amp;lt;2&amp;gt; &lt;code&gt;- type&lt;/code&gt; is an actual mapping item, and it says: map the OpenAPI &lt;code&gt;array&lt;/code&gt; schema type to Java's &lt;code&gt;java.util.Collection&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Important:&lt;br&gt;
the processor assumes that the Java target of &lt;code&gt;array&lt;/code&gt; has a single generic parameter, and it will automatically use the &lt;code&gt;array&lt;/code&gt;'s &lt;code&gt;item&lt;/code&gt; property type as the generic parameter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;lt;3&amp;gt; this one maps an OpenAPI schema &lt;code&gt;Foo&lt;/code&gt; to an existing Java class in our code base.&lt;/p&gt;

&lt;h3&gt;
  
  
  path mapping
&lt;/h3&gt;

&lt;p&gt;The second mapping is &lt;em&gt;path-based&lt;/em&gt; type mapping and it is quite useful. It allows us to limit a mapping rule to a single endpoint. It is not used for any other endpoint.&lt;/p&gt;

&lt;p&gt;Continue reading &lt;a href="https://hauner.github.io/blog/2020/openapi-processor-mapping"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://hauner.github.io/blog/2020/openapi-processor-mapping"&gt;https://hauner.github.io&lt;/a&gt; on August 14, 2020.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>java</category>
      <category>springboot</category>
    </item>
    <item>
      <title>configuring openapi-processor-maven</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Mon, 27 Jul 2020 20:41:03 +0000</pubDate>
      <link>https://dev.to/hauner/configuring-openapi-processor-maven-39pf</link>
      <guid>https://dev.to/hauner/configuring-openapi-processor-maven-39pf</guid>
      <description>&lt;h1&gt;
  
  
  what is openapi-processor?
&lt;/h1&gt;

&lt;p&gt;openapi-processor is a small framework to process OpenAPI yaml files. Currently, openapi-processor provides java code generation for Spring Boot and conversion to json.&lt;/p&gt;

&lt;p&gt;It does support gradle and maven to run any openapi-processor as part of the build process.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://docs.openapiprocessor.io"&gt;documentation&lt;/a&gt; for more. There is also a &lt;a href="https://playground.openapiprocessor.io"&gt;playground&lt;/a&gt; to preview the processors.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;maven plugin&lt;/strong&gt; is the newest member of the openapi-processor family, and the following sections provide a short introduction into its configuration.&lt;/p&gt;

&lt;h1&gt;
  
  
  introduction
&lt;/h1&gt;

&lt;p&gt;I will just show the configuration of the maven plugin for integrating an OpenAPI yaml file. I don't describe the creation of a Spring Boot application.&lt;/p&gt;

&lt;p&gt;Integrating it in a new Spring Boot starter project created by &lt;a href="https://start.spring.io/"&gt;Spring Initializr&lt;/a&gt; (maven &amp;amp; web-mvc) should work without issues.&lt;/p&gt;

&lt;p&gt;To see a working demo project take a look at the &lt;a href="https://docs.openapiprocessor.io/samples"&gt;openapi-processor samples&lt;/a&gt;. The available samples have a &lt;code&gt;pom.xml&lt;/code&gt;, and a &lt;code&gt;build.gradle&lt;/code&gt; file, so you can build them using maven or gradle.&lt;/p&gt;

&lt;h2&gt;
  
  
  what to expect
&lt;/h2&gt;

&lt;p&gt;Assuming a (simple) OpenAPI yaml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.2&lt;/span&gt;
    &lt;span class="s"&gt;info&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ping api&lt;/span&gt;
      &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;

    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;/ping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ping&lt;/span&gt;
          &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;returns a single "pong" string.&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;super simple endpoint.&lt;/span&gt;
          &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pong&lt;/span&gt;
              &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;text/plain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the &lt;a href="https://docs.openapiprocessor.io/maven"&gt;openapi-processor-maven plugin&lt;/a&gt; will generate a java interface by running the &lt;a href="https://docs.openapiprocessor.io/spring"&gt;openapi-processor-spring&lt;/a&gt; (in short oap-spring).&lt;/p&gt;

&lt;p&gt;The interface generated for the simple api will look like this (the package name &lt;code&gt;io.openapiprocessor.simple&lt;/code&gt; is configurable):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.simple.api&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PingApi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/ping"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;produces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getPing&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now implement the interface to provide a working endpoint in your Spring Boot application.&lt;/p&gt;

&lt;p&gt;The sample implements the interface with a hardcoded result like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.openapiprocessor.simple&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;  &lt;span class="nn"&gt;io.openapiprocessor.simple.api.PingApi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Controller&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PingController&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PingApi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getPing&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"pong"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's look at the necessary configuration to generate the interface from maven.&lt;/p&gt;

&lt;p&gt;Continue reading &lt;a href="https://hauner.github.io/blog/2020/openapi-processor-maven"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://hauner.github.io/blog/2020/openapi-processor-maven"&gt;https://hauner.github.io&lt;/a&gt; on July 18, 2020.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>maven</category>
      <category>springboot</category>
      <category>java</category>
    </item>
    <item>
      <title>fixing a (transitive) dependency mess with gradle</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Tue, 09 Jun 2020 09:02:18 +0000</pubDate>
      <link>https://dev.to/hauner/fixing-a-transitive-dependency-mess-with-gradle-1g5</link>
      <guid>https://dev.to/hauner/fixing-a-transitive-dependency-mess-with-gradle-1g5</guid>
      <description>&lt;h1&gt;
  
  
  the transitive dependency mess
&lt;/h1&gt;

&lt;p&gt;While extracting openapi-processor-core from &lt;a href="https://hauner.github.io/openapi-processor/spring/index.html"&gt;&lt;em&gt;openapi-processor-spring&lt;/em&gt;&lt;/a&gt; I noticed duplicate dependencies with different and sometimes unexpected versions in the external libraries section o the project view (in IDEA).&lt;/p&gt;

&lt;p&gt;In this case jackson packages.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;gradle dependencies&lt;/code&gt; to see where they are coming from prints the following output (look for &lt;code&gt;jackson&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gradle dependencies (simplified)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--- com.fasterxml.jackson.module:jackson-module-kotlin:2.11.0
|    +--- com.fasterxml.jackson.core:jackson-databind:2.11.0 &amp;lt;1&amp;gt;
|    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.11.0
|    |    \--- com.fasterxml.jackson.core:jackson-core:2.11.0
|    \--- com.fasterxml.jackson.core:jackson-annotations:2.11.0
+--- org.openapi4j:openapi-parser:1.0
|    \--- org.openapi4j:openapi-core:1.0
|         +--- com.fasterxml.jackson.core:jackson-databind:2.9.10 -&amp;gt; 2.11.0 (*) &amp;lt;2&amp;gt;
|         \--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.10 -&amp;gt; 2.10.2 &amp;lt;3&amp;gt;
|              \--- com.fasterxml.jackson.core:jackson-core:2.10.2 -&amp;gt; 2.11.0 &amp;lt;4&amp;gt;
+--- io.swagger.parser.v3:swagger-parser:2.0.20
     +--- io.swagger.parser.v3:swagger-parser-v3:2.0.20
          +--- io.swagger.core.v3:swagger-models:2.1.2
          |    \--- com.fasterxml.jackson.core:jackson-annotations:2.10.1 -&amp;gt; 2.11.0 &amp;lt;5&amp;gt;
          +--- io.swagger.core.v3:swagger-core:2.1.2
          |    +--- com.fasterxml.jackson.core:jackson-annotations:2.10.1 -&amp;gt; 2.11.0
          |    +--- com.fasterxml.jackson.core:jackson-databind:2.10.1 -&amp;gt; 2.11.0 (*)
          |    +--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.1 -&amp;gt; 2.10.2 (*) &amp;lt;6&amp;gt;
          |    +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1 &amp;lt;7&amp;gt;
          |         +--- com.fasterxml.jackson.core:jackson-annotations:2.10.1 -&amp;gt; 2.11.0
          |         +--- com.fasterxml.jackson.core:jackson-core:2.10.1 -&amp;gt; 2.11.0
          |         \--- com.fasterxml.jackson.core:jackson-databind:2.10.1 -&amp;gt; 2.11.0 (*)
          +--- com.fasterxml.jackson.core:jackson-annotations:2.10.2 -&amp;gt; 2.11.0
          +--- com.fasterxml.jackson.core:jackson-databind:2.10.2 -&amp;gt; 2.11.0 (*)
          \--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.2 (*) &amp;lt;8&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a bit of a mess regarding the jackson packages and their versions. Here are a couple of entries:&lt;/p&gt;

&lt;p&gt;&amp;lt;1&amp;gt; some with version 2.11.0&lt;br&gt;
&amp;lt;2&amp;gt; upgrade from 2.9.10 to 2.11.0&lt;br&gt;
&amp;lt;3&amp;gt; upgrade from 2.9.10 to 2.10.2&lt;br&gt;
&amp;lt;4&amp;gt; upgrade from 2.10.2 to 2.11.0&lt;br&gt;
&amp;lt;5&amp;gt; upgrade from 2.10.1 to 2.11.0&lt;br&gt;
&amp;lt;6&amp;gt; upgrade from 2.10.1 to 2.10.2&lt;br&gt;
&amp;lt;7&amp;gt; version 2.10.1&lt;br&gt;
&amp;lt;8&amp;gt; version 2.10.2&lt;/p&gt;

&lt;p&gt;The 3 top-level dependencies are direct dependencies (as gradle calls them) of my project and all of them use different jackson versions:&lt;/p&gt;

&lt;p&gt;. &lt;code&gt;com.fasterxml.jackson.module:jackson-module-kotlin:2.11.0&lt;/code&gt;&lt;br&gt;
. &lt;code&gt;org.openapi4j:openapi-parser:1.0&lt;/code&gt;&lt;br&gt;
. &lt;code&gt;io.swagger.parser.v3:swagger-parser:2.0.20&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The first one is simple. Because &lt;code&gt;com.fasterxml.jackson.module:jackson-module-kotlin&lt;/code&gt; is a jackson package itself, gradle selects &lt;strong&gt;2.11.0&lt;/strong&gt; for the other transitive jackson dependencies.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;jackson-module-kotlin (simplified)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    +--- com.fasterxml.jackson.module:jackson-module-kotlin:2.11.0
         +--- com.fasterxml.jackson.core:jackson-annotations:2.11.0
         +--- com.fasterxml.jackson.core:jackson-core:2.11.0
         \--- com.fasterxml.jackson.core:jackson-databind:2.11.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next one is &lt;code&gt;org.openapi4j:openapi-parser:1.0&lt;/code&gt;. This one depends on jackson &lt;strong&gt;2.9.10&lt;/strong&gt; and gradle upgrades everything to &lt;strong&gt;2.11.0&lt;/strong&gt; because that is the newest version it found.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;openapi-parser (simplified)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--- org.openapi4j:openapi-parser:1.0
     +--- com.fasterxml.jackson.core:jackson-core:2.10.2 -&amp;gt; 2.11.0
     +--- com.fasterxml.jackson.core:jackson-databind:2.9.10 -&amp;gt; 2.11.0 (*)
     \--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.10 -&amp;gt; 2.10.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, not for all jackson packages. It doesn't use &lt;strong&gt;2.11.0&lt;/strong&gt; for &lt;code&gt;jackson-dataformat-yaml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is not using &lt;strong&gt;2.11.0&lt;/strong&gt; because gradle has not seen a newer version of &lt;code&gt;jackson-dataformat-yaml&lt;/code&gt;than &lt;strong&gt;2.9.10&lt;/strong&gt;. So why is it not &lt;strong&gt;2.9.10&lt;/strong&gt;? It is not because the third direct dependency &lt;code&gt;io.swagger.parser.v3:swagger-parser:2.0.20&lt;/code&gt; is using &lt;strong&gt;2.10.1&lt;/strong&gt; and &lt;strong&gt;2.10.2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;swagger-parser (simplified)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--- io.swagger.parser.v3:swagger-parser:2.0.20
     +--- com.fasterxml.jackson.core:jackson-annotations:2.10.1 -&amp;gt; 2.11.0
     +--- com.fasterxml.jackson.core:jackson-core:2.10.1 -&amp;gt; 2.11.0
     +--- com.fasterxml.jackson.core:jackson-databind:2.10.1 -&amp;gt; 2.11.0
     +--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.1 -&amp;gt; 2.10.2
     \--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2.10.2&lt;/strong&gt; for &lt;code&gt;jackson-dataformat-yaml&lt;/code&gt;. This is the highest version for this package so gradle picks it.&lt;/p&gt;

&lt;p&gt;Gradle finally selects the following versions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;package (stripped com.fasterxml.jackson.)&lt;/th&gt;
&lt;th&gt;version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;core:jackson-annotations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;core:jackson-core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;core:jackson-databind&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dataformat:jackson-dataformat-yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.10.2   =&amp;gt; want 2.11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;datatype:jackson-datatype-jsr310&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.10.1 =&amp;gt; want 2.11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gradle uses the highest version it does find for each package. It doesn't know that the jackson packages belong together and that all of them should use the same version.&lt;/p&gt;

&lt;p&gt;There are two possible solutions to make all jackson packages use the expected version.&lt;/p&gt;

&lt;h2&gt;
  
  
  solution
&lt;/h2&gt;

&lt;p&gt;According to the gradle documentation the preferred solution is to add a &lt;code&gt;constraints&lt;/code&gt; block to the &lt;code&gt;dependencies&lt;/code&gt;. Adding a direct dependency is not the correct solution:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.gradle.org/current/userguide/dependency_constraints.html"&gt;gradle-constraints&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Often developers incorrectly fix transitive dependency issues by adding direct dependencies. To avoid this, Gradle provides the concept of dependency constraints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Modifying the dependency resolution rules is not an option either:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.gradle.org/current/userguide/resolution_rules.html#sec:dependency_resolve_rules"&gt;gradle dependency resolve rules&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are authoring a library, you should always prefer dependency constraints as they are published for your consumers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  constraints
&lt;/h3&gt;

&lt;p&gt;The project is a library and the constraints solution look like this in the &lt;code&gt;build.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;jacksonVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2.11.0'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// .. dependencies ..&lt;/span&gt;

    &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;because&lt;/span&gt; &lt;span class="s1"&gt;'use the same version for all jackson packages'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonVersion"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;because&lt;/span&gt; &lt;span class="s1"&gt;'use the same version for all jackson packages'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, this fixes the issue. :-)&lt;/p&gt;

&lt;p&gt;Too bad each single package requires its own constraint (the closure with &lt;code&gt;because&lt;/code&gt; ist not required). It would be nice to use wildcards to match all jackson packages with a single constraint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;jacksonVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2.11.0'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// .. dependencies ..&lt;/span&gt;

    &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// does NOT work&lt;/span&gt;
        &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"com.fasterxml.jackson.*:*:$jacksonVersion"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;because&lt;/span&gt; &lt;span class="s1"&gt;'use the same version for all jackson packages'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That would be a bit simpler but unfortunately it does not work.&lt;/p&gt;

&lt;h3&gt;
  
  
  platform
&lt;/h3&gt;

&lt;p&gt;I found another solution in the gradle documentation that even uses jackson as an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.gradle.org/current/userguide/dependency_version_alignment.html"&gt;gradle dependency version alignment&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First step is to create a metadata rule that joins all jackson packages into a &lt;em&gt;platform&lt;/em&gt;. Jackson has a platform bom that lists all packages belonging to a platform version, and it is used to create the platform rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JacksonPlatformRule&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;ComponentMetadataRule&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ComponentMetadataContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;with&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"com.fasterxml.jackson"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;belongsTo&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"com.fasterxml.jackson:jackson-bom:${id.version}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I simply added the class at the end of the &lt;code&gt;build.gradle&lt;/code&gt; for testing, but it will probably move to gradles &lt;code&gt;buildSrc&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Second step is to activate the rule in the &lt;code&gt;dependencies&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JacksonPlatformRule&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// .. dependencies ..&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By grouping the packages gradle now selects the jackson &lt;strong&gt;platform&lt;/strong&gt; with the highest version and uses the versions listed in the bom for any jackson package.&lt;/p&gt;

&lt;p&gt;This is also visible in the output of &lt;code&gt;gradle dependencies&lt;/code&gt; (starting at line 4). Gradle selects the &lt;strong&gt;2.11.0&lt;/strong&gt; platform module and upgrades all jackson packages to the platform version:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gradle dependencies (simplified)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--- com.fasterxml.jackson.module:jackson-module-kotlin:2.11.0
|    +--- com.fasterxml.jackson.core:jackson-databind:2.11.0
|    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.11.0
|    |    |    \--- com.fasterxml.jackson:jackson-bom:2.11.0
|    |    |         +--- com.fasterxml.jackson:jackson-bom:2.11.0 (*)
|    |    |         +--- com.fasterxml.jackson.core:jackson-annotations:2.11.0 (c)
|    |    |         +--- com.fasterxml.jackson.core:jackson-core:2.11.0 (c)
|    |    |         +--- com.fasterxml.jackson.core:jackson-databind:2.11.0 (c)
|    |    |         +--- com.fasterxml.jackson.module:jackson-module-kotlin:2.11.0 (c)
|    |    |         +--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11.0 (c)
|    |    |         \--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.0 (c)
|    |    +--- com.fasterxml.jackson.core:jackson-core:2.11.0
|    |    |    \--- com.fasterxml.jackson:jackson-bom:2.11.0 (*)
|    |    \--- com.fasterxml.jackson:jackson-bom:2.11.0 (*)
|    +--- com.fasterxml.jackson.core:jackson-annotations:2.11.0 (*)
|    \--- com.fasterxml.jackson:jackson-bom:2.11.0 (*)
+--- org.openapi4j:openapi-parser:1.0
|    \--- org.openapi4j:openapi-core:1.0
|         +--- com.fasterxml.jackson.core:jackson-databind:2.9.10 -&amp;gt; 2.11.0 (*)
|         \--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.10 -&amp;gt; 2.11.0
|              +--- com.fasterxml.jackson.core:jackson-databind:2.11.0 (*)
|              +--- org.yaml:snakeyaml:1.26
|              +--- com.fasterxml.jackson.core:jackson-core:2.11.0 (*)
|              \--- com.fasterxml.jackson:jackson-bom:2.11.0 (*)
+--- io.swagger.parser.v3:swagger-parser:2.0.20
     +--- io.swagger.parser.v3:swagger-parser-v3:2.0.20
          +--- io.swagger.core.v3:swagger-models:2.1.2
          |    \--- com.fasterxml.jackson.core:jackson-annotations:2.10.1 -&amp;gt; 2.11.0 (*)
          +--- io.swagger.core.v3:swagger-core:2.1.2
          |    +--- com.fasterxml.jackson.core:jackson-annotations:2.10.1 -&amp;gt; 2.11.0 (*)
          |    +--- com.fasterxml.jackson.core:jackson-databind:2.10.1 -&amp;gt; 2.11.0 (*)
          |    +--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.1 -&amp;gt; 2.11.0 (*)
          |    \--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1 -&amp;gt; 2.11.0
          |         +--- com.fasterxml.jackson.core:jackson-annotations:2.11.0 (*)
          |         +--- com.fasterxml.jackson.core:jackson-core:2.11.0 (*)
          |         +--- com.fasterxml.jackson.core:jackson-databind:2.11.0 (*)
          |         \--- com.fasterxml.jackson:jackson-bom:2.11.0 (*)
          +--- com.fasterxml.jackson.core:jackson-annotations:2.10.2 -&amp;gt; 2.11.0 (*)
          +--- com.fasterxml.jackson.core:jackson-databind:2.10.2 -&amp;gt; 2.11.0 (*)
          \--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.2 -&amp;gt; 2.11.0 (*)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;constraints&lt;/code&gt; solution is easy to use on single dependencies. The platform rule is the way to go for groups of packages like jackson.&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

</description>
      <category>gradle</category>
      <category>java</category>
    </item>
    <item>
      <title>openapi-processor-spring</title>
      <dc:creator>Martin Hauner</dc:creator>
      <pubDate>Mon, 25 May 2020 17:02:02 +0000</pubDate>
      <link>https://dev.to/hauner/openapi-processor-spring-368k</link>
      <guid>https://dev.to/hauner/openapi-processor-spring-368k</guid>
      <description>&lt;p&gt;&lt;a href="https://openapiprocessor.io/openapi-processor/spring/index.html"&gt;&lt;em&gt;openapi-processor-spring&lt;/em&gt;&lt;/a&gt; (or short: &lt;em&gt;oap-spring&lt;/em&gt;) is an &lt;a href="https://www.openapis.org/"&gt;OpenAPI&lt;/a&gt; interface &amp;amp; model Java code generator for &lt;a href="https://spring.io/projects/spring-boot"&gt;Spring Boot&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It is generating code for annotation based (MVC) controllers (oap-spring has experimental support for &lt;code&gt;Mono&amp;lt;&amp;gt;&lt;/code&gt; and &lt;code&gt;Flux&amp;lt;&amp;gt;&lt;/code&gt; like wrappers that makes it possible to use WebFlux with annotations).&lt;/p&gt;

&lt;p&gt;Its goal is to provide a smooth &amp;amp; straight forward mapping from an OpenAPI yaml description to Spring Boot Java code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;allowing common Spring Boot code patterns, like passing additional parameters (for example &lt;code&gt;HttpServletRequest&lt;/code&gt; or &lt;code&gt;HandlerMethodArgumentResolver&lt;/code&gt;) to controller endpoints without adding it to the OpenAPI description&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;providing an easy mapping to existing Java types with (simple) generic support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;getting out of the way if the processor does not create the expected code for single endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will need a gradle based spring boot project and the &lt;a href="https://openapiprocessor.io/openapi-processor/gradle"&gt;oap-gradle plugin&lt;/a&gt; to use oap-spring.&lt;/p&gt;

&lt;p&gt;See the quick overview below for how it works or check the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://openapiprocessoror.io/openapi-processor"&gt;Learn more about openapi-processor-spring&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openapi-processor-playground.appspot.com"&gt;Try the openapi-processor playground&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Current 1.0 milestone releases are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;com.github.hauner.openapi:openapi-processor-spring:1.0.0.M14&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;com.github.hauner.openapi:openapi-processor-gradle:1.0.0.M7&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  usage overview
&lt;/h2&gt;

&lt;p&gt;Here is a quick usage overview. A more detailed description is available in the &lt;a href="https://docs.openapiprocessor.io/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  api &amp;amp; processor configuration
&lt;/h3&gt;

&lt;p&gt;First, we put an &lt;code&gt;openapi.yaml&lt;/code&gt; with our OpenAPI description in the &lt;code&gt;src/api&lt;/code&gt; folder of our project. We put another yaml file &lt;code&gt;mapping.yaml&lt;/code&gt; into the same place. This is the configuration of the processor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src/api/
   openapi.yaml
   mapping.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the minimum content of the &lt;code&gt;mapping.yaml&lt;/code&gt; is the target package name for the code the processor generates. It will create two sub-packages &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;model&lt;/code&gt; for the endpoint interfaces and the model classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.github.hauner.openapi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  gradle configuration
&lt;/h3&gt;

&lt;p&gt;To enable the processor we add the following snippets to the &lt;code&gt;build.gradle&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add the oap-gradle plugin
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s1"&gt;'com.github.hauner.openapi-processor'&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s1"&gt;'1.0.0.M7'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;next is the plugin configuration for oap-spring. &lt;code&gt;apiPath&lt;/code&gt;, &lt;code&gt;mapping&lt;/code&gt; &amp;amp; &lt;code&gt;targetDir&lt;/code&gt; configure the paths of the input files, and the processor configuration file. &lt;code&gt;processor&lt;/code&gt; is like a dependency in the standard gradle &lt;code&gt;dependencies&lt;/code&gt; block and tells the plugin which processor to
use. The plugin will create a &lt;code&gt;processSpring&lt;/code&gt; task to run the given &lt;code&gt;processor&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;openapiProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;apiPath&lt;/span&gt; &lt;span class="s2"&gt;"${projectDir}/src/api/openapi.yaml"&lt;/span&gt;

    &lt;span class="n"&gt;spring&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;processor&lt;/span&gt; &lt;span class="s1"&gt;'com.github.hauner.openapi:openapi-processor-spring:1.0.0.M14'&lt;/span&gt;
        &lt;span class="n"&gt;mapping&lt;/span&gt; &lt;span class="s2"&gt;"${projectDir}/src/api/mapping.yaml"&lt;/span&gt;
        &lt;span class="n"&gt;targetDir&lt;/span&gt; &lt;span class="s2"&gt;"${projectDir}/build/openapi"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;last step is to include the generated files into the build. With standard gradle configurations we add the &lt;code&gt;targetDir&lt;/code&gt; to the &lt;code&gt;java&lt;/code&gt; source set so that gradle will compile them. To automatically re-generate the api when necessary we add the &lt;code&gt;processSpring&lt;/code&gt; task as a dependency to the &lt;code&gt;compileJava&lt;/code&gt; task.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;sourceSets&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;srcDir&lt;/span&gt; &lt;span class="s2"&gt;"${projectDir}/build/openapi"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;compileJava&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dependsOn&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'processSpring'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we change &lt;code&gt;openapi.yaml&lt;/code&gt; or &lt;code&gt;mapping.yaml&lt;/code&gt; gradle automatically runs the processor to update the api code before it is compiling the rest of our code.&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZJbOYIZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.openapiprocessor.io/assets/openapi-processor-spring%40400x200.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZJbOYIZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://docs.openapiprocessor.io/assets/openapi-processor-spring%40400x200.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>springboot</category>
      <category>java</category>
    </item>
  </channel>
</rss>
