package-names from location
The package-names from location feature allows the processor to create package names based on the file location of $ref’erenced parts of the OpenAPI description.
This gets enabled by setting the package-names:location
option.
package-names:location
package-names:location
is the parent package for location based package names.
Only (OpenAPI) file locations below the parent package will be generated with a location based package name. Any other (OpenAPI) file location will use package-names.base
(or package-name
) as the package name.
Enabling this has a few conditions:
-
to create an interface or resource in a specific package, its OpenAPI description has to be in the target package and must be reachable from the root OpenAPI description.
-
it only works with the
INTERNAL
OpenAPI parser (it is the default parser). It will not work with theSWAGGER
OpenAPI parser.
mapping.yaml
The first step is to enable the feature in the mapping.yaml
:
openapi-processor-mapping: v13
options:
# this must be a parent package of the target packages
#package-name: io.openapiprocessor.openapi (1)
package-names:
base: io.openapiprocessor.openapi (2)
# this enables package generation from the endpoint $ref file location
location: io.openapiprocessor.samples (3)
1 | the shortcut for setting package-names.base . If location based packages should be used, setting package-names.base is preferred. |
2 | this is the base package for all generated code. This is identical to the current behaviour (i.e. package-name ). Any file the is not below package-names.location will be generated with this as the base package. |
3 | package-name.location is the parent package name of the project’s target packages. If the processor finds a file ref’erenced from the main OpenAPI in a subpackage of package-name.location the generated sources will be generated with that package. |
OpenAPI and $refs
The second step is to split the OpenAPI definition into multiple files and place them into the desired packages.
The openapi.yaml
is placed into the usual place, in this example in the source folder src/api
.
openapi: 3.1.0
info:
title: openapi-processor-spring sample api
version: 1.0.0
servers:
- url: "https://openapiprocessor.io/{path}"
variables:
path:
default: api
paths:
/foo:
$ref: '../main/kotlin/io/openapiprocessor/samples/foo/foo.yaml' (1)
The project directories so far look like this, where sample
is the root folder of the project.
sample \---- src \---- api +---- mapping.yaml \---- openapi.yaml
foo endpoint $ref
The foo
path item in openapi.yaml
$ref’erences the endpoint definition in foo.yaml
.
post:
tags:
- foo
summary: echo a Foo.
description: simple sample endpoint
requestBody:
$ref: 'resources.yaml#/FooBody'
responses:
'200':
description: foo
content:
application/json:
schema:
$ref: 'resources.yaml#/Foo'
foo.yaml
is placed into the main source folder of the project into the target package the generated interface should have.
In this case the target package of FooApi.java
will be io.openapiprocessor.samples.foo
The controller implementation and services for this endpoint will go into the same package.
foo.yaml
also $ref’erences a resources.yaml
file placed in the same package that defines the Foo
payload schema:
FooBody:
content:
application/json:
schema:
$ref: '#/Foo'
Foo:
type: object
description: Foo object description
properties:
foo:
type: string
maxLength: 10
description: foo property description
id:
type: string
format: uuid
description: id property description
The final directory structure then looks like this:
sample \---- src +---- api | +---- mapping.yaml | \---- openapi.yaml \---- main +---- kotlin | \---- io | \---- openapiprocessor | \---- samples | +---- foo | | +---- FooController.kt | | +---- foo.yaml | | \---- resources.yaml | +---- bar | | \---- ... | \ Application.kt \---- resources \---- application.properties
parent package name
Having an idea now how the files are organized, it is possible to explain which package is the parent package.
From the file tree above:
The package name of the foo
endpoint files is io.openapiprocessor.samples.foo
and the nearest parent package is io.openapiprocessor.samples
. This is then the package-names.location
option value.
It is possible to use io.openapiprocessor
or even io
as the parent package.
directory structure after processing
Assuming a Gradle build, the directory structure after processing is:
sample +---- build | \---- openapi | +--- java | | \---- io | | \---- openapiprocessor | | \---- samples | | +---- foo | | | +---- Foo.java | | | \---- FooApi.java | | \---- bar | | \---- ... | \---- resources | \---- api.properties \---- src +---- api | +---- mapping.yaml | \---- openapi.yaml \---- main +---- kotlin | +---- io | | \---- openapiprocessor | | \---- samples | | +---- foo | | | +---- FooController.kt | | | +---- foo.yaml | | | \---- resources.yaml | | \---- bar | | \---- ... \---- resources \---- application.properties
sample code
A full working example with multiple endpoints is available in the samples repository.