SpringBoot-OpenAPI: How to add default header to all requests - java

I have created an OpenAPI spec as below.
#Bean
public OpenAPI customOpenAPI() {
final String securitySchemeName = "Authorization";
final String apiTitle = "My Service";
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(
new Components()
.addSecuritySchemes(securitySchemeName,
new SecurityScheme()
.name(securitySchemeName)
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)))
.info(new Info().title(apiTitle));
}
Now, I want OpenAPI UI to add one extra header MyCustomHeader:MyValue to all the requests. How can I achieve this?

You can define OpenApiCustomiser bean as follows:
#Bean
public OpenApiCustomiser openApiCustomizer() {
return openApi ->
openApi.getPaths().values().stream()
.flatMap(pathItem -> pathItem.readOperations().stream())
.forEach(
operation ->
operation.addParametersItem(
new HeaderParameter()
.schema(new StringSchema()._default("MyValue"))
.name("MyCustomHeader")));
}
The bean adds the MyCustomHeader header to all endpoints with MyValue
as default value.

Related

In Spring Cloud gateway API, how add dynamic headers or query parameter?

I am working on application in which I am using Spring Cloud gateway and in front-end Angular 2, for login I am using Keyclock SSO.
However, after getting logged in I need to send some user information in front-end in some encrypted format, either via headers or query parameters. For that in Spring Cloud gateway I have written below code but it's not working.
This is my custom GlobalFilter where I try to add it headers and parameters but in front-end I am not getting it.
#Component
public class InterceptorFilterGatewayFilterFactory extends AbstractGatewayFilterFactory<InterceptorFilterGatewayFilterFactory.Config> {
public InterceptorFilterGatewayFilterFactory() {
super(Config.class);
}
#Override
public Config newConfig() {
return new Config();
}
public static class Config {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
#Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest sr = exchange.getRequest();
Mono var10000 = exchange.getPrincipal().filter((principal) -> principal instanceof OAuth2AuthenticationToken)
.map(p -> p).map((p) -> {
LinkedHashSet<URI> attr = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
ServerHttpRequest request = exchange.getRequest();
// Here I try to add query parameter
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.put("e", Collections.singletonList(toHexString(ja.toString().getBytes())));
URI newUri = UriComponentsBuilder.fromUri(request.getURI())
.replaceQueryParams(unmodifiableMultiValueMap(queryParams))
.build(true).toUri();
ServerHttpRequest updatedRequest = exchange.getRequest().mutate().uri(newUri)
.build();
// Here I add header
updatedRequest.mutate().header("e", toHexString(ja.toString().getBytes())).build();
return exchange.mutate().request(updatedRequest).build();
}).defaultIfEmpty(exchange).flatMap(chain::filter);
}
return var10000;
};
}
And in application yml file I am providing route as follow:
- id: appDepartmentWise
predicates:
- Path=/app/*/sso_login
- Method=GET,POST
uri: http://localhost:9000/app/
filters:
- PreserveHostHeader
- RewritePath=/.*, /app/index.html
- InterceptorFilter
- AddRequestParameter=e,*
What configuration is missing, and how to add dynamic Header or Query Parameters?
In case if it helps any one to add dynamic query parameter and redirect page you can do it using below code:
#GetMapping("/user")
public Mono<Void> sendRedirect(ServerWebExchange exchange, Principal p) {
// Here we can can create string which can have dynamic parameters
String responseData = "e="+p..getName();
return Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.FOUND);
// this used to get the base URL.
UriComponents uriComponents = UriComponentsBuilder.fromUri(exchange.getRequest().getURI()).replacePath(exchange.getRequest().getPath().contextPath().value()).replaceQuery((String)null).fragment((String)null).build();
// As below we can re-generate the URL and redirect it.
response.getHeaders().setLocation(URI.create(uriComponents.toUriString()+"/app/Dept"+"/sso_login?"+responseData));
});
}

Programmatically call spring cloud config actuator/env post endpoint in spring boot application

I am using spring cloud config in my spring boot application, I am trying to update the property value through actuator/env post endpoint.
Here is my code:
#Service
public class ActuatorRefreshService {
private final String inventoryModeKey = "inventory.initial.mode";
private WebClient webClient = WebClient.builder().build();
#Autowired
public ActuatorRefreshService() {
}
public void refreshStatus(String latestMode) {
Map<String, String> bodyMap = new HashMap();
bodyMap.put("name",inventoryModeKey);
bodyMap.put("value",latestMode);
webClient.post().uri("/actuator/env")
.header(HttpHeaders.CONTENT_TYPE, String.valueOf(MediaType.APPLICATION_JSON))
.body(Mono.just(bodyMap), Map.class).retrieve().onStatus(HttpStatus::isError, clientResponse -> {
return Mono.error(new Exception("error"));
}).bodyToMono(String.class);
System.out.println("call actuator endpoint to update the value");
}
}
When I am calling my rest endpoint that calls this refreshStatus method. The api returns me 200 status. After that I hit localhost:8080/actuator/refresh. When I check the updated value , it shows this __refreshAll__.
I have no idea why is this happening?? Any help would be appreciated.
Note :* When I hit the endpoint localhost:8080/actuator/env from postman and refresh then it updates the property.*
I tried with localhost:8080/actuator/busenv bus endpoint as well but still no luck.
Anyone tried this kind of requirement?
I was able to call this api localhost:8080/actuator/busenv programmatically in spring boot using RestTemplate in spring. It is refreshing the configuration as well in application context. I am not sure why it didn't work with WebClient though.
posting the answer if anyone else is looking for the same requirement.
Please find the below code
#Service
public class ActuatorRefreshService {
private final String inventoryModeKey = "inventory.initial.mode";
#Autowired
public ActuatorRefreshService() {
}
public void refreshInventoryMode(String latestMode) {
Map<String, String> bodyMap = new HashMap();
bodyMap.put("name",inventoryModeKey);
bodyMap.put("value",latestMode);
final String url = "http://localhost:8080/actuator/busenv";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers
.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<Object> entity = new HttpEntity<>(bodyMap, headers);
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
System.out.println("call actuator endpoint to update the value ");
}
}

Using BodyInserters to pass parameter with webClient

There is my code.
public Mono<RespDto> function(TransReqDto1 reqDto1, TransReqDto2 reqDto2, String token) {
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("TransReqDto1", reqDto1);
builder.part("TransReqDto2", reqDto2);
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
LinkedMultiValueMap map = new LinkedMultiValueMap();
map.add("TransReqDto1", reqDto1);
map.add("TransReqDto2", reqDto2);
return
client.post()
.uri("/api")
.body(BodyInserters.fromValue(reqDto1))
.headers(h -> h.setBearerAuth(token.split(" ")[1]))
.retrieve()
.bodyToMono(RespDto.class);
}
My probelm is that I need to send both reqDto1 & reqDto2. I've successfully sent reqDto1 with the code above but I can't figure out a way to send two objects.
Tried MultipartBodybuild and MultiValueMap but both are returning error from the target API. Please give me some hints!! Thank you
Here is the API I am trying to call!
#PostMapping("")
#ApiOperation(value = "test", notes = "test")
public Mono<?> transPost(#Valid #RequestBody TransReqDto1 reqDto1,
#Valid #RequestBody TransReqDto2 reqDto2) {
return testService.function(reqDto1, reqDto2);
}
You cannot use two #RequestBody. It can bind to a single object only. The expected way to do that is to create a wrapper DTO containing all the relevant data:
public class TransReqDto {
private TransReqDto1 transReqDto1;
private TransReqDto2 transReqDto2;
//...
}

How to prevent multiple authentication calls via WebClient

The following code will fetch 20 devices and will consume some data from an online service.
In order to use the online service the WebClient need to get access token (authorization-grant-type=client_credentials)
spring.security.oauth2.client.registration.web.client-id=xxxx
spring.security.oauth2.client.registration.web.client-secret=xxxx
spring.security.oauth2.client.registration.web.scope=xxxx
spring.security.oauth2.client.registration.web.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.web.token-uri=https://xxxx
Config:
#Configuration
public class Config {
#Autowired
public ClientRegistrationRepository clientRegistrationRepository;
#Bean
public WebClient webClient(ExchangeFilterFunction getOAuth2FilterFunction) {
logger.info("** start webClient **");
return WebClient.builder().filter(getOAuth2FilterFunction).build();
}
#Bean
public ExchangeFilterFunction getOAuth2FilterFunction(ReactiveClientRegistrationRepository clientRegistrationRepository) {
logger.info("** start getOAuth2FilterFunction **");
InMemoryReactiveOAuth2AuthorizedClientService authorizedClientService = new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(new ClientCredentialsReactiveOAuth2AuthorizedClientProvider());
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2FilterFunction = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth2FilterFunction.setDefaultClientRegistrationId("web");
return oauth2FilterFunction;
}
#Bean
public ReactiveClientRegistrationRepository clientRegistrations() {
logger.info("** start clientRegistrations **");
ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId("web");
return new InMemoryReactiveClientRegistrationRepository(clientRegistration);
}
WebClient:
private void getData(List<Device> initlist) {
logger.info("** start getDeviceData **");
List<Mono<DeviceDto>> jsonDeviceList = initlist.stream()
.map(device -> webClient.post().uri(infoUri)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.body(Mono.just(device.getMacAddress()),String.class)
.attributes(ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId("web"))
.retrieve()
.bodyToMono(DeviceDto.class))
.collect(Collectors.toList());
ObjectMapper mapper = new ObjectMapper();
Flux<DeviceDto> mergedMonos = Flux.fromIterable(jsonDeviceList).flatMapSequential(Function.identity());
mergedMonos.map(device -> mapper.valueToTree(device)).collectList().subscribe(list -> {
generateCsv(list);
});
}
The problem is that for each service request there will be an equivalent access token request from the authentication server. So for all 20 devices in the list the WebClient will request access token 20 times.
How can I change this to have only one call rather then 20 ?
Thank you
What #Toerktumlare said is right. If you want to call oauth server once, you just need to cache the access_token in memory or redis at first request and then use the same access_token before it is expired.
WebClient webClient = WebClient.builder()
.defaultHeader("Authorization", "Bearer " + getAccessToken())
.build();
private String getAccessToken() {
// get access_token from redis
// if expiring, it will return null
String access_token = (String) redisTemplate.opsForValue().get("access_token");
if (null != access_token) {
return access_token;
}
// get access_token from oauth server again and cache it into redis
return getAccessTokenFromOauthServer();
}

Unable to link Swagger-ui to my swagger Spring mvc project

I'm currently creating an API Rest using Eclipse, Spring Framework MVC, and I just added to my project swagger. I can access the json result of swagger but I need to add swagger ui.
Here are all my files creating for swagger-springmvc:
WebAppInitializer.java
public class WebAppInitializer implements WebApplicationInitializer {
private AnnotationConfigWebApplicationContext ctx = null;
#Override
public void onStartup(final ServletContext sc) throws ServletException {
System.setProperty("spring.profiles.active", "web");
// Create the 'root' Spring application context
ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringBaseWebConfiguration.class,
SpringSwaggerConfiguration.class);
// Manages the lifecycle
sc.addListener(new ContextLoaderListener(ctx));
sc.addListener(new ContextCleanupListener());
// Spring WebMVC
ServletRegistration.Dynamic springWebMvc = sc.addServlet("ws",
new DispatcherServlet(ctx));
springWebMvc.setLoadOnStartup(1);
springWebMvc.addMapping("/ws/*");
springWebMvc.setAsyncSupported(true);
}
#PreDestroy
protected final void cleanup() {
if (ctx != null) {
ctx.close();
}
}
}
SpringSwaggerConfiguration.java
public class SpringSwaggerConfiguration {
public static final List<String> DEFAULT_INCLUDE_PATTERNS = Arrays
.asList(new String[]{"/com/sa/rnd/dark/resources/.*"});
public static final String SWAGGER_GROUP = "ApiDark";
public static final String RELATIVE_GROUP = "ApiDark";
#Autowired
private SpringSwaggerConfig springSwaggerConfig;
/**
* Adds the jackson scala module to the MappingJackson2HttpMessageConverter
* registered with spring Swagger core models are scala so we need to be
* able to convert to JSON Also registers some custom serializers needed to
* transform swagger models to swagger-ui required json format
*/
#Bean
public JacksonScalaSupport jacksonScalaSupport() {
final JacksonScalaSupport jacksonScalaSupport = new JacksonScalaSupport();
// Set to false to disable
jacksonScalaSupport.setRegisterScalaModule(true);
return jacksonScalaSupport;
}
/**
* Global swagger settings
*/
#Bean
public SwaggerGlobalSettings swaggerGlobalSettings() {
final SwaggerGlobalSettings swaggerGlobalSettings = new SwaggerGlobalSettings();
swaggerGlobalSettings.setGlobalResponseMessages(springSwaggerConfig
.defaultResponseMessages());
swaggerGlobalSettings.setIgnorableParameterTypes(springSwaggerConfig
.defaultIgnorableParameterTypes());
return swaggerGlobalSettings;
}
/**
* API Info as it appears on the swagger-ui page
*/
private ApiInfo apiInfo() {
return new ApiInfo(
"Swagger Spring MVC for Dark Api",
"Sample application demonstrating how to use swagger-springmvc in a no-XML environment.",
"http://en.wikipedia.org/wiki/Terms_of_service",
"michael#laccetti.com", "Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0.html");
}
/**
* Configure a SwaggerApiResourceListing for each swagger instance within
* your app. e.g. 1. private 2. external apis Required to be a spring bean
* as spring will call the postConstruct method to bootstrap swagger
* scanning.
*
* #return
*/
#Bean
public SwaggerApiResourceListing swaggerApiResourceListing() {
// The group name is important and should match the group set on
// ApiListingReferenceScanner
// Note that swaggerCache() is by DefaultSwaggerController to serve the
// swagger json
final SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(
springSwaggerConfig.swaggerCache(), SWAGGER_GROUP);
// Set the required swagger settings
swaggerApiResourceListing
.setSwaggerGlobalSettings(swaggerGlobalSettings());
// Supply the API Info as it should appear on swagger-ui web page
swaggerApiResourceListing.setApiInfo(apiInfo());
// Use the default path provider
swaggerApiResourceListing.setSwaggerPathProvider(springSwaggerConfig
.defaultSwaggerPathProvider());
// Global authorization - see the swagger documentation
swaggerApiResourceListing.setAuthorizationTypes(authorizationTypes());
// Sets up an auth context - i.e. which controller request paths to
// apply global auth to
swaggerApiResourceListing
.setAuthorizationContext(authorizationContext());
// Every SwaggerApiResourceListing needs an ApiListingReferenceScanner
// to scan the spring request mappings
swaggerApiResourceListing
.setApiListingReferenceScanner(apiListingReferenceScanner());
return swaggerApiResourceListing;
}
#Bean
/**
* The ApiListingReferenceScanner does most of the work.
* Scans the appropriate spring RequestMappingHandlerMappings
* Applies the correct absolute paths to the generated swagger resources
*/
public ApiListingReferenceScanner apiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner = new ApiListingReferenceScanner();
// Picks up all of the registered spring RequestMappingHandlerMappings
// for
// scanning
apiListingReferenceScanner
.setRequestMappingHandlerMapping(springSwaggerConfig
.swaggerRequestMappingHandlerMappings());
// Excludes any controllers with the supplied annotations
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig
.defaultExcludeAnnotations());
//
apiListingReferenceScanner
.setResourceGroupingStrategy(springSwaggerConfig
.defaultResourceGroupingStrategy());
// Path provider used to generate the appropriate uri's
apiListingReferenceScanner
.setSwaggerPathProvider(relativeSwaggerPathProvider());
// Must match the swagger group set on the SwaggerApiResourceListing
apiListingReferenceScanner.setSwaggerGroup(SWAGGER_GROUP);
// Only include paths that match the supplied regular expressions
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
return apiListingReferenceScanner;
}
private List<AuthorizationType> authorizationTypes() {
final List<AuthorizationType> authorizationTypes = new ArrayList<>();
authorizationTypes.add(new BasicAuth());
return authorizationTypes;
}
#Bean
public AuthorizationContext authorizationContext() {
final List<Authorization> authorizations = newArrayList();
AuthorizationScope authorizationScope = new AuthorizationScope(
"global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[]{authorizationScope};
authorizations.add(new Authorization("basic", authorizationScopes));
AuthorizationContext authorizationContext = new AuthorizationContext.AuthorizationContextBuilder(
authorizations).withIncludePatterns(DEFAULT_INCLUDE_PATTERNS)
.build();
return authorizationContext;
}
// Relative path example
#Bean
public SwaggerApiResourceListing relativeSwaggerApiResourceListing() {
SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(
springSwaggerConfig.swaggerCache(), RELATIVE_GROUP);
swaggerApiResourceListing
.setSwaggerGlobalSettings(swaggerGlobalSettings());
swaggerApiResourceListing
.setSwaggerPathProvider(relativeSwaggerPathProvider());
swaggerApiResourceListing
.setApiListingReferenceScanner(relativeApiListingReferenceScanner());
return swaggerApiResourceListing;
}
#Bean
public ApiListingReferenceScanner relativeApiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner =
new ApiListingReferenceScanner();
apiListingReferenceScanner
.setRequestMappingHandlerMapping(springSwaggerConfig
.swaggerRequestMappingHandlerMappings());
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig
.defaultExcludeAnnotations());
apiListingReferenceScanner
.setResourceGroupingStrategy(springSwaggerConfig
.defaultResourceGroupingStrategy());
apiListingReferenceScanner
.setSwaggerPathProvider(relativeSwaggerPathProvider());
apiListingReferenceScanner.setSwaggerGroup(RELATIVE_GROUP);
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
return apiListingReferenceScanner;
}
#Bean
public SwaggerPathProvider relativeSwaggerPathProvider() {
return new ApiRelativeSwaggerPathProvider();
}
private class ApiRelativeSwaggerPathProvider extends
DefaultSwaggerPathProvider {
#Override
public String getAppBasePath() {
return "/ApiDark/ws";
}
}
}
SpringBaseWebConfiguration.java :
#Configuration
#ComponentScan(basePackages = {"com.sa.rnd.dark.resources",
"com.mangofactory.swagger.configuration",
"com.mangofactory.swagger.controllers"})
#EnableWebMvc
public class SpringBaseWebConfiguration extends WebMvcConfigurerAdapter {
private List<HttpMessageConverter<?>> messageConverters;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/api-docs").setViewName("redirect:index.html");
}
/**
* The message converters for the content types we support.
*
* #return the message converters; returns the same list on subsequent calls
*/
private List<HttpMessageConverter<?>> getMessageConverters() {
if (messageConverters == null) {
messageConverters = new ArrayList<>();
final MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
final ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
mappingJacksonHttpMessageConverter.setObjectMapper(mapper);
messageConverters.add(mappingJacksonHttpMessageConverter);
}
return messageConverters;
}
#Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
converters.addAll(getMessageConverters());
}
#Bean
public static PropertyPlaceholderConfigurer swaggerProperties() {
final PropertyPlaceholderConfigurer swaggerProperties = new PropertyPlaceholderConfigurer();
swaggerProperties.setLocation(new ClassPathResource(
"swagger.properties"));
return swaggerProperties;
}
}
Here are my 3 files to add swagger to my project, atm I just decide to check just 1 method which is :
#Api(description = "CRUD services for containers working with WebDark",
value = "CRUD Services Containers")
#RestController
#RequestMapping(value = "/container", produces = MediaType.APPLICATION_JSON_VALUE)
public class ContainersResources {
/**
* Find all children of a container.
*
* #param containerId
* ID of the parent container
* #return ApiResponse
*/
#ApiOperation(response = ApiResponse.class,
value = "Find all children containers of one container",
notes = "Find all children containers of one container")
#RequestMapping(method = RequestMethod.GET, value = "/{containerId}")
#ResponseStatus(HttpStatus.OK)
public #ResponseBody ApiResponse<List<ContainerModel>> getContainerChildren(
#ApiParam(required = true, value = "The id of the container parent",
name = "containerId")#PathVariable("containerId") final String containerId) {
ApiResponse<List<ContainerModel>> result = new ApiResponse<>();
result.setMessage("getContainerChildren method of new Api Dark");
result.setSuccess(true);
result.setTotal(9000);
return result;
}
}
My results : I can access the following url http://localhost:8080/ApiDark/ws/api-docs but I get the json value like :
{"apiVersion":"1","swaggerVersion":"1.2","authorizations":{"basicAuth":{"type":"basicAuth"}},"info":{"title":"Swagger Spring MVC for Dark Api","description":"Sample application demonstrating how to use swagger-springmvc in a no-XML environment.","termsOfServiceUrl":"http://en.wikipedia.org/wiki/Terms_of_service","contact":"michael#laccetti.com","license":"Apache 2.0","licenseUrl":"http://www.apache.org/licenses/LICENSE-2.0.html"}}
That's why I decided to add swagger-ui. I add the content of dist folder (taken from swagger-ui) to my src/main/webapp folder. And modify the content of index.html to point to my url :
<script type="text/javascript">
$(function () {
window.swaggerUi = new SwaggerUi({
url: "http://localhost:8080/ApiDark/ws/api-docs.json",
dom_id: "swagger-ui-container",
But I can't access to swagger-ui interface, I just have the json result... Need help to make it work please !
This issue seems old but just to share, with the recent version of swagger-springmvc and springmvc-ui, it has become very easy and less complicated to integrate swagger & swagger-ui with your web service to see in production REST api documentation.
#EnableSwagger annotation is added that enables swagger-springmvc out of the box. The generated swagger json Resource Listing can be accessed at /api-docs.
You may refer to following link for the steps on integrating swagger-springmvc and swagger-ui with your spring mvc project.
https://github.com/martypitt/swagger-springmvc
What do you mean by 'I can't access to swagger-ui interface'?
In my case, my browser did not load the index.html (I think it throw 404), which I had in a subfolder together with all the dist files: webapp/doc/index.html. I had to exclude the subfolder from the servlet mapping in web.xml as I shortly described here:
Java swagger with JaxRS throwing errors
My web.xml snippet looks like this finally:
<servlet-mapping>
<servlet-name>My application servlet-name</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/doc/*</url-pattern>
</servlet-mapping>
(why this works see here:http://blog.ericdaugherty.com/2010/02/excluding-content-from-url-pattern-in.html)
Hope that helps!

Categories

Resources