What is the function of springdoc-openapi-maven-plugin configuration/apiDocsUrl?
Asked Answered
Q

5

18

I'm running the springdoc-openapi-maven-plugin, with the following (standard) configuration:

        <plugin>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-maven-plugin</artifactId>
            <version>0.2</version>
            <executions>
                <execution>
                    <id>integration-test</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

The plugin appears to run, but there is no output.

I am getting a 404 error in the Maven output:

[INFO] --- springdoc-openapi-maven-plugin:0.2:generate (integration-test) @ paatinc-util-websrv ---
10:40:33.930 [http-nio-8080-exec-1] INFO  o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
10:40:33.931 [http-nio-8080-exec-1] INFO  o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
10:40:33.956 [http-nio-8080-exec-1] INFO  o.s.web.servlet.DispatcherServlet - Completed initialization in 25 ms
10:40:33.969 [http-nio-8080-exec-1] INFO  io.paat.util.filter.LoggingFilter - GET http://localhost:8080/v3/api-docs from 127.0.0.1
[ERROR] An error has occured: Response code 404

I can see from my log that the 404 is on a call to: http://localhost:8080/v3/api-docs

I also see in the springdoc-openapi-maven-plugin docs the following configuration:

 <configuration>
  <apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl>
  <outputFileName>openapi.json</outputFileName>
  <outputDir>/home/springdoc/maven-output</outputDir>
 </configuration>

So, it appears that the plugin is attempting to open the local server during integration tests and is failing. What is the point of this? I thought that the plugin would read though my source files and generate an openapi.json file. Why does it need to make an HTTP connection to /v3/api-docs?

Quadrangle answered 6/1, 2020 at 17:4 Comment(9)
"I thought that the plugin would read though my source files and generate an openapi.json file." - Nope. The plugin starts the app and tries to access an URL of the app where the application.json is supposed to reside. My guess is that they took the stance of "someone else generated the application.json, we do not have to re-create it. We just start the server and fetch it".Visitor
Thanks for the response. Do you know how I can generate just the openapi.json file for my SpringBoot app via Maven?Quadrangle
Nope. But let me know if you find out =) I have the same problem.Visitor
It says explicitly "The aim of springdoc-openapi-maven-plugin is to generate json and yaml OpenAPI description during build time." It doesn't make sense that it expects to read it from somewhere.Quadrangle
@Visitor I figured it out. Here is my project which demonstrates how to generate the openapi.json via Maven at build time: github.com/kbaynes/springdoc-maven-plugin-demo. I just had the dependencies wrong.Quadrangle
There is no shame in answering your own question. Out of curiosity: can you point me to the changes that were necessary? It still looks like the server is started through the spring-boot-maven-pluginVisitor
For me the problem was that I had removed the 'springdoc-openapi-core' dep. I don't understand why the server still runs, though I think it has something to do with the triggering the plugin to run as part of 'integration tests'.Quadrangle
Let us continue this discussion in chat.Visitor
I've tried your solution (I was mission the core dependency also) but seems the server it's still needed to be up and running which is not "compile time". Were you able to manage it?Floccus
V
9

By using springdoc-openapi-ui you generate the documentation (html, json & yaml) at runtime, when your app is deployed.

In some scenarios you may want to have the documentation at build time, and that's what the springdoc-openapi-maven-plugin is for. In order for it to work you need as well to have your application started using spring-boot during the integration phase, as explained in the documentation.

Valerivaleria answered 10/4, 2020 at 13:13 Comment(3)
That's exactly the thing - the documentation is lying about being generated at build time. Everything is generated at runtime and fetched via http.Blakney
Yeah I'm still getting this even when I follow the instructions and use the spring boot maven plugin to run the app beforehand.Purchasable
yeah, this is not technically generated at build time, but at run time (as integration-test phase requires a running server I presume they thought this was ideal time to do it). not ideal if you don't want integration tests running. I used springdoc-openapi instead and works a treatPeasant
L
5

Both diegomtassis & Erdinc Ay together with this great baeldung post got me on the right track.

The thing about the springdoc-openapi-maven-plugin is: it isn't able to successfully run on it's own - nor does it suffice to simply add it as the only dependency to your pom.xml!

The plugin needs 2 other dependencies to do the groundwork in order to make it work:

  1. You need to add the springdoc-openapi-ui plugin (for Tomcat / Spring MVC based apps) OR the springdoc-openapi-webflux-ui plugin (for Reactive WebFlux / Netty based apps) to your pom.xml first!

Here's the Spring MVC example:

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.4.8</version>
</dependency>
  1. You need to configure the spring-boot-maven-plugin to fire up our Spring Boot app including the API url the springdoc-openapi-maven-plugin needs to generate the openapi.json inside the Maven integration test phase.

Here's the needed configuration of the already present spring-boot-maven-plugin inside your pom.xml (and no: you don't need a version for this plugin here, since it's inheritet from the spring-boot-starter-parent you use):

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>pre-integration-test</id>
                    <goals>
                        <goal>start</goal>
                    </goals>
                </execution>
                <execution>
                    <id>post-integration-test</id>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-maven-plugin</artifactId>
            <version>1.1</version>
            <executions>
                <execution>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

As the docs state you can customize things like apiDocsUrl, outputDir where the openapi.json will be placed - and even the name of the json file with outputFileName. But you don't need to do so (in contrast to what Peeve said)!

