Reputation: 594
I configured a swagger for a private API on a spring boot application. These endpoints are made with spring.
There is also a public API on the same server with endpoints made with Jersey.
I configured a swagger for this public API and it seems to work.
When I access to http://localhost:8080/@context.root@/swagger-ui/index.html I can see definitions
However I feel like the configuration is a bit "weird" and could be improved.
Indeed the openapi.json files are created in two different ways and I am pretty sure the swagger configuration could be the same for both API.
I would like to configure the swagger for the jersey resources (public API) using GroupedOpenApi
class and remove all urls configuration from application.yml
, but so far unsuccessfuly...
spring boot version: 2.7.0 but it is planned to upgrade to v3 next month
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.2</version>
</dependency>
Configure swagger "02 - private" for private api made with spring endpoints
import java.time.LocalDate;
import java.time.LocalDateTime;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.SpringDocUtils;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;
@Configuration
public class SwaggerConfiguration implements WebMvcConfigurer {
private static final String FORWARD_SWAGGER_UI_HTML = "forward:/swagger-ui.html";
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/swagger").setViewName(FORWARD_SWAGGER_UI_HTML);
registry.addViewController("/swagger/").setViewName(FORWARD_SWAGGER_UI_HTML);
registry.addViewController("/swagger-ui").setViewName(FORWARD_SWAGGER_UI_HTML);
registry.addViewController("/swagger-ui/").setViewName(FORWARD_SWAGGER_UI_HTML);
}
@Bean
public OpenAPI openApiDefinition(final AppProperties properties) {
SpringDocUtils.getConfig().replaceWithClass(LocalDate.class, String.class);
SpringDocUtils.getConfig().replaceWithClass(LocalDateTime.class, String.class);
return new OpenAPI()
.addServersItem(new Server().url("/" + properties.getContextRoot()))
.info(new Info().title(properties.getAppName()));
}
@Bean
public GroupedOpenApi privateApi(final AppProperties properties) {
return GroupedOpenApi.builder()
.group("02 - private")
.pathsToMatch("/api/**")
.pathsToExclude("/api/pub/*")
.addOpenApiCustomiser(this.customizeApiPrivate(properties))
.build();
}
private OpenApiCustomiser customizeApiPrivate(final AppProperties properties) {
return (final OpenAPI openApi) -> openApi.getInfo()
.title("Private API title")
.description("Private API description")
.version(properties.getAppVersion());
}
// This create "01 - public" but with empty endpoints / operations,
// it seems like jersey endpoints are just ignored if swagger is configured this way
/**
@Bean
public GroupedOpenApi publicApi(final AppProperties properties) {
return GroupedOpenApi.builder()
.group("01 - public")
.pathsToMatch("/api/pub/**")
.packagesToScan("path.to.resources.package.api.pub")
.addOpenApiCustomiser(...)
.build();
}
*/
}
Configure location of openapi.json for the public api "01 - public"
springdoc:
swagger-ui:
disable-swagger-default-url: true
defaultModelExpandDepth: 3
operationsSorter: "alpha"
tagsSorter: "alpha"
urls:
- name: '01 - public'
url: '/@context.root@/swagger-ui/pub/openapi.json'
Configure jersey endpoints + add mapping for swagger of the public api
@EnableWebMvc
@Configuration
@PropertySources(...)
@ComponentScan(...)
@ConfigurationPropertiesScan(...)
public class AppConfiguration implements WebMvcConfigurer {
@Bean
public ServletRegistrationBean<ServletContainer> publicJersey(AppProperties properties)
{
ServletRegistrationBean<ServletContainer> pubJersey = new ServletRegistrationBean<>(
new ServletContainer(new ApiPublicJerseyConfig(properties)));
pubJersey.addUrlMappings("/api/pub/*","/swagger-ui/pub/*");
pubJersey.setLoadOnStartup(0);
return pubJersey;
}
...
}
Configure swagger "01 - public" for public api made with jersey endpoints
import org.glassfish.jersey.server.ResourceConfig;
import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
import io.swagger.v3.oas.integration.SwaggerConfiguration;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;
public class ApiPublicJerseyConfig extends ResourceConfig {
public ApiPublicJerseyConfig(AppProperties properties) {
super();
packages("path.to.resources.package.api.pub");
register(swaggerConfig(properties));
}
private static BaseOpenApiResource swaggerConfig(AppProperties properties) {
return new OpenApiResource().openApiConfiguration(
new SwaggerConfiguration()
.resourcePackages(new HashSet<>(Collections.singletonList("path.to.resources.package.api.pub")))
.openAPI(publicOpenApi(properties))
);
}
private static OpenAPI publicOpenApi(final AppProperties properties) {
return new OpenAPI()
.addServersItem(new Server().url("/" + properties.getContextRoot() + "/api/pub"))
.info(new Info()
.title("Public API title")
.description("Public API description")
.version(properties.getAppVersion())
);
}
}
Upvotes: 0
Views: 1471
Reputation: 594
Ok I think I had my answer here https://springdoc.org/faq.html It seems like I cannot have the same kind of swagger configuration for both servlet types (Spring & Jersey)
Does springdoc-openapi support Jersey?
If you are using JAX-RS and as implementation Jersey (
@Path
for example), we do not support it.We only support exposing Rest Endpoints using Spring managed beans (@RestController for example).
You can have a look at swagger-jaxrs2 project:
https://github.com/swagger-api/swagger-samples/tree/2.0/java/java-jersey2-minimal
Upvotes: 1