Springfox swagger - no api-docs with spring boot jersey and gradle - gradle

I have a spring boot application with jersey and gradle, and I am trying to automatically generate the API documentation using springfox.
I have followed the steps here: http://springfox.github.io/springfox/docs/current/
Here is what I did:
build.gradle:
dependencies {
.........
//Swagger
compile "io.springfox:springfox-swagger2:2.4.0"
compile "io.springfox:springfox-bean-validators:2.4.0"
compile 'io.springfox:springfox-swagger-ui:2.4.0'
}
Spring boot Application:
#SpringBootApplication
#EnableSwagger2
public class AnalyzerServiceApplication{
public static void main(String[] args) {
SpringApplication.run(AnalyzerServiceApplication.class, args);
}
#Bean
public Docket analyzerApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping("/")
.directModelSubstitute(LocalDate.class, String.class)
.genericModelSubstitutes(ResponseEntity.class)
.alternateTypeRules(
newRule(typeResolver.resolve(DeferredResult.class,
typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
typeResolver.resolve(WildcardType.class)))
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET,
newArrayList(new ResponseMessageBuilder()
.code(500)
.message("500 message")
.responseModel(new ModelRef("Error"))
.build()))
.securitySchemes(newArrayList(apiKey()))
.securityContexts(newArrayList(securityContext()))
.enableUrlTemplating(true)
.globalOperationParameters(
newArrayList(new ParameterBuilder()
.name("someGlobalParameter")
.description("Description of someGlobalParameter")
.modelRef(new ModelRef("string"))
.parameterType("query")
.required(true)
.build()))
.tags(new Tag("Pet Service", "All apis relating to pets"))
;
}
#Autowired
private TypeResolver typeResolver;
private ApiKey apiKey() {
return new ApiKey("mykey", "api_key", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("/anyPath.*"))
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return newArrayList(
new SecurityReference("mykey", authorizationScopes));
}
#Bean
SecurityConfiguration security() {
return new SecurityConfiguration(
"test-app-client-id",
"test-app-client-secret",
"test-app-realm",
"test-app",
"apiKey",
ApiKeyVehicle.HEADER,
"api_key",
"," /*scope separator*/);
}
#Bean
UiConfiguration uiConfig() {
return new UiConfiguration("validatorUrl");
}
Now the controller (Jersey)
#Api(value = "/widget")
#Path("/widget")
#Component
public class WidgetController extends BaseController {
#Autowired
private WidgetService widgetService;
#GET
#Path("/secHealth")
#ApiOperation(value = "Find pet by ID", notes = "Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions", response = Pet.class)
#ApiResponses(value = { #ApiResponse(code = 400, message = "Invalid ID supplied"),
#ApiResponse(code = 404, message = "Pet not found") })
public Response getPet() {
//Do something
}
When I start the server and navigate to http://localhost:8080/swagger-ui.html, I can see the "green" UI screen with only the basic-error-controller listed there. My own controller is not there.
What did I do wrong?
Thanks
Guy

As of version 2.5.0 springfox only supports spring-mvc controllers. Jax-rs implementations like jersey aren't supported.
The current alternative to using springfox is to use the swagger-core library for jax-rs/jersey based services.
It does have the hooks needed to implement support for jersey in 2.6+. Here is an excerpt of a way to implement it in this issue
Currently ResourceConfig has a method called "getClasses" which will
list everything registerted. like Resources, Filters,etc... Maybe this
could help. But be aware that the returning classes could also be
filters or any other stuff you could register with jersey2.

To be able to see Jersey methods from Springfox swagger UI:
Configure your Swagger with Jersey following https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5
Configure Springfox Swagger following http://springfox.github.io/springfox/docs/current/
Add in you SpringBoot application configuration class (annotated with #Configuration):
#Value("${springfox.documentation.swagger.v2.path}")
private String swagger2Endpoint;
In application.properties add reference to your Jersey swagger.json:
springfox.documentation.swagger.v2.path=/{change it to your Jersey api path}/swagger.json
Now you should be able to see Jersey Swagger generated api from Springfox Swagger UI page.

Thanks #Dilip-Krishnan for the springfox update and #Guy-Hudara for the question, I came up with the following solution to get swagger support in my springboot jersey powered app :
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* As of version 2.5.0 springfox only supports spring-mvc controllers. Jax-rs implementations like jersey aren't supported.
*
* Fortunately io.swagger::swagger-jersey2-jaxrs::1.5.3 have the hooks needed to implement support for jersey in 2.6+.
*
* some pointers I used to get this swagger config done and swagger-core, springboot and jersey integrated:
* http://stackoverflow.com/questions/37640863/springfox-swagger-no-api-docs-with-spring-boot-jersey-and-gardle
* https://www.insaneprogramming.be/blog/2015/09/04/spring-jaxrs/
* https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5#adding-the-dependencies-to-your-application
*
*/
#Configuration
public class SwaggerConfiguration {
#Autowired
ResourceConfig resourceConfig;
#PostConstruct
public void configure() {
resourceConfig.register(ApiListingResource.class);
resourceConfig.register(SwaggerSerializers.class);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8888");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("com.my.resource");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
}
}
That worked out great for me

Related

SpringBoot Rest Controller Supporting both xml and json with JAXB Pojos + Custom Http Message Converters + Swagger-UI

Getting following Swagger error when I introduced custom message converters
Unable to render this definition
The provided definition does not specify a valid version field.
Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
The error is misleading, I guess its getting confused with the converters. Any Ideas to get it fixed?
I followed - swagger-ui not working with custom XML ObjectMapper (no luck)
Background:
I have generated pojos from xsd(s) through xjc. And I have a rest endpoint which needs to support both xml and json for request/response
We got it working by following [spring documentation][1] section: 22.16.12 Message Converters
Here is what I added in MyConfig
#Configuration
#EnableWebMvc
public class MyConfig implements WebMvcConfigurer {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter(objectMapper()));
converters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper()));
}
#Bean
#Primary
public ObjectMapper objectMapper() {
return new Jackson2ObjectMapperBuilder()
.modulesToInstall(new JaxbAnnotationModule())
.build();
}
#Bean
public XmlMapper xmlMapper() {
return new Jackson2ObjectMapperBuilder()
.indentOutput(true)
.defaultUseWrapper(false)
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.modulesToInstall(new JaxbAnnotationModule())
.createXmlMapper(true)
.build();
}
}
and my controller
// all the open api annotations //
#RequestMapping(value = "/run",
produces = {"application/json", "application/xml"},
consumes = {"application/json", "application/xml"},
method = RequestMethod.POST)
public ResponseEntity<MyResponse> run(#RequestBody MyRequest request) {
Ok its about which objectMapper. I had to clean up and remove '#primary' which made the trick in MyConfig
#Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
return new MappingJackson2HttpMessageConverter(new Jackson2ObjectMapperBuilder()
.modulesToInstall(new JaxbAnnotationModule())
.build());
}
#Bean
public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter() {
return new MappingJackson2XmlHttpMessageConverter(new Jackson2ObjectMapperBuilder()
.indentOutput(true)
.defaultUseWrapper(false)
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.modulesToInstall(new JaxbAnnotationModule())
.createXmlMapper(true)
.build());
}

