How to use swagger with dropwizard .0.7.0 - swagger

I have the latest dropwizard setup. Now I have created a simple API and I am trying to add Swagger on top. There is a Swagger implementation for dropwizard but the sample code is against Yammer dropwizard 0.6.2 which requires addProvider and addResource. The io.dropwizard environment doesn't seem to have this function. Can you please let me know how I can do this under io.dropwizard?

For Dropwizard 0.7.0 I configure swagger like this:
void configureSwagger(Environment environment) {
environment.jersey().register(new ApiListingResourceJSON());
environment.jersey().register(new ApiDeclarationProvider());
environment.jersey().register(new ResourceListingProvider());
ScannerFactory.setScanner(new DefaultJaxrsScanner());
ClassReaders.setReader(new DefaultJaxrsApiReader());
SwaggerConfig config = ConfigFactory.config();
config.setApiVersion(API_VERSION);
config.setBasePath(".." + environment.getApplicationContext().getContextPath());
}
EDIT
To run Swagger UI with Dropwizard clone the repo and copy the dist directory into src/main/resources/swagger/ (customizing as necessary). Then add the asset bundle like this:
#Override
public void initialize(Bootstrap<ApplicationConfiguration> bootstrap) {
bootstrap.addBundle(new AssetsBundle("/swagger/", "/docs", "index.html"));
}

There are some changes for Swagger spec 2.0 that you can see here:
https://github.com/swagger-api/swagger-core/tree/develop_2.0/samples/java-dropwizard
Namely the configuration is slightly different:
#Override
public void run(SwaggerSampleConfiguration configuration, Environment environment) {
environment.jersey().register(new ApiListingResource());
// specific to the sample
environment.jersey().register(new PetResource());
environment.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
BeanConfig config = new BeanConfig();
// api specific configuration
config.setTitle("Swagger sample app");
config.setVersion("1.0.0");
config.setResourcePackage("com.wordnik.swagger.sample");
config.setScan(true);
}

Dropwizard 1.0.2, Swagger 1.5.0. Call this from your application's run().
private void configureSwagger(Environment environment) {
BeanConfig magicBean = new BeanConfig();
magicBean.setVersion("0.1");
magicBean.setTitle("title");
magicBean.setBasePath("/api");
magicBean.setResourcePackage("com.me.resources");
magicBean.setScan(true);
environment.jersey().register(new ApiListingResourceJSON());
environment.jersey().register(new SwaggerSerializers());
}

In addition to what #fehguy messaged above, I would like to add on how to actually get the base path in dropwizard as well (atleast with 0.8) because apparently you will not be able to get basePath from the yml like this :
config.setBasePath(".." + environment.getApplicationContext().getContextPath());
You will have to do do something like this:
DefaultServerFactory defaultServerFactory = (DefaultServerFactory) serverConfiguration.getServerFactory();
String basePath = defaultServerFactory.getApplicationContextPath();
Refer to the github issue here which took me DAYS to figure out. Hope this helps others

Related

How to set OpenApi config via code and not using annotation in Micronaut

I have a springboot application and I want to convert to Micronaut, but how I config the openapi via code, like in this article
https://keepgrowing.in/java/springboot/how-to-secure-spring-boot-swagger-ui-with-basic-authentication/
Code snippet:
#Configuration
public class OpenApiConfig {
#Bean
public OpenAPI customOpenAPI(OpenApiProperties properties) {
var openApi = new OpenAPI()
.info(getInfo(properties));
return openApi;
}
private Info getInfo(OpenApiProperties properties) {
return new Info()
.title(properties.getProjectTitle())
.description(properties.getProjectDescription())
.version(properties.getProjectVersion())
.license(getLicense());
}
private License getLicense() {
return new License()
.name("Unlicense")
.url("https://unlicense.org/");
}
}
Currently, I have already done the ff:
Replace #Bean as #Singleton, Failed
Adding #Factory to the class, Failed
** The application compiles, but on run time the OpenApi definition is not set on the swagger ui
Micronaut generates the Open-API definition at the compilation time, so it's not possible to have dynamic properties. The only way is to set those values is to use annotations https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html

Using openapi.yaml in springdoc

