当前位置: 首页 > 知识库问答 >
问题:

Jackson在编译成本机映像的Micronaut应用程序中找不到POJO的属性

张姚石
2023-03-14

我用Micronaut 2.0.0创建了一个简单的应用程序:它是使用Micronaut application generator在此处https://Micronaut.io/launch/生成的,然后添加了以下内容:

@Controller
public class HelloController {
    @Get("/hello")
    public Result hello() {
        return new Result("Hello world!");
    }
}

public class Result {
    private final String message;

    public Result(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

然后我使用./mvnw clean package构建应用程序。

当我用java-jar target/micronaut-minimal-1.0.jar启动它时,它成功启动。它会正确响应:

$ curl http://localhost:8080/hello
{"message":"Hello world!"}

现在我构建一个本机映像:

native-image -jar target/micronaut-minimal-0.1.jar target/app

然后运行它:

target/app

开始还可以。

现在相同的请求会产生错误:

$ curl http://localhost:8080/hello
{"message":"Internal Server Error: Error encoding object [com.example.Result@7f21a9858b70] to JSON: No serializer found for class com.example.Result and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)"}

我使用GraalVM CE20.1.0(Build11.0.7+10-jvmci-20.1-B02)来运行和构建jar和映像。

共有1个答案

澹台锐
2023-03-14

我找到了两种解决问题的方法:一种是特定的,更干净,另一种是更通用的,但更脏。

更干净的方法很简单:只需用@instrospected注释类:

@Introspected
public class Result {
    private final String message;

    public Result(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

就是这样。如果我没有理解错的话,这个注释使Micronaut在编译时生成内省类,然后可能被Jackson序列化机器使用。文件上说

您可以使用Jackson.bean-inspection-module设置启用与Jackson的bean内省集成,以实现无反射的JSON序列化和反序列化。

但在我的情况下,它起作用了。

正如@Turing85所指出的,由于result#messageresult#getmessage()在代码中没有引用,native-image不知道我们在运行时仍然需要它们,因此没有为反射API(默认情况下Jackson可能使用)留下它们的痕迹。

我们可以指示native-image工具保留这些信息。首先,我们需要创建一个JSON配置(在我的示例中,文件名为reflect-config.JSON):

[
  {
    "name" : "com.example.Result",
    "fields" : [
      { "name" : "message" }
    ],
    "methods" : [
      { "name" : "getMessage", "parameterTypes" : [] }
    ]
  }
]

这里我们指示工具保留字段message和方法getMessage()

然后我们使用-h:reflectionConfigurationFiles提供此文件:

native-image --no-server -H:ReflectionConfigurationFiles=reflect-config.json -jar target/micronaut-minimal-0.1.jar target/app

第一种方法更简洁,因为它完全避免了反射的使用(这意味着代码工作更快,占用的内存更少)。

第二种方法更具有普遍性,因为第一种方法只有在具体处理的情况下才有可能。如果一个工具仍然需要反射,那么您别无选择,只能坚持使用它。

 类似资料:
  • 正如标题所示,我试图使用Docker为一个基于Kotlin的Micronaut应用程序构建一个本机映像。 我已将以下依赖项添加到文件中。 一切似乎都井然有序。映像启动并似乎接受连接,但当我启动http请求时,会出现以下错误。 有没有关于如何避免上述错误的线索?

  • GraalVM系统显然无法将Spring应用程序编译为本机映像。

  • 我正在尝试将我的. jar项目转换为本地映像,因为我需要在不支持Java的设备中运行它。为此,我安装了GraalVM和所有必需的依赖项,本地映像构建工作完美(或者至少看起来是这样,因为它在过程中不会产生任何错误)。 我用于构建的命令是: /usr/lib/jvm/graalvm/bin/native image-jar-MyApp。jar MyApp——启用http——启用https——无回退——

  • 我有一个类的数组列表,如下所示: 我想把这个列表写成Json,并尝试了以下代码: 并收到以下错误信息: 找不到类~~~~~的序列化程序,也找不到创建BeanSerializer的属性(为了避免异常,请禁用SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过引用链:java.util.ArrayList[0])` 我尝试添加但由于未知原因,它使所有Person对象

  • 我和jackson一起绘制地图,我有点迷茫。我的Json具有以下结构 我确实找到了很多处理数组的教程,但我在第一个标记“d”时就已经失败了。而且根本不需要所有的“_元数据”标记。 我创建了一个包含lastName等属性和一个集合附件的pojo。但我的代码在标记“d”或“_元数据”时总是失败 还有杰克逊的读者 任何提示都将不胜感激。 问候马蒂亚斯

  • 我在GraalVm native-image(Micronaut框架)中遇到了MongoDB的问题。当我使用IDE和。jar进行部署时,所有工作都正常,没有任何异常。当我使用由Micronauts launcher生成的标准Gradle任务创建本机映像并试图从数据库中获取实体时,找不到。这是我的成绩。建造 下面是我的DroneService.class,我试图从MongoDB中获取实体 日志 有什