Search code examples
spring-bootquerydslspringdocspringdoc-openapi-ui

How to make QueryDSL Springdoc predicates work in Springboot 3 as it did in Springboot 2?


I utilized Springdocs 1 in Springboot 2 to generate my Swagger documentation. In addition, I employed the springdoc-openapi-data-rest library to generate the additional parameters necessary for @QuerydslPredicate instead of using the predicate object.

This was the dependency I was using with Springboot 2.

    <dependency>
        <!-- required swagger documentation of QueryDSL predicates -->
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-data-rest</artifactId>
        <version>1.6.15</version>
    </dependency>

Since I have upgraded to Springboot 3 and Springdoc 2, the swagger documentation for these parmeters are no longer being generated.

I now get:

swagger ui

My controller looks like this:

@RequiredArgsConstructor
@RestController
public class BookController {
    private final BookRepository bookRepository;
    @GetMapping("/books")
    @Operation(description = "Find all books.")
    public Iterable<Book> getBooks(@QuerydslPredicate(root = Book.class, bindings = BookRepository.class)  Predicate predicate) {
        return bookRepository.findAll(predicate);
    }
}

According to the Springdoc documentation, all I need to do is add springdoc-openapi-starter-webmvc-api

I have a minimal viable project on Github.

How do I make the project generate the parmeters for Book (id, name, bookNumber and otherField) as Springboot 2 and springdoc-openapi-data-rest did.


Solution

  • I did not get a answer for this, so it would still be nice to get one.

    Thinking about it, spring-doc performs a lot of magic that may aid in speed of development, but it may have unintended consequences if one of the columns in the database is not indexed.

    My solution is then to explicitly include the parameters that make sense.

    In the below example you still get all the benefits of QueryDSL by explicitly adding the all the parmeters except otherField.

    @GetMapping("/books")
    @Parameter(name ="predicate",  schema = @Schema(type = "string") ,hidden = true)
    @Parameter(name ="id",         schema = @Schema(type = "string"))
    @Parameter(name ="name",       schema = @Schema(type = "string"))
    @Parameter(name ="bookNumber", schema = @Schema(type = "string"), example = "9781234567897")
    //@Parameter(name ="otherField", schema = @Schema(type = "string"))
    @Operation(description = "Find all books.")
    public Iterable<Book> getBooks(@QuerydslPredicate(root = Book.class, bindings = BookRepository.class)  Predicate predicate) {
        return bookRepository.findAll(predicate);
    }
    

    You should also exclude the fields when defining your repository.

    public interface BookRepository extends QuerydslPredicateExecutor<Book>, QuerydslBinderCustomizer<QBook>, JpaRepository<Book, Integer> {
        @Override
        default void customize(QuerydslBindings bindings, QBook root){
           bindings.excluding(root.otherField);
        }
    }