I can customize OpenAPI from code.
Can I do same over openapi.yaml like swagger-petstore
I create simple springboot project with one #RestController.
I create openapi.yaml and copy it to /src/main/resources/.
But I see default values on open swagger-ui page.
This is available from the FAQ page in the spring-doc documentation.
See What is a proper way to set up Swagger UI to use provided spec.yml? and How can use custom json/yml file instead of generated one ? of the same page.
Example from the FAQ page
Turn off auto-generation in the project property file springdoc.api-docs.enabled=false
Put your yaml file in src/main/resources/static such as src/main/resources/static/myApiFile.yaml
Set the swagger-ui url for the file springdoc.swagger-ui.url=/myApiFile.yaml
Enable the minimal beans configuration
import org.springdoc.core.SpringDocConfigProperties;
import org.springdoc.core.SpringDocConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class SpringDocsConfiguration {
#Bean
SpringDocConfiguration springDocConfiguration() {
return new SpringDocConfiguration();
}
#Bean
public SpringDocConfigProperties springDocConfigProperties() {
return new SpringDocConfigProperties();
}
}
The code below is all what we needed to do to use openapi.yaml specification file instead of the default one that is generated from code.
Explanation:
org.springdoc.webflux.api.OpenApiResource is Controller that handles /v3/api-docs and /v3/api-docs.yaml endpoints. Swagger UI is using that endpoint to show swagger ui page - /swagger-ui.html. You can see the configuration when you hit /v3/api-docs/swagger-config endpoint.
org.springdoc.webflux.api.OpenApiResource bean is registered only if missing. You can see it in SpringDocWebFluxConfiguration. The method that creates the bean is annotated with #ConditionalOnMissingBean. So you just need to extend it and adjust OpenApi specification retrieval (see below).
org.springdoc.webflux.api.OpenApiResource is using getOpenApi() method to retrieve OpenAPI specification (by default the specification is generated based on the class annotation from code). So you just need to override getOpenApi() method and provide the specification from yaml file itself (getYamlMapper() method is also provided for you in the parent classes, so it's really that easy how it is in the file below)
You can see OpenApiResource is in webflux package because we use org.springdoc:springdoc-openapi-webflux-ui, Spring WebFlux. It is done similarly in Spring MVC.
Hope this helps :) When you hit /swagger-ui.html you should see the docs directly from .yaml spec. When you hit /v3/api-docs you should see the specs itself in JSON. When you hit /v3/api-docs.yaml you should see the specs itself in YAML. No Spring Configuration code is needed. Just the controller as you see below :)
Just to be clear. Our OpenAPI spec is in src/main/resources/openapi/api.yaml
package com.your.package;
...imports omitted for readability...
import org.springdoc.webflux.api.OpenApiResource;
#RestController
public class OpenApiController extends OpenApiResource {
#Value("classpath:openapi/api.yaml")
private Resource openAPIResource;
private OpenAPI openAPI;
public OpenApiController(ObjectFactory<OpenAPIBuilder> openAPIBuilderObjectFactory, AbstractRequestBuilder requestBuilder, GenericResponseBuilder responseBuilder, OperationBuilder operationParser, RequestMappingInfoHandlerMapping requestMappingHandlerMapping, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, SpringDocConfigProperties springDocConfigProperties, Optional<ActuatorProvider> actuatorProvider) {
super(openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, requestMappingHandlerMapping, operationCustomizers, openApiCustomisers, springDocConfigProperties, actuatorProvider);
}
#SneakyThrows
#PostConstruct
public void initOpenAPI() {
openAPI = getYamlMapper().readValue(openAPIResource.getInputStream(), OpenAPI.class);
}
#Override
protected synchronized OpenAPI getOpenApi() {
return openAPI;
}
}
If you need configuration file, you can have a look at the FAQ, documentation:
https://springdoc.org/faq.html#can-i-use-spring-property-with-swagger-annotations
And here is the link for code samples:
https://raw.githubusercontent.com/springdoc/springdoc-openapi/master/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app15/SpringDocApp15Test.java

Configuring Thymeleaf spring security 4 integration module using Yaml

I'm trying to use spring security 4 integration module (https://github.com/thymeleaf/thymeleaf-extras-springsecurity), Seems like I have to use java config and this can't be done in Yaml.
I'm not using any spring xml configuration. only Yaml and java configs.
Is there anyway to configure spring security integration module yet not mess up with thymeleaf auto configuration provided by Spring boot?
Right now I'm doing the configuration like this :
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
dialects.add(new org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect());
engine.setAdditionalDialects(dialects);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("classpath:/templates/");
resolver.setTemplateMode("HTML5");
return resolver;
}
But I'm getting java.lang.NoClassDefFoundError: org/thymeleaf/dialect/IProcessorDialect
Thank you in advance,

Swagger 2.0 where to declare Basic Auth Schema

