zandero / rest.vertx

A JAX-RS like annotation processor for vert.x verticals and more
Apache License 2.0
160 stars 28 forks source link

jakarta.validation.Validator can't be registered #156

Open stefanvettiger opened 7 hours ago

stefanvettiger commented 7 hours ago

I have an instance of a jakarta Validator and I want to register it with the RestRouter.validateWith() method. It's not compatible with the javax Validator class. Is there a way to handle this?

I'm using Spring 3.3.2, Hibernate Core 6.5.2.Final and Hibernate Validator 8.0.1.Final.

drejc commented 6 hours ago

Hi @stefanvettiger can you please provide a code snippet / example of what are you doing.

stefanvettiger commented 5 hours ago

2024-11-14_19h44_16

This pom.xml is working

<?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>

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

    <properties>
        <java.version>21</java.version>
        <vertx.version>4.4.5</vertx.version>
        <hibernate.version>5.6.4.Final</hibernate.version>
    </properties>

    <dependencies>

        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </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-validation</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>

        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-junit5</artifactId>
            <version>4.2.5</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>${vertx.version}</version>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>

        <dependency>
            <groupId>com.zandero</groupId>
            <artifactId>rest.vertx</artifactId>
            <version>1.1.1</version>
        </dependency>

    </dependencies>
</project>

This WebserverVerticle.java is working

package swiss.avm.cma.backend.rest.config;

import com.zandero.rest.RestRouter;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import swiss.avm.cma.backend.CmaBackendApplication;
import swiss.avm.common.rest.controller.IRestController;

import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class WebserverVerticle extends AbstractVerticle {

    private static final Logger LOGGER = LoggerFactory.getLogger(CmaBackendApplication.class);
    private final int serverPort;
    private final List<IRestController> restControllers;

    public WebserverVerticle(int serverPort) {
        this.serverPort = serverPort;
        this.restControllers = new ArrayList<>();
    }

    public WebserverVerticle with(List<IRestController> restControllers) {
        this.restControllers.addAll(restControllers);
        return this;
    }

    @Override
    public void start(Promise<Void> startPromise) throws Exception {
        super.start();

        Router router = Router.router(vertx);
        Set<String> allowedHeaders = new HashSet<>();

        allowedHeaders.add("Content-Type");
        allowedHeaders.add("Accept");
        allowedHeaders.add("Accept-Language");
        allowedHeaders.add("Authorization");

        RestRouter.enableCors(router,
                ".+",
                false,
                600,
                allowedHeaders,
                HttpMethod.GET,
                HttpMethod.POST,
                HttpMethod.PUT,
                HttpMethod.PATCH,
                HttpMethod.DELETE,
                HttpMethod.OPTIONS);

        HibernateValidatorConfiguration configuration = Validation
                .byProvider(HibernateValidator.class)
                .configure();

        Validator validator = configuration.buildValidatorFactory().getValidator();
        RestRouter.validateWith(validator);

        BodyHandler bodyHandler = BodyHandler.create("upload-folder")
                .setDeleteUploadedFilesOnEnd(true);
        RestRouter.setBodyHandler(bodyHandler);

        for (IRestController controller : restControllers) {
            RestRouter.register(router, controller);
        }

        HttpServer httpServer = vertx.createHttpServer().requestHandler(router);
        httpServer.listen(serverPort);
        System.out.println("Server Started");
        startPromise.complete();
        LOGGER.info("Webserver Verticle Started");
    }
}

This pom.xml is NOT working

<?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>

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

    <properties>
        <java.version>21</java.version>
        <vertx.version>4.5.9</vertx.version>
    </properties>

    <dependencies>

        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </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-validation</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>

        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-junit5</artifactId>
            <version>4.2.5</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>${vertx.version}</version>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>

        <dependency>
            <groupId>com.zandero</groupId>
            <artifactId>rest.vertx</artifactId>
            <version>1.1.1</version>
        </dependency>

    </dependencies>    
</project>

This WebserverVerticle.java is NOT working

package swiss.avm.cma.backend.rest.config;

import com.zandero.rest.RestRouter;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import swiss.avm.cma.backend.CmaBackendApplication;
import swiss.avm.common.rest.controller.IRestController;

import jakarta.validation.Validation;
import jakarta.validation.Validator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class WebserverVerticle extends AbstractVerticle {

    private static final Logger LOGGER = LoggerFactory.getLogger(CmaBackendApplication.class);
    private final int serverPort;
    private final List<IRestController> restControllers;

    public WebserverVerticle(int serverPort) {
        this.serverPort = serverPort;
        this.restControllers = new ArrayList<>();
    }

    public WebserverVerticle with(List<IRestController> restControllers) {
        this.restControllers.addAll(restControllers);
        return this;
    }

    @Override
    public void start(Promise<Void> startPromise) throws Exception {
        super.start();

        Router router = Router.router(vertx);
        Set<String> allowedHeaders = new HashSet<>();

        allowedHeaders.add("Content-Type");
        allowedHeaders.add("Accept");
        allowedHeaders.add("Accept-Language");
        allowedHeaders.add("Authorization");

        RestRouter.enableCors(router,
                ".+",
                false,
                600,
                allowedHeaders,
                HttpMethod.GET,
                HttpMethod.POST,
                HttpMethod.PUT,
                HttpMethod.PATCH,
                HttpMethod.DELETE,
                HttpMethod.OPTIONS);

        HibernateValidatorConfiguration configuration = Validation
                .byProvider(HibernateValidator.class)
                .configure();

        Validator validator = configuration.buildValidatorFactory().getValidator();
        RestRouter.validateWith(validator); // javax.validation.Validator needed but jakarta.validation.Validator provided

        BodyHandler bodyHandler = BodyHandler.create("upload-folder")
                .setDeleteUploadedFilesOnEnd(true);
        RestRouter.setBodyHandler(bodyHandler);

        for (IRestController controller : restControllers) {
            RestRouter.register(router, controller);
        }

        HttpServer httpServer = vertx.createHttpServer().requestHandler(router);
        httpServer.listen(serverPort);
        System.out.println("Server Started");
        startPromise.complete();
        LOGGER.info("Webserver Verticle Started");
    }
}
stefanvettiger commented 5 hours ago

We have a few more libraries that we use in the pom.xml, but they are the same in the old and new pom.xml.

drejc commented 4 hours ago

At a fast glance I think it is a problem / conflict between jakarta and javax lib. I have a jakarta update in the working, but can't promise anything fast as I'm swamped with payed work.

stefanvettiger commented 4 hours ago

Thank you! Would be nice if you can provide an update within the next 6 months 😉