How do I create an OpenApi from a Rest interface? - spring-boot

I would like to map this rest interface in OpenApi?
Is there by chance a tool with which I can create an OpenApi from the rest interface without including this tool in my Spring Boot Application? Or is there a template I can use to build the interface myself in Openapi? I would be very grateful for an approach.
#GetMapping("/page")
public Page<FootballTeamLocationEntityView> getPageableFootballTeamList(#PageableDefault(value = 10) Pageable pageable) {
return footballTeamService.getFootballTeams(pageable);
}
I use OpenApi 3.0 and Spring Boot 2
UPDATE 1
default ResponseEntity<FootballTeamLocation> getPageableFootballTeamList(Pageable pageable) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "{ \"name\" : \"Westfalen-Stadion\", \"locZ\" : 5.962133212312, \"externalId\" : \"externalId\", \"locX\" : 6.02749381870403, \"id\" : 0, \"locY\" : 11.4658129805029452 }";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

Consider using springdoc. It is a recent library that is easier to use and way less error-prone than Springfox (the other option for Spring Boot apps). We moved to it 2 years ago and we are very glad we did. There is very good documentation and tutorials online for it:
https://springdoc.org/
https://www.baeldung.com/spring-rest-openapi-documentation
It is also very active and you usually get your issues answered very fast on the github page.

Related

Springdoc openapi migration from springfox

I am working on the migration of swagger spring fox to spring doc open api. I followed below link.
https://deepak-shinde.medium.com/migrating-from-springfox-swagger-2-to-springdoc-openapi-3-79a79757b8d1
Below version used.
spring_boot_version= "2.5.5"
springdoc_openapi_version= "1.6.0"
In gradle dependency mentioned as below
implementation "org.springdoc:springdoc-openapi-ui:$springdoc_openapi_version"
implementation "org.springdoc:springdoc-openapi-javadoc:$springdoc_openapi_version"
I defined rest controller.
#RestController
#RequestMapping("/v1")
#Slf4j
#Tag(name = "Master", description = "Master service API")
public class MasterController {
#Operation(summary = "Get test data",security = {
#SecurityRequirement(name = MasterConstant.HTTP_AUTH_SECURITY_SCHEME) }, tags = {
"Master" } ,description = " This method is used to get test data")
#PostMapping("/codes")
public ResponseEntity<MasterCodeResponse> getTestData()
}
application.properties
springdoc.swagger-ui.path=swagger-ui
springdoc.packages-to-exclude=com.master.persistence.*
springdoc.packages-to-scan=com.master.controller,com.common.controller // here * by default not working as its not listing apis
springdoc.api-docs.resolve-schema-properties=false
When i invoke v3/apidocs - Tags is coming empty. No controller name or description is displayed.
"openapi":"3.0.1",
"info":{
"title":"Test REST API",
"version":"1.0.0"
},
"servers":[
{
"url":"http://localhost:8082/master-service/",
"description":"Generated server url"
}
],
"security":[
{
"bearerAuth":[
]
}
],
"tags":[
{
}
],
Same way for operations tags is coming empty.
"/v1/codes":{
"post":{
"tags":[
null
],
"o
Below bean is defined
#Bean
public OpenAPI customizeOpenAPI() {
final String securitySchemeName = "bearerAuth";
return new OpenAPI().addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(
new Components().addSecuritySchemes(securitySchemeName,
new SecurityScheme().name(securitySchemeName).type(SecurityScheme.Type.HTTP)
.scheme("bearer").bearerFormat("JWT")))
.info(new Info().title("Test REST API").version("1.0.0"));
}
Please let me know how to get the summary of the opertaion and controller tags in swagger as well as in the apidocs yaml. Please advice if i am doing something wrong here.
There were some issue about tags, as you can see here
You should try to update springdoc-openapi to at least version 1.6.7.

Spring Cloud Gateway RouteLocator Java Code Can not get with specific route id

I have tried to custom RouteLocator in Spring Cloud Gateway with Java Code. I can see all the list of routes that registered with endpoint /actuator/gateway/routes but when I was trying to get the specific route in given id it is 404 /actuator/gateway/routes/auth-server.
This is what I was trying to invoke /actuator/gateway/routes
[
{
"route_id": "auth-server",
"route_object": {
"predicate": "org.springframework.cloud.gateway.support.ServerWebExchangeUtils$$Lambda$264/896945135#4e9d7b14"
},
"order": 0
},
{
"route_id": "song",
"route_object": {
"predicate": "org.springframework.cloud.gateway.support.ServerWebExchangeUtils$$Lambda$264/896945135#7d49ff95"
},
"order": 0
}
]
The one with specific route /actuator/gateway/routes/auth-server
http://localhost:8080/actuator/gateway/routes/auth-server
I got the result status code 404 not found.
This is java custom route configuration:
#Configuration
public class RouteConfiguration {
#Bean
RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
return routeLocatorBuilder.routes()
.route("auth-server", predicateSpec -> predicateSpec.path("/uaa/**").uri("lb://auth-service"))
.route("song", predicateSpec -> predicateSpec.path("/song/**").uri("lb/song-service"))
.build();
}
}
It should be given with auth-server route.
#soyphea That's a known issue, but I couldn't find the ticket back on GitHub. Can you create a bug report for this just to be sure: https://github.com/spring-cloud/spring-cloud-gateway/issues/new? Thanks for your great question!

Web API add openid scope to auth url for swagger/swashbuckle UI

We have a asp.net web api application which uses swagger/swashbuckle for it's api documentation. The api is secured by azure AD using oauth/openid-connect. The configuration for swagger is done in code:
var oauthParams = new Dictionary<string, string>
{
{ "resource", "https://blahblahblah/someId" }
};
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion(Version, Name);
c.UseFullTypeNameInSchemaIds();
c.OAuth2("oauth2")
.Description("OAuth2 Implicit Grant")
.Flow("implicit")
.AuthorizationUrl(
"https://login.microsoftonline.com/te/ourtenant/ourcustompolicy/oauth2/authorize")
.TokenUrl(
"https://login.microsoftonline.com/te/ourtenant/ourcustompolicy/oauth2/token");
c.OperationFilter<AssignOAuth2SecurityRequirements>();
})
.EnableSwaggerUi(c =>
{
c.EnableOAuth2Support(_applicationId, null, "http://localhost:49919/swagger/ui/o2c-html", "Swagger", " ", oauthParams);
c.BooleanValues(new[] { "0", "1" });
c.DisableValidator();
c.DocExpansion(DocExpansion.List);
});
When swashbuckle constructs the auth url for login, it automatically adds:
&scope=
However I need this to be:
&scope=openid
I have tried adding this:
var oauthParams = new Dictionary<string, string>
{
{ "resource", "https://blahblahblah/someId" },
{ "scope", "openid" }
};
But this then adds:
&scope=&someotherparam=someothervalue&scope=openid
Any ideas how to add
&scope=openid
To the auth url that swashbuckle constructs?
Many thanks
So, found out what the issue was, the offending code can be found here:
https://github.com/swagger-api/swagger-ui/blob/2.x/dist/lib/swagger-oauth.js
These js files are from a git submodule that references the old version of the UI.
I can see on lines 154-158 we have this code:
url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopes.join(scopeSeparator));
url += '&state=' + encodeURIComponent(state);
It basically adds scopes regardless of whether there are scopes or not. This means you cannot add scopes in the additionalQueryParams dictionary that gets sent into EnableOAuth2Support as you will get a url that contains 2 scope query params i.e.
&scope=&otherparam=otherparamvalue&scope=openid
A simple length check around the scopes would fix it.
I ended up removing swashbuckle from the web api project and added a different nuget package called swagger-net, found here:
https://www.nuget.org/packages/Swagger-Net/
This is actively maintained and it resolved the issue and uses a newer version of the swagger ui. The configuration remained exactly the same, the only thing you need to change is your reply url which is now:
http://your-url/swagger/ui/oauth2-redirect-html