swagger-ui doesn't list any of the controllers endpoints

I'm trying to add Swagger to a very simple hello word Spring-Boot project.
I'm following this tutorial :
https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api
this is my SwaggerConfig:
#Configuration
#EnableSwagger2
public class SwaggerConfig{
#Bean
public Docket greetingApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.swaggerready"))
.build()
.apiInfo(metaData());
}
private ApiInfo metaData() {
return new ApiInfoBuilder()
.title("Spring Boot REST API")
.description("\"Spring Boot REST API for greeting people\"")
.version("1.0.0")
.license("Apache License Version 2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"")
.build();
}
}
However, the results I have running it is only the first page without any information.
This is the repository if someone wants to see the full code.
https://github.com/ThadeuFerreira/SpringMicro
In class SwaggerConfig you need to change line:
.apis(RequestHandlerSelectors.basePackage("com.example.swaggerready"))
To:
.apis(RequestHandlerSelectors.basePackage("com.example.SpringMicro"))

Spring Boot & Swagger UI. Set JWT token

I have a Swagger config like this
#EnableSwagger2
#Configuration
public class SwaggerConfig {
#Bean
public Docket api() {
List<SecurityScheme> schemeList = new ArrayList<>();
schemeList.add(new ApiKey(HttpHeaders.AUTHORIZATION, "JWT", "header"));
return new Docket(DocumentationType.SWAGGER_2)
.produces(Collections.singleton("application/json"))
.consumes(Collections.singleton("application/json"))
.ignoredParameterTypes(Authentication.class)
.securitySchemes(schemeList)
.useDefaultResponseMessages(false)
.select()
.apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
.paths(PathSelectors.any())
.build();
}
}
In the Swagger UI when I click on the Authorize button I enter my JWT token in the value field eyJhbGc..nN84qrBg. Now I expect that any request I do through the Swagger UI will contain the JWT in the header. However, that is not the case.
No request contains a Authorization header.
What am I missing?
Original answer
Support for Authorization: Bearer [JWT_TOKEN] header is working as of version 2.9.2
Added the following dependencies to build.gradle
compile("io.springfox:springfox-swagger2:2.9.2") {
exclude module: 'mapstruct' // necessary in my case to not end up with multiple mapstruct versions
}
compile "io.springfox:springfox-bean-validators:2.9.2"
compile "io.springfox:springfox-swagger-ui:2.9.2"
Configured Swagger via
#Configuration
#EnableSwagger2
#Import(springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration.class)
public class SwaggerConfiguration {
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String DEFAULT_INCLUDE_PATTERN = "/api/.*";
private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);
#Bean
public Docket swaggerSpringfoxDocket() {
log.debug("Starting Swagger");
Contact contact = new Contact(
"Matyas Albert-Nagy",
"https://justrocket.de",
"matyas#justrocket.de");
List<VendorExtension> vext = new ArrayList<>();
ApiInfo apiInfo = new ApiInfo(
"Backend API",
"This is the best stuff since sliced bread - API",
"6.6.6",
"https://justrocket.de",
contact,
"MIT",
"https://justrocket.de",
vext);
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.pathMapping("/")
.apiInfo(ApiInfo.DEFAULT)
.forCodeGeneration(true)
.genericModelSubstitutes(ResponseEntity.class)
.ignoredParameterTypes(Pageable.class)
.ignoredParameterTypes(java.sql.Date.class)
.directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
.directModelSubstitute(java.time.ZonedDateTime.class, Date.class)
.directModelSubstitute(java.time.LocalDateTime.class, Date.class)
.securityContexts(Lists.newArrayList(securityContext()))
.securitySchemes(Lists.newArrayList(apiKey()))
.useDefaultResponseMessages(false);
docket = docket.select()
.paths(regex(DEFAULT_INCLUDE_PATTERN))
.build();
watch.stop();
log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis());
return docket;
}
private ApiKey apiKey() {
return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN))
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Lists.newArrayList(
new SecurityReference("JWT", authorizationScopes));
}
}
Access the ui via http://host:port/<context-root>/swagger-ui.html
Press Authorize all requests and enter Bearer [JWT_TOKEN]
Voila your next requests will have the JWT header
Update 2022-09-24
After a series of newer projects, I started using springdoc-openapi that generates docs based on javadoc, eliminating the need of extra annotations.
Writing this for anyone who is willing to give this library a try. I would recommend it/am a happy user of this lib.
Dependencies
build.gradle
[...]
// swagger ui
implementation 'org.springdoc:springdoc-openapi-ui:1.6.9'
implementation 'org.springdoc:springdoc-openapi-javadoc:1.6.9'
annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.13.0'
implementation 'com.github.therapi:therapi-runtime-javadoc:0.13.0'
[...]
Declare Authentication
Using the project specific SecurityConfiguration.java - define the pattern of the OpenAPI authorization. This case: Bearer in Authorization in the HTTP header.
import static io.swagger.v3.oas.annotations.enums.SecuritySchemeIn.HEADER;
import static io.swagger.v3.oas.annotations.enums.SecuritySchemeType.HTTP;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
#Component
#SecurityScheme(name = SecurityConfiguration.SECURITY_CONFIG_NAME, in = HEADER, type = HTTP, scheme = "bearer", bearerFormat = "JWT")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
[...]
public static final String SECURITY_CONFIG_NAME = "App Bearer token";
[...]
Usage in REST controllers
Usage in SomeController.java shall reference the security config
import static com.x.common.security.SecurityConfiguration.SECURITY_CONFIG_NAME;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
#RestController
#RequestMapping("/api/v1/resources")
#SecurityRequirement(name = SECURITY_CONFIG_NAME)
public class ConnectionSyncController {
/**
* Documentation that will be rendered
*
* supports
*
* 1. markdown
* 1. list
*/
#PostMapping("/{id}/sync")
#DomainAuthorize(permissionType = BasePermissions.PERM_ADMIN_OPERATIONS)
public void syncConnection(#PathVariable("id") Long id) {
Configure reachability
Configure location of openapi specs (swagger yml) - default /v3/api-docs
Configure where swagger-ui is located/loads config from
Configure which backends swagger-ui can talk with
In case we are behind a proxy, we need to make sure that the calls are proxied with correct headers for everything to work.
/src/main/resources/application.yml
server:
port: 80
# needed for swagger-ui to detect correct proxied paths correctly.
# Configuration needed for the [Try out] buttons to work
# this works in combination with the proxied headers
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Prefix /services/impower-facilioo;
forward-headers-strategy: FRAMEWORK
springdoc:
swagger-ui:
# where the UI configuration is located at
configUrl: /[some/public/path]/v3/api-docs/swagger-config
filter: true
deepLinking: true
# where the server API yml/json files are at (dropdown in top right corner)
urls[0]:
url: /[some/public/path]/v3/api-docs
name: backend
For swagger version 2.9.2
Create a SwaggerConfig class.
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.securitySchemes(Arrays.asList(apiKey()));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Sig-Predict REST API Document")
.description("work in progress")
.termsOfServiceUrl("localhost")
.version("1.0")
.build();
}
private ApiKey apiKey() {
return new ApiKey("jwtToken", "Authorization", "header");
}
Then annotate each API you would like to send this Authorization header to with:
#ApiOperation(value = "", authorizations = { #Authorization(value="jwtToken") })
Your code is correct.
There is a bug in springfox-swagger-ui/springfox-swagger2 version 2.8.0 and it seems 2.9.2 as well. I suspect you are using a version effected by this bug.
I simply downgraded to 2.7.0 and it worked perfectly.
For a quick solution, I configured my docket with a global parameter authorization header in my swaggerConfig class.
#Configuration
#EnableSwagger2
public class SwaggerConfig {
private static final Set<String> DEFAULT_PRODUCES_CONSUMES = new HashSet<String>(Arrays.asList("application/json"));
#Bean
public Docket api() {
ParameterBuilder parameterBuilder = new ParameterBuilder();
parameterBuilder.name("Authorization")
.modelRef(new ModelRef("string"))
.parameterType("header")
.description("JWT token")
.required(true)
.build();
List<Parameter> parameters = new ArrayList<>();
parameters.add(parameterBuilder.build());
return new Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO)
.produces(DEFAULT_PRODUCES_CONSUMES)
.consumes(DEFAULT_PRODUCES_CONSUMES)
.select()
.build()
// Setting globalOperationParameters ensures that authentication header is applied to all APIs
.globalOperationParameters(parameters);
}
}
Wrote a small post authorization-field-in-swagger-ui about this.
Please try something like below
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any()).paths(PathSelectors.regex("/api/v1/.*"))
.build().groupName("API")
.globalOperationParameters(newArrayList(
new ParameterBuilder().name(HttpHeaders.AUTHORIZATION).description("Authorization token").required(true)
.modelRef(new ModelRef("string")).parameterType("header").required(true).build()))
.apiInfo(apiInfo());
Where the accepted answer is correct, it has a small flaw. You have to manually add 'Bearer '-text in the authorization value to make the token work correctly (when the prefix is expected like in my case).
Did some research to improve this and got this working with using the OpenApi without the need for that tiny nasty addition.
Source I used to go on with this (Made some minor changes/additions)
In pom.xml I have the following:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.5</version>
<relativePath />
</parent>
<properties>
<java.version>16</java.version>
<swagger.version>2.9.2</swagger.version>
<open.api.version>1.6.9</open.api.version>
</properties>
<dependencies>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${open.api.version}</version>
</dependency>
</dependencies>
To the application.properties I added few lines (optional):
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
springdoc.swagger-ui.path=swagger-ui.html
springdoc.paths-to-exclude=/swagger-resources/**
The swagger needed to have some security setting exceptions:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfiguration extends WebSecurityConfigurerAdapter {
/* Specify the urls not requiring authentication. */
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/webjars/**");
}
}
And finally the actual configuration for the swagger using OpenApi:
package com.fujitsu.emom.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
/**
* Configuration for swagger using OpenApi.<br/>
* Notice the spring security must allow to access to the swagger ui at 'SecurityConfiguration.java'.<br/>
* There are also configuration at 'application.properties' for defining the URL to swagger page.
*/
#Configuration
public class SwaggerConfig {
public static final String SCHEME_NAME = "BearerScheme";
public static final String SCHEME = "Bearer";
#Bean
public OpenAPI customOpenAPI() {
var openApi = new OpenAPI().info(this.apiInfo());
this.addSecurity(openApi);
return openApi;
}
private Info apiInfo() {
var contact = new Contact();
contact.setEmail("mailbox#product.com");
contact.setName("product_admin");
contact.setUrl("http://product.com");
return new Info()
.title("Product API")
.description("Product description")
.termsOfService("http://product.com/terms_of_service")
.contact(contact)
// TODO: Version should be dynamically
.version("0.5.1");
}
private void addSecurity(OpenAPI openApi) {
var components = this.createComponents();
var securityItem = new SecurityRequirement().addList(SCHEME_NAME);
openApi.components(components).addSecurityItem(securityItem);
}
private Components createComponents() {
var components = new Components();
components.addSecuritySchemes(SCHEME_NAME, this.createSecurityScheme());
return components;
}
private SecurityScheme createSecurityScheme() {
return new SecurityScheme().name(SCHEME_NAME).type(SecurityScheme.Type.HTTP).scheme(SCHEME);
}
}

