spring hateoas hal-forms 可供性支持在升级到 spring boot 3 后由于 jakarta.validation 和 hibernate 版本冲突而无法工作

问题描述 投票:0回答:0

如果您升级到 Spring Boot 3,Spring Hateoas 似乎不提供对 HAL-FORMS 中模板可供性属性验证的支持。似乎 Spring Boot 正在迁移到更新版本的休眠和 jakarta 验证 api,而 Spring Hateoas PropertyUtils 没有尚不支持。它的主要分支仍然导入javax.validation.constraints.NotNull,并且它的hibernate版本与Spring boot 3冲突。

这是一个只有 1 个文件(& pom)的非常简单的示例,它演示了它适用于 Spring boot 2.7.6(请参阅我们稍后将使用的注释掉的 spring-boot-starter-parent 版本。

<?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 https://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.6</version>
        <!-- <version>3.0.5</version> -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-hateoas-affordance-sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-hateoas-affordance-sample</name>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
package com.example.demo;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

import org.hibernate.validator.constraints.Length;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotNull;
//import jakarta.validation.constraints.NotNull;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Value;

@SpringBootApplication
@EnableHypermediaSupport(type = HypermediaType.HAL_FORMS)
public class SpringHateoasAffordanceSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringHateoasAffordanceSampleApplication.class, args);
    }
    @RestController
    class FooController {

        private static final String TEMPLATE = "Hello, %s!";

        @GetMapping("/")
        public HttpEntity<FooRepresentation> get(
            @RequestParam(value = "name", defaultValue = "foo") String name) {

            var controller = methodOn(FooController.class);
            return new ResponseEntity<>(
                    new FooRepresentation(String.format(TEMPLATE, name))
                            .add(linkTo(controller.get(name)).withSelfRel())
                            .add(linkTo(controller.post(new FooModel("foo"))).withRel("foo"))
                    , HttpStatus.OK);
        }
        
        @PostMapping("/foo")
        public HttpEntity<FooModel> post(@RequestBody FooModel fooModel) {
            return new ResponseEntity<>(fooModel, HttpStatus.OK);
        }
    }
    
    @Value
    @EqualsAndHashCode(callSuper=false)
    class FooRepresentation extends RepresentationModel<FooRepresentation> {
        private final String name;
    }
    
    @Data
    @AllArgsConstructor
    public class FooModel {
        
        @NotNull
        @Length(min = 2, max = 10)
        private String name;
    }
}

如果我运行上面的命令并将我的浏览器指向 http://localhost:8080,我会得到 'required=true' 以及我期望的 FooModel.name 属性的最小长度和最大长度。我不得不调整网址,因为堆栈溢出认为它们是垃圾邮件

{
    "name": "Hello, foo!",
    "_links": {
        "self": {
            "href": "/?name=foo"
        },
        "foo": {
            "href": "/foo"
        }
    },
    "_templates": {
        "default": {
            "method": "POST",
            "properties": [
                {
                    "name": "name",
                    "required": true,
                    "minLength": 2,
                    "maxLength": 10,
                    "type": "text"
                }
            ],
            "target": "/foo"
        }
    }
}

但是如果我升级到 Spring 3.0.5(请参阅 pom 中的注释行)我必须将导入更改为 jakarta.validation.constraints.NotNull 而不是 javax.validation.constraints.NotNull 但是当我重复我的测试时我得到缺少注释驱动提示的响应。

{
    "name": "Hello, foo!",
    "_links": {
        "self": {
            "href": "/?name=foo"
        },
        "foo": {
            "href": "/foo"
        }
    },
    "_templates": {
        "default": {
            "method": "POST",
            "properties": [
                {
                    "name": "name",
                    "type": "text"
                }
            ],
            "target": "/foo"
        }
    }
}

虽然它不是很明显来自休眠的@Length(导入包没有改变)我怀疑版本冲突也是原因。

是否有一些我可以用来变通的配置,或者是否计划在 spring boot 3 中支持它?

spring-hateoas
© www.soinside.com 2019 - 2024. All rights reserved.