How to generate OpenApi 3.0 spec from existing Spring Boot App? - spring-boot

I have a project (Spring Boot App + Kotlin) that I would like to have an Open API 3.0 spec for (preferably in YAML). The Springfox libraries are nice but they generate Swagger 2.0 JSON. What is the best way to generate an Open Api 3.0 spec from the annotations in my controllers? Is writing it from scratch the only way?

We have used springdoc-openapi library in our kotlin project, and it meets our need for automating the generation of API documentation using spring boot projects.
It automatically deploys swagger-ui to a spring-boot application
The Swagger UI page should then be available at:
- http://server:port/context-path/swagger-ui.html
The OpenAPI description will be available at the following url for json format:
- http://server:port/context-path/v3/api-docs
Add the library to the list of your project dependencies (No additional configuration is needed)
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.2.32</version>
</dependency>

You could look at spring-restdocs and restdocs-api-spec.
spring-restdocs takes a test-driven approach to API documentation which has many advantages over the introspection-driven approach spring-fox uses. restdocs-api-spec is an extension for spring-restdocs that adds API specification support. Currently it supports OpenAPI2 OpenAPI3 and Postman.

I decided to implement my own generator https://github.com/jrcodeza/spring-openapi maybe you can check it out too. It's based on reflection and supports javax and spring annotations. It also generates inheritance model (with discriminators) based on Jackson annotations. Besides you can define your own interceptors if you want to alter generation process (e.g. when you have your own annotations and need to adjust generated sections of schema). You can use it in runtime mode or as a maven plugin. There is also OpenAPI3 to java client generator, which generates the model from openapi3 spec. Again it generates also Javax annotations and Jackson annotations for correct inheritance.

If you're using jax-rs this tutorial helps. It uses the Apache CXF implementation. I couldn't find any other implementation of jaxrs that uses Spring Boot AND generate Open API 3.0 spec.
You'll need these depedencies:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description-openapi-v3</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.13.6</version>
</dependency>
Here is the general configuration, more detail is in the link:
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackageClasses = PeopleRestService.class)
public class AppConfig {
#Autowired private PeopleRestService peopleRestService;
#Bean(destroyMethod = "destroy")
public Server jaxRsServer(Bus bus) {
final JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
factory.setApplication(new JaxRsApiApplication());
factory.setServiceBean(peopleRestService);
factory.setProvider(new JacksonJsonProvider());
factory.setFeatures(Arrays.asList(new OpenApiFeature()));
factory.setBus(bus);
factory.setAddress("/");
return factory.create();
}
#Bean
public ServletRegistrationBean cxfServlet() {
final ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new CXFServlet(), "/api/*");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
}
https://dzone.com/articles/moving-with-the-times-towards-openapi-v300-adoptio

You can also refer to
https://www.baeldung.com/spring-rest-openapi-documentation
which provides a tutorial on implementing OpenAPI 3.0 with a SpringBoot 1.x or 2.x application using springdoc-openapi.
To summarize, you just add the maven dependency for springdoc-openapi into your application and when you bootRun, go to path
http://server:port/v3/api-docs.yaml/ and you will download an Open API 3.0 spec file in yaml, generated from your application's code.
You can do some other stuff with springdoc-openapi, by accessing the following when your SpringBoot application is running:
http://server:port/v3/api-docs: Gives your spec file in Json format.
http://server:port/swagger-ui.html: Access this in your browser and you will see the swagger documentation.

Related

Spring Boot OpenAPI 3 - How to pass the Pagination Details?