Spring boot with swagger UI gives empty page

I am trying to use Swagger UI for API documentation which is developed using Spring Boot framework.
1) Dependency in pom
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<version>${swagger-core-version}</version>
</dependency>
<properties>
<springfox-version>2.5.0</springfox-version>
<swagger-core-version>1.5.10</swagger-core-version>
</properties>
2) Docket configuration
#ComponentScan(basePackages = {"com.testApp.*"})
#Configuration
#EnableSwagger2
public class Application {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select().apis(
RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
3) Resource configuration in com.testApp package
#Path("/resources")
#Api(value = "Test resource", produces = "application/json")
public class MyResource {
#Autowired
public SomeClass someclass;
/**
*
* #param uriInfo
* #return
* #throws PlatformException
*/
#ApiOperation(value = "Gets a hello resource. World Version 1 (version in Accept Header)", response = String.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Hello resource found"),
#ApiResponse(code = 404, message = "Hello resource not found")
})
#GET
#Produces({ MediaType.APPLICATION_JSON })
public String loadResouces(#Context UriInfo uriInfo) {
//method defination
}
This service runs on port 9001. whenever hit localhost:8080/swagger-ui.html. It returns an empty page of swagger-ui. I've tried few properties of Docket like host, pathmapping etc. But I am not able to generate documentation using this.
To the best of my knowledge springfox-swagger2 supports APIs implemented using Spring MVC only.
If you prefer to implement the endpoints using JAX-RS but still use Swagger to document them, please take a look at this answer.
A "how-to" could be found at a blog I created sometime ago, Microservices using Spring Boot, Jersey Swagger and Docker
I have solved the similar issue by implementing TypeResolver and RequestMappingHandlerMapping beans.
Please try adding the following beans to your Application class.
#Bean
public TypeResolver typeResolver(){
return new TypeResolver();
}
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(){
return new RequestMappingHandlerMapping();
}