How do I define basic authentication using Swagger 2.0 annotations and have it display in swagger UI.
In the resource I have:
#ApiOperation(value = "Return list of categories", response=Category.class, responseContainer="List", httpMethod="GET", authorizations = {#Authorization(value="basicAuth")})
public Response getCategories();
I looked here:
https://github.com/swagger-api/swagger-core/wiki/Annotations#authorization-authorizationscope
And it says "Once you've declared and configured which authorization schemes you support in your API, you can use these annotation to note which authorization scheme is required on a resource or a specific operation" But I can't find anything that talks about where to declare and configure the authorization schemes.
Update:
I found code on how to declare the schema, but I still do not see any information about the authentication schema in the UI. I'm not sure what I am missing
#SwaggerDefinition
public class MyApiDefinition implements ReaderListener {
public static final String BASIC_AUTH_SCHEME = "basicAuth";
#Override
public void beforeScan(Reader reader, Swagger swagger) {
}
#Override
public void afterScan(Reader reader, Swagger swagger) {
BasicAuthDefinition basicAuthDefinition = new BasicAuthDefinition();
swagger.addSecurityDefinition(BASIC_AUTH_SCHEME, basicAuthDefinition);
}
}
Using Springfox 2.6 annotations, you must first define Basic authentication as one of the security schemes when you set up the Docket in your configuration, like this:
List<SecurityScheme> schemeList = new ArrayList<>();
schemeList.add(new BasicAuth("basicAuth"));
return new
Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo)
.securitySchemes(schemeList)
...
Then you can use the Springfox annotations in your service to set Basic Auth for the operation for which you want to require authentication:
#ApiOperation(value = "Return list of categories", response=Category.class, responseContainer="List", httpMethod="GET", authorizations = {#Authorization(value="basicAuth")})
public Response getCategories();
I struggeled with this as well. In my case i used the swagger-maven-plugin. To solve this i added this within the maven plugin:
<securityDefinitions>
<securityDefinition>
<name>basicAuth</name>
<type>basic</type>
</securityDefinition>
</securityDefinitions>
After that i was able to add it on my resource like this:
#Api(value = "My REST Interface", authorizations = {#Authorization(value="basicAuth")})
The generated json included the security element for each endpoint:
"security":[{
"basicAuth" : []
}]
And the security definition:
"securityDefinitions" : {
"basicAuth" : {
"type" : "basic"
}
}
I hope this helps others as well.
You can use the #SwaggerDefinition
http://swagger.io/customizing-your-auto-generated-swagger-definitions-in-1-5-x/
or you can configure the swagger object directly, here's an example
http://www.programcreek.com/java-api-examples/index.php?source_dir=rakam-master/rakam/src/main/java/org/rakam/WebServiceRecipe.java

How to use swagger with OAuth API?

Is it possible to use swagger as a documentation/testing tool for APIs that use OAuth2? I don't see anything on the swagger site (or anywhere else for that matter). Every usage I've seen uses either an API key, HTTP basic, or cookies.
I have been working along the same lines. Swagger will accept any header or URL defined api key or token. Adding a validation helper to the api and app is a standard approach.
Oauth does require a HTML review and or login to start the handshake aouth process. This means that a swagger api will need to support a web interface for a standard login and scope acceptance. Rolling oauth into swagger results in a few logic loops, which long term are not easy to support.
A different approach we are exploring is the option to let the api handle and store access tokens for a number of different oauth providers; GitHub, twitter and Facebook. This might result in login loops as well.
late to the party here but oAuth support is now in 1.3.0-RC1 of swagger-core. The javascript library which can support oAuth was released yesterday in swagger-js. Finally, the swagger-ui is in develop phase, and will soon have a oAuth implicit and server flow.
the blog´s post http://developers-blog.helloreverb.com/enabling-oauth-with-swagger/ cited by #fehguy shows an example of java code to include the authorization data in json generated by swagger, however my question was where it should be included with app with Spring, JAXRS and CXF. I didn´t find it in CXF + JAXRS Sample :https://github.com/swagger-api/swagger-core/tree/master/samples/java-jaxrs-cxf
However, looking for a bit more and gotcha !
https://github.com/swagger-api/swagger-core/blob/master/samples/java-jersey-spring/src/main/resources/beans-asset-ws.xml
Is necessary include a Bean with a class called Bootstrap (extends HttpServlet) and a static block !
Opinion: Maybe it would be more “spring-friendly” loaded from annotations by SwaggerConfig Scanner in Rest class instead a static block in a servlet.
#Configuration
public class SwaggerConfiguration {
#Bean
#DependsOn("jaxRsServer") //org.apache.cxf.endpoint.Server bean
public ServletContextInitializer initializer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
BeanConfig scanner = (BeanConfig) ScannerFactory.getScanner();
Swagger swagger = scanner.getSwagger();
servletContext.setAttribute("swagger", swagger);
}
};
}
#Bean
public Feature swaggerFeature() {
XSwagger2Feature feature = new XSwagger2Feature();
return feature;
}
#Bean
public FilterRegistrationBean swaggerApiFilter() {
ApiOriginFilter filter = new ApiOriginFilter();
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registrationBean;
}
public static class XSwagger2Feature extends Swagger2Feature {
#Override
protected void addSwaggerResource(Server server) {
super.addSwaggerResource(server);
BeanConfig scanner = (BeanConfig) ScannerFactory.getScanner();
Swagger swagger = scanner.getSwagger();
swagger.securityDefinition("api_key", new ApiKeyAuthDefinition("api_key", In.HEADER));
swagger.securityDefinition("petstore_auth",
new OAuth2Definition()
.implicit("http://petstore.swagger.io/api/oauth/dialog")
.scope("read:pets", "read your pets")
.scope("write:pets", "modify pets in your account"));
}
}
}
IOdocs from mashery seems to support OAuth, but it's quite different from swagger (redis, node, etc.). It's available on github.

Resources