I'm looking to develop the Spring Boot + OpenAPI 3 example by taking a look at the https://www.dariawan.com/tutorials/spring/documenting-spring-boot-rest-api-springdoc-openapi-3/ and https://techsparx.com/software-development/openapi/spring-boot-rest-api-docs.html. In this example, I am looking to pass the pagination details through Swagger UI that I got by adding the springdoc-openapi-ui.
What Spring Boot Configurations do I need to do in order to support custom pagination.?
Add #PageableAsQueryParam annotation on the method
and add springdoc-openapi-data-rest as a dependency
Their is more than one possiblity the simpliest and fastest is if only want to enable the support of spring Pageable Type, you can just enable it using:
SpringDocUtils.getConfig().replaceWithClass(org.springframework.data.domain.Pageable.class,
org.springdoc.core.converters.models.Pageable.class);
Alternately, the projects that use Pageable type can aslo add the follwing dependency together with the springdoc-openapi-ui dependency. This dependency enables the support of spring-data-rest types as well: #RepositoryRestResource and QuerydslPredicate annotations.
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.5.6</version>
</dependency>
And the add #ParameterObject on the Pageable object on your controller method.
#GetMapping("/books")
public ResponseEntity<List<BookDTO>> getBooks(#ParameterObject Pageable pageable)
"The support for Pageable of spring-data-commons is available out-of-the box since springdoc-openapi v1.6.0. For this, you have to combine #ParameterObject annotation with the Pageable type." - Source
Assuming you are using springdoc-openapi v1.6.0 or grater, you could do something like this:
#GetMapping("/foo")
public Page<Foo> getFoo(#ParameterObject Pageable pageable) {
// do something
}

Spring boot auto configuration with dependency and without #ComponentScan

Spring boot provides #ComponentScan to find packages to be scanned.
I am building a library which has #RestControllers inside with package com.mylib.controller. There are other classes as well with stereotype annotations in different packages.
So, if some one is developing SpringBoot Application with com.myapp base package.
He uses my library in his application. He need to mention #ComponentScan("com.mylib") to discover stereotype components of library.
Is there any way to scan components without including library package in #ComponentScan?
As spring-boot-starter-actuator expose its endpoints just with dependency, without defining #ComponentScan. OR any default package which is scanned regardless of application base package.
You could create a Spring Boot Starter in the same style as the Spring Provided Starters. They are essentially a jar'd library with a a spring.factories file pointing to the #Configuration class to load with some other annotations on there to provide overriding/bean back off (#ConditionalOnMissingBean) and generally provide their own #ConfigurationProperties.
Stéphane Nicoll provided an excellent demo of how to build one.
https://github.com/snicoll-demos/hello-service-auto-configuration
It is also documented in the Spring Boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
The library approach would also work but I see no benefit in not making it a starter. Additionally for any library/starter I'd recommend dropping the #ComponentScan and just defining the beans in a #Configuration. This will work for sterotypes like #RestController etc. will function as normal if you create an #Bean out of it in a configuration.
Spring boot starter are special artifacts designed by Spring and used by Spring.
You can check that in the source code that contains mainly a
spring.provides file :
provides: spring-boot-actuator,micrometer-core
I don't know the exact way to process in the same way as Spring Boot Starter but as probably acceptable workaround, you could define in your jar a #Configuration class that specifies #ComponentScan("com.mylib").
#Configuration
#ComponentScan("com.mylib")
public class MyLibConfig {
//...
}
In this way, clients of the jar need "only" to import the #Configuration class :
#Import(MyLibConfig.class)
#Configuration
public class ClientConfig{
//...
}

Deploy Spring Boot (with JSP) to Elastic Beanstalk

I am attempting to deploy my Spring Boot project to Amazon Elastic Beanstalk. I have tested and have no issue if I use the default Thymeleaf configuration, but when I switch to JSP based setup I get 404's as it cannot find the JSP's (located in src/main/webapp/WEB-INF/jsp)
I have attempted to deploy the sample (spring-boot-sample-tomcat-jsp) and find that this as well gives me a 404 when I run the provided test.
Here is how I have typically been configuring my Spring Boot Projects to allow for the use of JSP's.
Add Jasper and JSTL to pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
Override default view resolver configuration
#Configuration
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter
{
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
}
Create folder for JSP's (src/main/webapp/WEB-INF/jsp)
Now this method works without issue until I deploy to Elastic Beanstalk where I find that no matter if I create a jar and use Java (in Elastic Beanstalk) or create a war and use Tomcat (in eb) I get a 404 when any controller tries to return a view in the WEB-INF/jsp folder.
Is the above method for switching to JSP's not recommended? Is there a better way to configure Spring Boot to use Tomcat/Jasper/JSP's?
I have attempted the method provided in the Spring Boot Samples on github here
But what's interesting is if I run the provided test i get the same 404.
Any help would be greatly appreciated. If there is a better way to deploy a Spring Boot project that utilizes JSP's I'd be happy to switch over, but currently I seem to have configured myself into a corner.
Thx!
I am answering as a novice developer in Springboot development. And, I am just playing around with AWS EB and SpringBoot app deployment.
Here are my findings,
WebMvcConfigurerAdapter is deprecated
SpringBoot app works seamlessly on AWS EB only when we extend application/main class with SpringBootServletInitializer
I tried a sample HelloWorld application extending WebMvcConfigurerAdapter, which worked seamlessly on localhost and failed miserable on AWS EB.
I switched the application class extending from WebMvcConfigurerAdapter to SpringBootServletInitializer, this worked on both localhost as well as AWS EB.
The example I tried is inspired from here: https://github.com/in28minutes/deploy-spring-boot-aws-eb/tree/master/03-spring-boot-web-application-h2
Here is the application class that I changed from extending SpringBootServletInitializer to WebMvcConfigurerAdapter, which didn't work and gave me 404.
https://github.com/in28minutes/deploy-spring-boot-aws-eb/blob/master/03-spring-boot-web-application-h2/src/main/java/com/in28minutes/springboot/web/SpringBootFirstWebApplication.java
Hopefully this helps ...!
Still finding out a reason about why we receive 404 when we extend Application class with WebMvcConfigurerAdapter. I Will update this same answer, once I find a reason.
Thank you...!

How to add Struts2 to a web application without web.xml?

Can someone help me with a minimal project setup with Spring Boot and Struts2?
I have already create a Spring Boot application with a H2-database. I also added a h2Configuration class, so that I'm able to access the database with localhost:8080/console.
But how can I add Struts2 to my Application without web.xml?
Without web.xml you can only write a Struts2 filter using servlet 3.0 or higher
#WebFilter("/*")
public class Struts2Filter extends Struts2PrepareAndExecuteFilter {
}
The content could be empty, it's enough to add annotated filter without any inclusion in the web.xml file.
If you want to integrate Struts2 with Spring, then you should use a plugin.
Struts 2 provides a plugin that enables Spring to inject into the ActionSupport classes any dependent objects you've specified in the Spring configuration file. Consult Spring Plugin documentation for more information about how the plugin works.

A 'simple' way to implement Swagger in a Spring MVC application

I have a ReSTFul API written in simple Spring (no Spring Boot, no fancy stuff!). I need to implement Swagger into this. So far, EVERY page on the internet has only driven me crazy with confusing configurations and bloated code that I did not find portable at all.
Does anyone have a sample project (or a set of detailed steps) that can help me accomplish this? In particular, I am looking for a good sample that uses swagger-springmvc. I know it has 'samples', but at best, the esoteric code is discouraging.
I must clarify that I am not looking for "why Swagger is simply the best". I am not using (and for my current task will not use) Spring Boot or such.
Springfox (Swagger spec 2.0, current)
Springfox has replaced Swagger-SpringMVC, and now supports both Swagger specs 1.2 and 2.0. The implementation classes have changed, allowing for some deeper customization, but with some work. The documentation has improved, but still needs some details added for advanced configuration. The old answer for the 1.2 implementation can still be found below.
Maven dependency
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
The bare-minimum implementation looks more-or-less the same, but now uses the Docket class instead of the SwaggerSpringMvcPlugin class:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/api/.*"))
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("TITLE")
.description("DESCRIPTION")
.version("VERSION")
.termsOfServiceUrl("http://terms-of-services.url")
.license("LICENSE")
.licenseUrl("http://url-to-license.com")
.build();
}
}
Your Swagger 2.0 API documentation will now be available at http://myapp/v2/api-docs.
Note : If you are not using Spring boot then you should add jackson-databind dependency. Since springfox uses jackson for databinding.
Adding Swagger UI support is even easier now. If you are using Maven, add the following dependency for the Swagger UI webjar:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>
If you are using Spring Boot, then your web app should automatically pick up the necessary files and show the UI at http://myapp/swagger-ui.html (formerly: http://myapp/springfox). If you are not using Spring Boot, then as yuriy-tumakha mentions in the answer below, you will need to register a resource handler for the files. The Java configuration looks like this:
#Configuration
#EnableWebMvc
public class WebAppConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
The new static documentation generation feature also looks quite nice, though I have not tried it out myself.
Swagger-SpringMVC (Swagger spec 1.2, older)
The documentation for Swagger-SpringMVC can be a little bit confusing, but it is actually incredibly easy to set up. The simplest configuration requires creating a SpringSwaggerConfig bean and enabling annotation-based configuration (which you probably already do in your Spring MVC project):
<mvc:annotation-driven/>
<bean class="com.mangofactory.swagger.configuration.SpringSwaggerConfig" />
However, I think it is well worth it to take the extra step of defining a custom Swagger configuration using the SwaggerSpringMvcPlugin, instead of the previous XML-defined bean:
#Configuration
#EnableSwagger
#EnableWebMvc
public class SwaggerConfig {
private SpringSwaggerConfig springSwaggerConfig;
#SuppressWarnings("SpringJavaAutowiringInspection")
#Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
this.springSwaggerConfig = springSwaggerConfig;
}
#Bean
public SwaggerSpringMvcPlugin customImplementation(){
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.apiInfo(apiInfo())
.includePatterns(".*api.*"); // assuming the API lives at something like http://myapp/api
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("TITLE")
.description("DESCRIPTION")
.version("VERSION")
.termsOfServiceUrl("http://terms-of-services.url")
.license("LICENSE")
.licenseUrl("http://url-to-license.com")
.build();
}
}
When you run your application, you should now see your API spec created at http://myapp/api-docs. To get the fancy Swagger UI set up, you need to clone the static files from the GitHub project and put them in your project. Make sure your project is configured to serve the static HTML files:
<mvc:resources mapping="*.html" location="/" />
Then edit the index.html file at the top level of the Swagger UI dist directory. Towards the top of the file, you'll see some JavaScript that refers to the api-docs URL of another project. Edit this to point to your project's Swagger documentation:
if (url && url.length > 1) {
url = url[1];
} else {
url = "http://myapp/api-docs";
}
Now when you navigate to http://myapp/path/to/swagger/index.html, you should see the Swagger UI instance for your project.
Springfox Swagger UI works for me after adding WebJar dependency and resource mappings.
http://www.webjars.org/documentation#springmvc
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.5</version>
</dependency>
spring-servlet.xml:
<mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/"/>
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
or Spring Annotation
https://github.com/springfox/springfox-demos/blob/master/spring-java-swagger/src/main/java/springfoxdemo/java/swagger/SpringConfig.java
Swagger2 should be enabled
#EnableSwagger2
public class SwaggerConfiguration {
}
You can also consider using swagger-maven-plugin to generate swagger.json and copy it to yours static swagger-ui.
Please check simple sample of working plugin with Spring MVC annotations on this repo:
https://github.com/khipis/swagger-maven-example
or for JAX-RS
https://github.com/kongchen/swagger-maven-example

Resources