Spring Boot - Change the location of the /health endpoint to /ping/me

I set the endpoints.health.path property to /ping/me. But I cannot access the endpoint using http://localhost:9000/ping/me
It only works with http://localhost:9000/health. What am I missing ?
Here is the code in app properties file.
#Configuration for Health endpoint
endpoints.health.id=health
endpoints.health.path=/ping/me
endpoints.health.enabled=true
endpoints.health.sensitive=false
#Manage endpoints
management.port=9000
management.health.diskspace.enabled=false
The response I get is :
{
"timestamp" : 1455736069839,
"status" : 404,
"error" : "Not Found",
"message" : "Not Found",
"path" : "/ping/me"
}
The Actuator became technology-agnostic in Spring Boot 2.0.0, so it's not tied to MVC now. Thus if you use Spring Boot 2.0.x, you can just add the following config properties:
# custom actuator base path: use root mapping `/` instead of default `/actuator/`
management.endpoints.web.base-path=
# override endpoint name for health check: `/health` => `/ping/me`
management.endpoints.web.path-mapping.health=/ping/me
If you don't override the management.endpoints.web.base-path, your health-check will be available at /actuator/ping/me.
The properties like endpoints.* became deprecated in Spring Boot 2.0.0.
See below for Spring Boot 2.*
https://stackoverflow.com/a/50364513/2193477
MvcEndpoints is responsible for reading endpoints.{name}.path configurations and somehow in its afterPropertiesSet method:
for (Endpoint<?> endpoint : delegates) {
if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {
EndpointMvcAdapter adapter = new EndpointMvcAdapter(endpoint);
String path = this.applicationContext.getEnvironment()
.getProperty("endpoints." + endpoint.getId() + ".path");
if (path != null) {
adapter.setPath(path);
}
this.endpoints.add(adapter);
}
}
It refusing from setting the endpoints.health.path, since isGenericEndpoint(...) is returning false for HealthEndpoint. Maybe it's a bug or something.
Update: Apparently this was a bug and got fixed in 1.3.3.RELEASE version. So, you can use the /ping/me as your health monitoring path in this version.

Why are my Spring Data repositories not found if moved into another package of a Spring Boot application?

I created a new project in Eclipse from these helpful spring examples (Import Getting Started Content). It is called "gs-accessing-data-rest-complete"
Reference and full Code can be found: spring-guides/gs-accessing-data-rest
When leaving the example unchanged, except using WAR instead of JAR packaging, everything works well. When calling $ curl http://localhost:8080/, I'll get an exposure of usable resources.
$ curl http://localhost:8080/
{
"_links" : {
"people" : {
"href" : "http://localhost:8080/name{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/alps"
}
}
But when moving the PersonRepository into another package, e.g. myRepos via Eclipse's Refactor-->Move command, a resource is not accessible anymore.
The response from curl is then:
$ curl http://localhost:8080/
{
"_links" : {
"profile" : {
"href" : "http://localhost:8080/alps"
}
}
}
As far as I understood, Spring scans for Repositories automatically. Because the main class uses #SpringBootApplication annotation, everything should be found by spring itself.
What am I missing? Do I have to add some special XML configuration file or add another Configuration Class somewhere? Or do I have to update application.properties in order to sth.?
Perhaps somebody has some useful experiences, she or he might share with me. Thank you.
Try specifying the base package to use when scanning for repositories by using this annotation on your config class: #EnableJpaRepositories(basePackages = "your.base.repository.package")

Resources