How to specify my restful API for swagger-ui in spring-boot application

I am using spring-boot + jersey as restful implementation. I have setup the swagger and I am able to open the swagger ui on the browser. But the swagger-ui doesn't have any API to show, it is an empty page. Below is the code I setup for configuring swagger. How can I let swagger to scan my API definition in jersey?
SwaggerConfiguration.java
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/com.hello.*"))
.build().pathMapping("/swagger2");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("App API")
.description("App API")
.version("1.0.0-SNAPSHOT")
.termsOfServiceUrl("")
.contact("Cooltoo company")
.license("Public")
.licenseUrl("http://hello.com/")
.build();
}
JerseyConfiguration.java
#Configuration
#EnableSwagger2
#EnableAutoConfiguration
#Api(value = "home", description = "Demo API")
#ApplicationPath("/nursego")
public class JerseyConfiguration extends ResourceConfig {
public JerseyConfiguration() {
register(BadgeAPI.class);
register(MultiPartFeature.class);
register(OrderAPI.class);
register(NurseAPI.class);
configureSwagger();
}
private void configureSwagger() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/nursego");
beanConfig.setResourcePackage("com.cooltoo.backend.api");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
register( io.swagger.jaxrs.listing.ApiListingResource.class );
register( io.swagger.jaxrs.listing.SwaggerSerializers.class );
}
}
When I open http://localhost:8080/swagger-ui.html, I see below image but none of them are from my API. I don't know where they are from
I used the BeanConfig class to embed the Swagger into my SpringBoot+Jersey implmentation, the code example is as follows,
#Component
#ApplicationPath( "/api" )
public class JerseyConfig extends ResourceConfig{
public JerseyConfig(){
// method for embedding the Swagger
configSwagger();
// registers the REST resource classes
configEndPoints();
}
private void configEndPoints(){
// here register all the REST resource classes
}
private void configSwagger(){
BeanConfig beanConfig = new BeanConfig();
beanConfig.setSchemes( new String[]{ "http" } );
beanConfig.setHost( "localhost:9001" );
beanConfig.setBasePath( "/api" );
beanConfig.setDescription( "REST API services for accessing the pcg application" );
beanConfig.setTitle( "RESTAPI" );
beanConfig.setVersion( "1.0.1" );
// this will tell Swagger config to scan only these packages
beanConfig.setResourcePackage( "com.aig.rest.web" );
beanConfig.setScan( true );
register( io.swagger.jaxrs.listing.ApiListingResource.class );
register( io.swagger.jaxrs.listing.SwaggerSerializers.class );
}
}
I believe #EnableSwagger2 annotation works if the endpoints are implemented using Spring MVC instead of Jersey (or any other JAX-RS impl).
I have detailed how to accomplish this in a blog post I created earlier this year, Microservices using Spring Boot, Jersey Swagger and Docker
Basically if you need to document your Jersey-implemented endpoints via Swagger, you would need to:
1)
Make sure your Spring Boot app scans for components located in specific packages (ie com.asimio.jerseyexample.config) via:
#SpringBootApplication(
scanBasePackages = {
"com.asimio.jerseyexample.config", "com.asimio.jerseyexample.rest"
}
)
2) Jersey configuration class implementation:
package com.asimio.jerseyexample.config;
...
#Component
public class JerseyConfig extends ResourceConfig {
#Value("${spring.jersey.application-path:/}")
private String apiPath;
public JerseyConfig() {
// Register endpoints, providers, ...
this.registerEndpoints();
}
#PostConstruct
public void init() {
// Register components where DI is needed
this.configureSwagger();
}
private void registerEndpoints() {
this.register(HelloResource.class);
// Access through /<Jersey's servlet path>/application.wadl
this.register(WadlResource.class);
}
private void configureSwagger() {
// Available at localhost:port/swagger.json
this.register(ApiListingResource.class);
this.register(SwaggerSerializers.class);
BeanConfig config = new BeanConfig();
config.setConfigId("springboot-jersey-swagger-docker-example");
config.setTitle("Spring Boot + Jersey + Swagger + Docker Example");
config.setVersion("v1");
config.setContact("Orlando L Otero");
config.setSchemes(new String[] { "http", "https" });
config.setBasePath(this.apiPath);
config.setResourcePackage("com.asimio.jerseyexample.rest.v1");
config.setPrettyPrint(true);
config.setScan(true);
}
}
3) Resource implementation using JAX-RS (Jersey) and Swagger annotations:
package com.asimio.jerseyexample.rest.v1;
...
#Component
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Api(value = "Hello resource", produces = "application/json")
public class HelloResource {
private static final Logger LOGGER = LoggerFactory.getLogger(HelloResource.class);
#GET
#Path("v1/hello/{name}")
#ApiOperation(value = "Gets a hello resource. Version 1 - (version in URL)", response = Hello.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Hello resource found"),
#ApiResponse(code = 404, message = "Hello resource not found")
})
public Response getHelloVersionInUrl(#ApiParam #PathParam("name") String name) {
LOGGER.info("getHelloVersionInUrl() v1");
return this.getHello(name, "Version 1 - passed in URL");
}
...
}
4) Make sure your app's Spring Boot configuration file makes a distinction between Spring MVC (for actuator endpoints) and Jersey (for resources) endpoints:
application.yml
...
# Spring MVC dispatcher servlet path. Needs to be different than Jersey's to enable/disable Actuator endpoints access (/info, /health, ...)
server.servlet-path: /
# Jersey dispatcher servlet
spring.jersey.application-path: /api
...

Resources