swagger-api / swagger-core

Examples and server integrations for generating the Swagger API Specification, which enables easy access to your REST API
http://swagger.io
Apache License 2.0
7.38k stars 2.18k forks source link

Multi-module Maven Regression #3302

Open jellisgwn opened 5 years ago

jellisgwn commented 5 years ago

I'm using the following configuration in a multi-module maven project:

<plugin>
                <groupId>io.swagger.core.v3</groupId>
                <artifactId>swagger-maven-plugin</artifactId>
                <version>2.0.9</version>
                <executions>
                    <execution>
                        <configuration>
                            <outputFileName>openapi_1</outputFileName>
                            <outputPath>${project.parent.basedir}/swagger</outputPath>
                            <configurationFilePath>${project.basedir}/src/main/resources/openapi-configuration.yaml</configurationFilePath>
                            <contextId>${project.artifactId}</contextId>
                            <prettyPrint>true</prettyPrint>
                        </configuration>
                        <phase>compile</phase>
                        <goals>
                            <goal>resolve</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

and finding that classes from other modules are being included in the generated swagger. By using resourcePackages in the openapi-configuration.yaml the damage can be limited, but there are common package names that make it impossible to completely avoid.

Seeing https://github.com/swagger-api/swagger-core/issues/3179 makes me wonder if this is a regression, or perhaps my expectation is wrong and providing a contextId does give the degree of isolation?

ChristianLutz commented 5 years ago

@jellisgwn Yes you must add the contextId in a multi-module project.

jellisgwn commented 5 years ago

@ChristianLutz right, and as you can see above, contextId is specified. However, that does nothing to restrict the scanner to resources within the module.

Having looked through the scanner code in 2.0.9, unless i'm completely missing things, no attempt it made to limit scanning to the classpath of a specific module. Perhaps this means that 'classes' is not getting reset between invocations of the plugin, and what i'm seeing is an accumulation?

My work around has been to list all the resource classes explicitly. Painful, but workable for now.

frantuma commented 5 years ago

This is indeed an issue in multi module configurations, due to the shared ClassRealm used by plugins in the 2 modules; we will address this looking into a different way to define the classpath for the plugin, possibly available in next release;

For current version a workaround exists, weird as it may sound: provide in each module a dependency to the plugin, which must be different from each other, e.g.:

NOTE: also provide 2 different contextId

moduleA:

            <plugin>
                <groupId>io.swagger.core.v3</groupId>
                <artifactId>swagger-maven-plugin</artifactId>
                <version>2.0.9</version>
                <executions>
                    <execution>
                        <configuration>
                            <outputFileName>openapi_1</outputFileName>
                            <outputPath>${project.parent.basedir}/swagger</outputPath>
                            <configurationFilePath>${project.basedir}/src/main/resources/openapi-configuration.yaml</configurationFilePath>
                            <contextId>moduleA</contextId>
                            <prettyPrint>true</prettyPrint>
                        </configuration>
                        <phase>compile</phase>
                        <goals>
                            <goal>resolve</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>io.swagger.core.v3</groupId>
                        <artifactId>swagger-models</artifactId>
                    </dependency>
                </dependencies>
            </plugin>

moduleB:

            <plugin>
                <groupId>io.swagger.core.v3</groupId>
                <artifactId>swagger-maven-plugin</artifactId>
                <version>2.0.9</version>
                <executions>
                    <execution>
                        <configuration>
                            <outputFileName>openapi_2</outputFileName>
                            <outputPath>${project.parent.basedir}/swagger</outputPath>
                            <configurationFilePath>${project.basedir}/src/main/resources/openapi-configuration.yaml</configurationFilePath>
                            <contextId>moduleB</contextId>
                            <prettyPrint>true</prettyPrint>
                        </configuration>
                        <phase>compile</phase>
                        <goals>
                            <goal>resolve</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>io.swagger.core.v3</groupId>
                        <artifactId>swagger-core</artifactId>
                    </dependency>
                </dependencies>
            </plugin>

This is related to the classloading mechanims in maven, see e.g. http://takari.io/book/91-maven-classloading.html

jellisgwn commented 5 years ago

@frantuma that's quite some workaround 🤣

not really practical for me due to the number of modules i'm dealing with, but it's good to know that i'm not losing my mind. had tried everything i could think of to get round the limitations. thanks!

frantuma commented 5 years ago

funny one indeed..

reopening ticket as we want to get this solved.