简体   繁体   English

Spring Boot 3 Native 与 lombok 不可变 (@Value)

[英]Spring Boot 3 Native with lombok immutable (@Value)

I've been trying to create a example project using spring boot 3, graalvm, lombok and jpa. Everything looks perfect when I execute the test using the main method.我一直在尝试使用 spring boot 3、graalvm、lombok 和 jpa 创建示例项目。当我使用 main 方法执行测试时,一切看起来都很完美。 But I have a problem when I run the native binary.但是当我运行本机二进制文件时遇到问题。

First I create the binary:首先我创建二进制文件:

mvn -Pnative native:build

Then I run the project:然后我运行项目:

./target/demo

The project start fine, but when I try to create a new record using curl:项目启动正常,但当我尝试使用 curl 创建新记录时:

curl --location --request POST 'localhost:8080' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "test",
    "surname": "surname"
}'

I see this error in console:我在控制台中看到此错误:

2022-12-21T01:51:48.055+01:00  WARN 105751 --- [nio-8080-exec-2] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.demo.dto.ExampleDto]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Builder class `com.example.demo.dto.ExampleDto$ExampleDtoBuilder` does not have build method (name: 'build')
2022-12-21T01:51:48.055+01:00  WARN 105751 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/json;charset=UTF-8' is not supported]

My DTO looks like this:我的 DTO 看起来像这样:

@Value
@Builder
@Jacksonized
public class ExampleDto {
    Integer id;
    String name;
    String surname;

}

The controller: controller:

@RestController
@RequestMapping("/")
@AllArgsConstructor
@Slf4j
public class ExampleController {

    private final ExampleService exampleService;

    @GetMapping
    public ExampleDto findByName(@RequestParam String name) {
        return exampleService.getByName(name);
    }

    @PostMapping
    public void save(@RequestBody ExampleDto dto) {
        exampleService.save(dto);
    }
}

The problem is pretty clear, there is a problem with the "build" method that is created by lombok.问题很明显,lombok 创建的“build”方法有问题。 If I inspect the generated source I can see the method in the right place.如果我检查生成的源代码,我可以在正确的位置看到该方法。 Apparently GraalVM (or jackson) does not see the method.显然 GraalVM(或 jackson)没有看到这个方法。

I also tried to add some traces in a GET method just to be sure that the controller has access to to builder.build() method and the method exist in runtime.我还尝试在 GET 方法中添加一些跟踪,以确保 controller 可以访问builder.build()方法并且该方法存在于运行时。 (2nd clue that gives me the idea that there is a configuration problem. (第二条线索让我觉得存在配置问题。

I removed the @Value , @Jacksonized and @Builder and put just @Data and everything works fine.我删除了@Value@Jacksonized@Builder并只放置了@Data并且一切正常。

Any idea?任何的想法? Should I add an extra configuration?我应该添加额外的配置吗?

The example project is in github: https://github.com/elysrivero99/spring-boot-3-native-demo示例工程在github: https://github.com/elysrivero99/spring-boot-3-native-demo

After a while I found the answer.过了一会儿,我找到了答案。 You have to add the hints as:您必须将提示添加为:

@SpringBootApplication
@ImportRuntimeHints(DemoApplication.DemoApplicationRuntimeHints.class)
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    static class DemoApplicationRuntimeHints implements RuntimeHintsRegistrar {

        @SneakyThrows
        @Override
        public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
            hints.reflection()
                    .registerConstructor(ExampleDto.ExampleDtoBuilder.class.getDeclaredConstructor(), ExecutableMode.INVOKE)
                    .registerMethod(
                            ExampleDto.ExampleDtoBuilder.class.getMethod("build"), ExecutableMode.INVOKE);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM