web-dev-qa-db-fra.com

Utilisation de Pageable avec Spring Boot

J'ai un chemin qui est nécessaire pour informer la page, la taille, le décalage, etc., donc je mets un paramètre de méthode Pageable in:

Manette

@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RestController
@RequestMapping("/orders")
public class OrderController {


    private final @lombok.NonNull OrderService orderService;

    @GetMapping()
    public ResponseEntity<Page<Order>> getOrdersByFilter(@RequestParam(value = "start", required = false) Date start,
                                                         @RequestParam(value = "end", required = false) Date end,
                                                         @RequestParam(value = "status", required = false) StatusType status,
                                                         @RequestParam(value = "delayed", required = false) Boolean delayed,
                                                         Pageable page) {
        OrderValidator.filtersAreValid(start, end, status, delayed);
        PedidoStatus orderStatus = StatusConverter.toDomain(status);
        Page<OrderES> orders = orderService.getOrdersByFilter(start, end, orderStatus, delayed, page);

        if (orders != null && !orders.getContent().isEmpty()) {
            Page result = new PageImpl(OrderESConverter.listToInterface(orders.getContent()), orders.getPageable(), orders.getTotalElements());
            return new ResponseEntity<>(result, HttpStatus.OK);
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }
}

J'ai envoyé une demande à Postman pour application ( localhost: 8080/app/v1/orders? Status = CANCELED & page = 1 & size = 10 ) et j'ai reçu un NoSuchMethodException  

Erreur

{
    "timestamp": 1526309013493,
    "status": 500,
    "error": "Internal Server Error",
    "message": "No primary or default constructor found for interface org.springframework.data.domain.Pageable",
    "path": "/app/v1/orders"
}

Détails

2018-05-14 11:43:33.469 ERROR 10406 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/app/v1] threw exception [Request processing failed; nested exception is Java.lang.IllegalStateException: No primary or default constructor found for interface org.springframework.data.domain.Pageable] with root cause

Java.lang.NoSuchMethodException: org.springframework.data.domain.Pageable.<init>()
    at Java.lang.Class.getConstructor0(Class.Java:3082) ~[na:1.8.0_151]

Le plus gros problème est le suivant: OrderController a besoin d'un bean orderService. Je ne peux donc pas créer de constructeur par défaut sans paramètre et laisser orderService nul. 

Configuration

@EntityScan(basePackages = {"br.com.app.models.interfaces", "br.com.app.models.domains"})
@ComponentScan(basePackages = {"br.com.app.api.*"})
@EnableJpaRepositories
@SpringBootApplication
@EnableSpringDataWebSupport
public class OrderApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(OrderApplication.class, args);
    }

}

pom.xml (orders-api)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>br.com.app</groupId>
    <artifactId>orders-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>orders-api</name>
    <description>Orders API</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <Java.version>1.8</Java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.8.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-Java-sdk</artifactId>
            <version>1.9.0</version>
        </dependency>

        <dependency>
            <groupId>br.com.app</groupId>
            <artifactId>app-models</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>br.com.apputils</groupId>
            <artifactId>api-utils</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
        </dependency>

        <!--<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>-->

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <requiresUnpack>
                        <dependency>
                            <groupId>br.com.app</groupId>
                            <artifactId>app-models</artifactId>
                        </dependency>
                    </requiresUnpack>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

pom.xml (apputils)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>br.com.apputils</groupId>
    <artifactId>api-utils</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>api-utils</name>
    <description>Utils classes for APIs development</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <Java.version>1.8</Java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-Java-sdk</artifactId>
            <version>1.9.0</version>
        </dependency>

        <dependency>
            <groupId>br.com.app</groupId>
            <artifactId>app-models</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

pom.xml (modèles d'application)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>br.com.app</groupId>
    <artifactId>app-models</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.2.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.13.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>org.jboss.logging</groupId>
                    <artifactId>jboss-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.4</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.4</version>
        </dependency>

    </dependencies>

</project>

Qu'est-ce que je peux faire? 

4
Daniela Morais

vous devriez utiliser le @PagebleDefault annotation, par exemple

public ResponseEntity<Page<Order>> getOrdersByFilter(@RequestParam(value = "start", required = false) Date start,
                                                     @RequestParam(value = "end", required = false) Date end,
                                                     @RequestParam(value = "status", required = false) StatusType status,
                                                     @RequestParam(value = "delayed", required = false) Boolean delayed,
                                                     @PageableDefault(size = 10, direction = Sort.Direction.DESC, sort = "someField") Pageable page) {
2
Vyncent

J'ai eu le même problème. Comme Kimosabe dit, c'est un problème Swagger. J'ai corrigé en ajoutant les ressources swagger sur le gestionnaire de ressources. Apparemment, Springfox Swagger et Spring Boot 2 ont quelques problèmes. Voici la classe:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
        .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
        .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}
1
Raphael Amoedo

C'est le problème de Swagger, voir ceci .

Je l'ai fait pour mon projet:

    @GetMapping("/orders")
    public ResponseEntity getAllOrders(@RequestParam(value = "page", defaultValue = "0", required = false) Integer page,
                                       @RequestParam(value = "size", defaultValue = "30", required = false) Integer size,
                                       @RequestParam(value = "sort", defaultValue = "orderNumber", required = false) String sort) {
        return execute(() -> service.getAllOrders(PageRequest.of(page, size, ASC, sort)));
    }

J'espère que ça vous aide.

0
Kimosabe