How to generate common classes to a separate package and then reuse them
I can define common classes in a separate schema file:
common.json { ... "components": { "schemas": { "FinancialContext": { ... } } }
and then reuse it in many other schemas: "financialContext": "$ref": "common.json#/components/schemas/FinancialContext" }
but when I generate models using swagger-codegen-maven-plugin this class will be duplicated in each package for each schema (I cannot generate all the classes to the same package because they can have other classes with the same name, but different content).
I want to be able to generate common.json to a separate package (this is actually possible now) and then all other executions of the plugin should import already generated classes from the common package instead of generating copies of the class in the apis packages.
Have you found a solution ?
@eakonovalov Hi, have you found a solution for this ? We are facing a similar issue but I didn't find a way to resolve it yet.
JFYI I have found the way how to do this, so in case anybody will search for solution in future this could help. The idea here is the combination of needed actions:
- Use OpenAPI Spec 3 $ref with Remote reference for all your common classes in multiple specification
# Folder structure
|── src
│ |── main
│ │ |── resources
│ | | |── bounded-context1-spec.yaml
| | | |── bounded-context2-spec.yaml
| | | |── common-classes.yaml
# bounded-context1-spec.yaml
openapi: 3.0.3
info:
title: OpenAPI 3 spec example for bounded context 1
version: 1.0.0
paths:
/test:
get:
tags:
- test
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: "common-classes.yaml#/components/schemas/Test"
# bounded-context2-spec.yaml
openapi: 3.0.3
info:
title: OpenAPI 3 spec example for bounded context 2
version: 1.0.0
paths:
/test2:
get:
tags:
- test2
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: "common-classes.yaml#/components/schemas/Test"
# common-classes.yaml
openapi: 3.0.3
info:
title: Common Classes which are used by both bounded contexts
version: 1.0.0
paths: {}
components:
schemas:
Test:
type: object
properties:
message:
type: string
- Additional execution step for swagger-codegen-plugin which is configured to generate only Models. (classes will be generated to com.test.common.model package)
# pom.xml
...
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<goals>
<goal>generate-common-classes</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/common-classes.yaml</inputSpec>
<modelPackage>com.test.common.model</modelPackage>
<language>spring</language>
<generateApis>false</generateApis>
</configuration>
</execution>
<!-- Main execution steps for Bounded Contexts OpenAPI specs -->
</executions>
</plugin>
...
- Add importMappings for common models into your main execution steps. This configuration will disable generation of common classes for specific bounded context and reuse classes generated in above step.
# pom.xml
...
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<goals>
<goal>generate-common-classes</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/common-classes.yaml</inputSpec>
<modelPackage>com.test.common.model</modelPackage>
<language>spring</language>
<generateApis>false</generateApis>
</configuration>
</execution>
<!-- Main execution steps for Bounded Contexts OpenAPI specs -->
<execution>
<goals>
<goal>generate-bounded-context-1</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/bounded-context1-spec.yaml</inputSpec>
<<apiPackage>com.test.bounded-context2</apiPackage>
<modelPackage>com.test.bounded-context2.model</modelPackage>
<language>spring</language>
<additionalProperties>
<additionalProperty>ignoreImportMappings=false</additionalProperty>
</additionalProperties>
<importMappings>
<importMapping>Test=com.test.common.model.Test</importMapping>
</importMappings>
</configuration>
</execution>
<execution>
<goals>
<goal>generate-bounded-context-2</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/bounded-context2-spec.yaml</inputSpec>
<apiPackage>com.test.bounded-context2</apiPackage>
<modelPackage>com.test.bounded-context2.model</modelPackage>
<language>spring</language>
<additionalProperties>
<additionalProperty>ignoreImportMappings=false</additionalProperty>
</additionalProperties>
<importMappings>
<importMapping>Test=com.test.common.model.Test</importMapping>
</importMappings>
</configuration>
</execution>
</executions>
</plugin>
...
- Profit 🙂
In case of additional questions do not hesitate to ask me
BTW I believe the issue could be closed for now
Hi, even though it works, in my opinion the solution is not ideal, because you need to explicitly declare the mapping for each class you want to be "shared". It would be better to have an option to let the plugin know that every class imported from common-classes.yaml remote reference should use the common package instead.