OpenAPI-Swagger webflux Spring boot 3

I don't know why in my Swagger, I see only one of my two routes
@Configuration
public class IngredientRouter {

private static final String BASE_URL = "/ingredient/";

@RouterOperations({
@RouterOperation(path = BASE_URL, method = RequestMethod.GET, beanClass = IngredientService.class, beanMethod = "getAllIngredients"),
@RouterOperation(path = BASE_URL + "{name}", method = RequestMethod.GET,beanClass = IngredientService.class, beanMethod = "getAllIngredientsStartingWith")
})
@Bean
public RouterFunction<ServerResponse> ingredientRoute(IngredientHandler handler) {
return RouterFunctions
.route(GET(BASE_URL).and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredients)
.andRoute(GET(BASE_URL + "{name}").and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredientsStartingWith);
}
@Configuration
public class IngredientRouter {

private static final String BASE_URL = "/ingredient/";

@RouterOperations({
@RouterOperation(path = BASE_URL, method = RequestMethod.GET, beanClass = IngredientService.class, beanMethod = "getAllIngredients"),
@RouterOperation(path = BASE_URL + "{name}", method = RequestMethod.GET,beanClass = IngredientService.class, beanMethod = "getAllIngredientsStartingWith")
})
@Bean
public RouterFunction<ServerResponse> ingredientRoute(IngredientHandler handler) {
return RouterFunctions
.route(GET(BASE_URL).and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredients)
.andRoute(GET(BASE_URL + "{name}").and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredientsStartingWith);
}
31 Replies
JavaBot
JavaBot12mo ago
This post has been reserved for your question.
Hey @Santo! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here. 💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one. In case your post is not getting any attention, you can try to use /help ping. Warning: abusing this will result in moderative actions taken against you.
Santo
SantoOP12mo ago
Any idea please ? 😦
JavaBot
JavaBot12mo ago
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one. In case your post is not getting any attention, you can try to use /help ping. Warning: abusing this will result in moderative actions taken against you.
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one. In case your post is not getting any attention, you can try to use /help ping. Warning: abusing this will result in moderative actions taken against you.
dan1st
dan1st12mo ago
Can you show the corresponding controllers? what exactly does it show?
Santo
SantoOP12mo ago
You can find the source code here : https://github.com/Hunikel/Cocktail-API This is the router (equivalent to Controllers from what I understood with ReactiveProgramming) : https://github.com/Hunikel/Cocktail-API/blob/main/src/main/java/com/santo/cocktail/router/IngredientRouter.java
dan1st
dan1st12mo ago
Where did you specify the endpoints?
Santo
SantoOP12mo ago
RouterFunctions.route(GET(BASE_URL) ... Apparently this is the way today for reactive programming and endpoint declaration
dan1st
dan1st12mo ago
oh ok And what does the swagger UI look like?
Santo
SantoOP12mo ago
No description
Santo
SantoOP12mo ago
it seems to detect only one route
dan1st
dan1st12mo ago
which route are you missing? /ingredient?
@Configuration
public class IngredientRouter {

private static final String BASE_URL = "/ingredient";//I removed a / here

@RouterOperations({
@RouterOperation(path = BASE_URL, method = RequestMethod.GET, beanClass = IngredientService.class, beanMethod = "getAllIngredients"),
@RouterOperation(path = BASE_URL + "{name}", method = RequestMethod.GET,beanClass = IngredientService.class, beanMethod = "getAllIngredientsStartingWith")
})
@Bean
public RouterFunction<ServerResponse> ingredientRoute(IngredientHandler handler) {
return RouterFunctions
.route(GET(BASE_URL).and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredients)
.andRoute(GET(BASE_URL + "/{name}").and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredientsStartingWith);//I added a /here
}
@Configuration
public class IngredientRouter {

private static final String BASE_URL = "/ingredient";//I removed a / here

@RouterOperations({
@RouterOperation(path = BASE_URL, method = RequestMethod.GET, beanClass = IngredientService.class, beanMethod = "getAllIngredients"),
@RouterOperation(path = BASE_URL + "{name}", method = RequestMethod.GET,beanClass = IngredientService.class, beanMethod = "getAllIngredientsStartingWith")
})
@Bean
public RouterFunction<ServerResponse> ingredientRoute(IngredientHandler handler) {
return RouterFunctions
.route(GET(BASE_URL).and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredients)
.andRoute(GET(BASE_URL + "/{name}").and(accept(MediaType.APPLICATION_JSON)), handler::getAllIngredientsStartingWith);//I added a /here
}
Does that change anything?
Santo
SantoOP12mo ago
It miss all the other routes
No description
dan1st
dan1st12mo ago
I changed .andRoute(GET(BASE_URL + "{name}"). to .andRoute(GET(BASE_URL + "/{name}"). What if you completely remove the andRoute line (except the ;)?
Santo
SantoOP12mo ago
No description
Santo
SantoOP12mo ago
The swagger doesn't automatically detect the routes, I have to use the @Operation for it to detect it I'm pretty sad with this compared to when the detection was automatic with RestController :/ https://springdoc.org/features.html I tried their way here :
@RouterOperations({ @RouterOperation(path = "/getAllPersons", beanClass = PersonService.class, beanMethod = "getAll"),
@RouterOperation(path = "/getPerson/{id}", beanClass = PersonService.class, beanMethod = "getById"),
@RouterOperation(path = "/createPerson", beanClass = PersonService.class, beanMethod = "save"),
@RouterOperation(path = "/deletePerson/{id}", beanClass = PersonService.class, beanMethod = "delete") })
@Bean
public RouterFunction<ServerResponse> personRoute(PersonHandler handler) {
return RouterFunctions
.route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
.andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
.andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
.andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
}
@RouterOperations({ @RouterOperation(path = "/getAllPersons", beanClass = PersonService.class, beanMethod = "getAll"),
@RouterOperation(path = "/getPerson/{id}", beanClass = PersonService.class, beanMethod = "getById"),
@RouterOperation(path = "/createPerson", beanClass = PersonService.class, beanMethod = "save"),
@RouterOperation(path = "/deletePerson/{id}", beanClass = PersonService.class, beanMethod = "delete") })
@Bean
public RouterFunction<ServerResponse> personRoute(PersonHandler handler) {
return RouterFunctions
.route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
.andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
.andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
.andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
}
dan1st
dan1st12mo ago
Stack Overflow
How to use OpenApi annotations in spring-webflux RouterFunction end...
I am currently working on a project where I use spring functional web programming. I usually use annotations of swagger 2 in restController but with functional web programming I can not find where ...
dan1st
dan1st12mo ago
Does it work without RouterOperations or not?
Santo
SantoOP12mo ago
no, even separating the RouterFunctions into multiple methods with a routeroperation each, the problem persists
dan1st
dan1st12mo ago
Maybe you need to seet an operationId
dan1st
dan1st12mo ago
OpenAPI 3 Library for spring-boot
OpenAPI 3 Library for spring-boot
Library for OpenAPI 3 with spring boot projects. Is based on swagger-ui, to display the OpenAPI description.Generates automatically the OpenAPI file.
Santo
SantoOP12mo ago
it's already there :
@RouterOperation(path = BASE_URL, produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET, beanClass = IngredientService.class, beanMethod = "getAllIngredients",
operation = @Operation(operationId = "getAllIngredients", responses = {
@ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Ingredient.class)))})),
@RouterOperation(path = BASE_URL, produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET, beanClass = IngredientService.class, beanMethod = "getAllIngredients",
operation = @Operation(operationId = "getAllIngredients", responses = {
@ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Ingredient.class)))})),
dan1st
dan1st12mo ago
And does it work properly with the annotation present?
Santo
SantoOP12mo ago
nope Maybe it's a bug ... i'll try downgrading the version
dan1st
dan1st12mo ago
GitHub
springdoc-openapi-demos/springdoc-openapi-spring-boot-2-webflux/src...
Demo for OpenAPI 3 with spring-boot. Contribute to springdoc/springdoc-openapi-demos development by creating an account on GitHub.
dan1st
dan1st12mo ago
If you completely remove the second route, does the first one show up?
Santo
SantoOP12mo ago
this is the recommanded way for spring boot 3 😅 but yeah i'll try if i remove the second route the first one shows up yeah
dan1st
dan1st12mo ago
Do you have different operationIds for both routes?
Santo
SantoOP12mo ago
yes
dan1st
dan1st12mo ago
maybe try specifying the method inside the Operation as well
Santo
SantoOP12mo ago
Found the culprit ... I removed the following (beanClass and beanMethod everywhere) and now everything shows
beanClass = IngredientService.class, beanMethod = "getAllIngredients"
beanClass = IngredientService.class, beanMethod = "getAllIngredients"
Idk why ... normally that's what's written in the doc, or it's not up to date
JavaBot
JavaBot12mo ago
Post Closed
This post has been closed by <@231028402025529344>.

Did you find this page helpful?