Now if you run Maven using mvn verify (or mvn verify -DskipTests=true to speed up the execution), you should see some output like that:

[INFO] --- spring-boot-maven-plugin:2.3.5.RELEASE:start (pre-integration-test) @ hellobackend ---
[INFO] Attaching agents: []

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.5.RELEASE)

2020-11-04 10:26:07.246  INFO 42143 --- [           main] i.j.s.SpringBootBuildpackApplication     : Starting SpringBootBuildpackApplication on PikeBook.fritz.box with PID 42143 (/Users/jonashecht/dev/spring-boot/spring-boot-kong/hellobackend/target/classes started by jonashecht in /Users/jonashecht/dev/spring-boot/spring-boot-kong/hellobackend)
2020-11-04 10:26:07.249  INFO 42143 --- [           main] i.j.s.SpringBootBuildpackApplication     : No active profile set, falling back to default profiles: default
2020-11-04 10:26:08.730  INFO 42143 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2020-11-04 10:26:08.742  INFO 42143 --- [           main] i.j.s.SpringBootBuildpackApplication     : Started SpringBootBuildpackApplication in 1.82 seconds (JVM running for 2.318)
[INFO]
[INFO] --- springdoc-openapi-maven-plugin:1.1:generate (default) @ hellobackend ---
2020-11-04 10:26:09.579  INFO 42143 --- [ctor-http-nio-2] o.springdoc.api.AbstractOpenApiResource  : Init duration for springdoc-openapi is: 29 ms
[INFO]
[INFO] --- spring-boot-maven-plugin:2.3.5.RELEASE:stop (post-integration-test) @ hellobackend ---
[INFO] Stopping application...
2020-11-04 10:26:09.661  INFO 42143 --- [on(2)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  23.392 s
[INFO] Finished at: 2020-11-04T10:26:11+01:00
[INFO] ------------------------------------------------------------------------

Finally you should have a new file openapi.json inside your Spring Boot app's /target folder like this (which was the point of using the springdoc-openapi-maven-plugin in the first place). If you like to see a fully comprehensible example project, you can have a look at this one: https://github.com/jonashackt/spring-boot-openapi-kong/tree/main/weatherbackend

Lag answered 4/11, 2020 at 9:54 Comment(1)
great post, thanks for the analysis!Galvanoscope
G
1

First add this Maven dependency to your project:

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.3.2</version>
        <scope>compile</scope>
    </dependency>

Secondly make the Maven plugin runnable:

    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>pre-integration-test</id>
                    <goals>
                        <goal>start</goal>
                    </goals>
                </execution>
                <execution>
                    <id>post-integration-test</id>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-maven-plugin</artifactId>
            <version>0.3</version>
            <executions>
                <execution>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <outputFileName>openapi.json</outputFileName>
                <outputDir>${project.build.directory}/openapi-spec</outputDir>
            </configuration>
        </plugin>
    </plugins>
Galvanoscope answered 14/4, 2020 at 14:45 Comment(0)
S
1

Okey guys, so the answer is that this plugins tryies to enable your spring servlet to download the openapi json from it during the compile time. My problem was, that I did not set the proper url for the openapi plugin and therefore 404 error.

The log from issue author:

[http-nio-8080-exec-1] INFO  o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
10:40:33.956 [http-nio-8080-exec-1] INFO  o.s.web.servlet.DispatcherServlet - Completed initialization in 25 ms
10:40:33.969 [http-nio-8080-exec-1] INFO  io.paat.util.filter.LoggingFilter - GET http://localhost:8080/v3/api-docs from 127.0.0.1
[ERROR] An error has occured: Response code 404

The trick is to set the correct url for the json in plugin configurations. It is the url where your json would be at run time (aka when server is running, so change the url, port or whatever you need):

        <plugin>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-maven-plugin</artifactId>
            <version>1.1</version>
            <executions>
                <execution>
                    <id>integration-test</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <apiDocsUrl>${url.docs}</apiDocsUrl>
            </configuration>
        </plugin>
Straka answered 4/11, 2020 at 8:27 Comment(3)
The first sentence of you answer is right. But then it could mislead people, since the default URL the springdoc-openapi plugin generates to serve the API live documentation is http://localhost:8080/v3/api-docs according to the docs. So you only need to configure apiDocsUrl, if you changed the configuration of the springdoc-openapi plugin beforehand.Lag
No, other possibilty is that you dont run the application on 8080 as default and then you need to change apiDocsUrl. The guy got 404 error, therfore the openapi.json was not served on the mentioned adress at compile time. So he do needs to change the apiDocsUrl as I said to "where your json would be at run time".Straka
But as both the authors and your logs show the app runs on 8080 ;) And he also asked for a "standard" configuration. If you use start.spring.io to generate an app skeleton, you get it with an empty application.properties file - so no different port! The real answer to the question is that you need to configure 2 additional maven plugins in order to get the springdoc-openapi-maven-plugin to work (see https://mcmap.net/q/681441/-what-is-the-function-of-springdoc-openapi-maven-plugin-configuration-apidocsurl).Lag
L
0

In my case I had property in application.yaml

servlet.context-path: /api/v1

And I needed to add this param in plugin

<apiDocsUrl>http://localhost:8080/api/v1/v3/api-docs.yaml</apiDocsUrl>

Or remove property servlet.context-path: /api/v1

Lubricate answered 26/8, 2021 at 12:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.