Springfox 3.0 not working in Spring framework - spring

I have a Spring application. I am trying to migrate it to Springfox 3.0 from Springfox 2.9.2.
It is already working on old Springfox dependencies, but with 3.0, I can't access any of the documentation at all. As far as I know, all I just need to do is add the Springfox dependecy below:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
And remove all Springfox 2.9.2 configurations/beans. And it should work alright.
I tried accessing the Swagger UI docs via
/swagger-ui
/swagger-ui/
/swagger-ui/#/
/swagger-ui/index.html
Still, its not accessible. The microservice compiles successfully with mvn clean install. What do I do to make Springfox 3.0 work?

You still need to keep the following basic configuration:
#Configuration
public class SpringFoxConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
You may want to check the migration guide here.
I strongly suggest you move to springdoc, which is a more recent library, way less buggy and much easier to work with. Take a look at:
https://springdoc.org/
https://springdoc.org/#migrating-from-springfox

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
}

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

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.

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...!

Spring boot metrics with Jersey2

I have an application running spring-boot, jersey2 and spring metrics:
below is maven snippet:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Jersey used to work well until introducing actuator dependency.
Then following bean has been created to make Jersey working as filter:
#Bean
public FilterRegistrationBean jerseyFilterRegistration() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setName("jerseyFilter");
bean.setFilter(new ServletContainer(resourceConfig()));
bean.setOrder(Ordered.LOWEST_PRECEDENCE);
bean.addInitParameter("com.sun.jersey.config.property.WebPageContentRegex", managementContextRegex);
return bean;
}
Metrics are mapped to /admin path. With this configuration I cannot make metrics working. However by adding management.port (different than main app port) both Jersey resource and metrics are available.
What I'm missing here to make both metrics and Jersey resource start working on the same port?
"com.sun.jersey.config.property.WebPageContentRegex"
This is the wrong property. That's for Jersey 1.x. For 2.x, it should be
"jersey.config.servlet.filter.staticContentRegex"
See ServletProperties.FILTER_STATIC_CONTENT_REGEX
As an aside you can avoid having to define your own FilterRegistrationBean by simply setting a couple configuration properties. In your application.properties, you could use the following
spring.jersey.type=filter
spring.jersey.init.jersey.config.servlet.filter.staticContentRegex=<your-regex>
Or you can configure the regex in your ResourceConfig subclass
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
property(ServletProperties.FILTER_STATIC_CONTENT_REGEX, "<your-regex>");
}
}
As another side, just an FYI, the cause of the problem is the default /* url-mapping used for Jersey. If you can change it, doing so would solve the problem. For instance /api. You can configure that in the properties with spring.jersey.applicationPath=/api or with #ApplicationPath("/api") on the ResourceConfig subclass.
And the final aside, there is also a property
ServletProperties.FILTER_FORWARD_ON_404
"jersey.config.servlet.filter.forwardOn404"
I'm not exactly sure how the staticContenRegex property works, I never really dug into to source code. So I don't know if it just does some file IO to get the static file or it forwards the request, but if it does some file IO, then I don't think the property will work for your use case, as the endpoints are not files. In which case the forwardOn404 should work.

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