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

Gluon客户端插件:用Jackson和Java时间模块构建APK

葛玉堂
2023-03-14

我添加了一个名为“Person”的模型。

package hellofx;
import java.time.LocalDate;

public class Person {
    private Integer id;
    private String name;
    private LocalDate dob;

    // Getters and Setters
}

并在“pom.xml”中添加了以下依赖项:

  • Jackson-DataBind
  • Jackson-DataType-JSR310
public class HelloFX extends Application {

    private Label parseStatusLabel = new Label("");
    
    private String serializedString = null;

    public void start(Stage stage) {
        String javaVersion = System.getProperty("java.version");
        String javafxVersion = System.getProperty("javafx.version");
        Label label = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");

        ImageView imageView = new ImageView(new Image(HelloFX.class.getResourceAsStream("/hellofx/openduke.png")));
        imageView.setFitHeight(200);
        imageView.setPreserveRatio(true);

        Button serButton = new Button("Serialize");
        serButton.setOnAction(e -> serialize());

        Button deserButton = new Button("Deserialize");
        deserButton.setOnAction(e -> deserialize());

        VBox root = new VBox(30, imageView, label, serButton, deserButton, parseStatusLabel);
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root, 640, 480);
        scene.getStylesheets().add(HelloFX.class.getResource("styles.css").toExternalForm());
        stage.setScene(scene);
        stage.show();
    }

    private void serialize() {
        Person person = new Person();
        person.setId(1);
        person.setName("John Doe");
        person.setDob(LocalDate.of(1960, 10, 10));

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());

        try {
            serializedString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(person);
            parseStatusLabel.setText("Serialization success \n" + serializedString);
        } catch (JsonProcessingException e) {
            parseStatusLabel.setText("Serialization failed");
            e.printStackTrace();
        }
    }

    private void deserialize() {
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.registerModule(new JavaTimeModule());

            Person person = mapper.readValue(serializedString, Person.class);
            parseStatusLabel.setText("Deserialization successful > " + person);
        } catch (JsonMappingException e) {
            parseStatusLabel.setText("Deserialization failed");
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            parseStatusLabel.setText("Deserialization failed");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

}
[Thu Mar 25 10:38:59 IST 2021][INFO] We will now compile your code for aarch64-linux-android. This may take some time.
[Thu Mar 25 10:39:14 IST 2021][INFO] [SUB] [hellofx.hellofx:215]    classlist:   5,873.73 ms,  0.96 GB
[Thu Mar 25 10:39:16 IST 2021][INFO] [SUB] [hellofx.hellofx:215]        (cap):     288.58 ms,  0.96 GB
[Thu Mar 25 10:39:17 IST 2021][INFO] [SUB] [hellofx.hellofx:215]        setup:   2,968.21 ms,  0.96 GB
[Thu Mar 25 10:40:25 IST 2021][INFO] [SUB] [hellofx.hellofx:215]     (clinit):   1,142.49 ms,  3.74 GB
[Thu Mar 25 10:40:25 IST 2021][INFO] [SUB] [hellofx.hellofx:215]   (typeflow):  30,888.81 ms,  3.74 GB
[Thu Mar 25 10:40:25 IST 2021][INFO] [SUB] [hellofx.hellofx:215]    (objects):  28,773.30 ms,  3.74 GB
[Thu Mar 25 10:40:25 IST 2021][INFO] [SUB] [hellofx.hellofx:215]   (features):   5,209.44 ms,  3.74 GB
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] [hellofx.hellofx:215]     analysis:  68,730.14 ms,  3.74 GB
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Warning: Aborting stand-alone image build. Unsupported features in 11 methods[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Detailed message:
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Error: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved method during parsing: com.fasterxml.jackson.databind.DeserializationContext.extractScalarFromObject(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.JsonDeserializer, java.lang.Class). To diagnose the issue you can use the --allow-incomplete-classpath option. The missing method is then reported at run time when it is accessed the first time.
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Trace:
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at parsing com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer.deserialize(DurationDeserializer.java:137)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Call path from entry point to com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer.deserialize(JsonParser, DeserializationContext):
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer.deserialize(DurationDeserializer.java:125)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer.deserialize(DurationDeserializer.java:43)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3402)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at hellofx.HelloFX.deserialize(HelloFX.java:99)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.oracle.svm.reflect.HelloFX_deserialize_15f8adc753d5dce15c2070972d1be99d7c98ca42_239.invoke(Unknown Source)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at java.lang.reflect.Method.invoke(Method.java:566)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.sun.prism.GraphicsPipeline.createPipeline(GraphicsPipeline.java:224)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:91)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_ARRAY:Ljava_lang_Runnable_2_0002erun_00028_00029V(generated:0)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Error: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved method during parsing: com.fasterxml.jackson.databind.DeserializationContext.extractScalarFromObject(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.JsonDeserializer, java.lang.Class). To diagnose the issue you can use the --allow-incomplete-classpath option. The missing method is then reported at run time when it is accessed the first time.
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Trace:
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at parsing com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:213)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB] Call path from entry point to com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(JsonParser, DeserializationContext):
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:202)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:50)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3402)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at hellofx.HelloFX.deserialize(HelloFX.java:99)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.oracle.svm.reflect.HelloFX_deserialize_15f8adc753d5dce15c2070972d1be99d7c98ca42_239.invoke(Unknown Source)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at java.lang.reflect.Method.invoke(Method.java:566)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.sun.prism.GraphicsPipeline.createPipeline(GraphicsPipeline.java:224)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:91)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
[Thu Mar 25 10:40:26 IST 2021][INFO] [SUB]      at 

这是完整的日志。

我在没有使用'localdate'和'javatimemodule'的情况下测试了这个应用程序,我能够构建APK,解析也能工作。

下面是完整的pom.xml

<?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>hellofx</groupId>
    <artifactId>hellofx</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>HelloFX</name>

    <properties>
        <main.class>hellofx.HelloFX</main.class>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>11</maven.compiler.release>
        <javafx.version>15.0.1</javafx.version>
        <javafx.maven.plugin.version>0.0.5</javafx.maven.plugin.version>
        <client.maven.plugin.version>0.1.38</client.maven.plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${javafx.version}</version>
        </dependency>

        <!-- Added jackson dependency here -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.1</version>
        </dependency>
        <!-- Added JavaTime data type -->
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>2.12.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>

            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>${javafx.maven.plugin.version}</version>
                <configuration>
                    <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>

            <plugin>
                <groupId>com.gluonhq</groupId>
                <artifactId>client-maven-plugin</artifactId>
                <version>${client.maven.plugin.version}</version>
                <configuration>
                     <target>${client.target}</target>
                     <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>desktop</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <client.target>host</client.target>
            </properties>
        </profile>
        <profile>
            <id>ios</id>
            <properties>
                <client.target>ios</client.target>
            </properties>
        </profile>
        <profile>
            <id>android</id>
            <properties>
                <client.target>android</client.target>
            </properties>
        </profile>
    </profiles>

</project>
  1. 所有JSON配置文件都是使用'client:runagent'创建的目标:-
    在关于这个问题的上一个问题中,Jose Pereda指示我使用'mvn client:runagent'。由于我在WSL中使用Ubuntu,所以我在windows命令提示符中运行了这个目标,并编辑了一些配置文件以删除windows特定的配置。
  2. Jackson不是导致此问题的原因,'JavaTimeModule'是:-
    我已经从'Person‘中删除了LocalDate'dob'属性,并在hellofx.java中注释掉了以下内容。
    mapper.registerModule(new JavaTimeModule());
    之后,我就可以构建和运行APK,序列化和反序列化都工作了。

我还尝试过按照dzim的建议,手动在衬底文件夹下添加'ReflectionConfig.json'。但同样的问题也发生了。

共有1个答案

东门清夷
2023-03-14

因为您需要更新反射配置,所以回答很长。(因为jackson正在做什么,graalvm需要了解它,因为它是预编译的)。

最重要的是:确保您已经阅读了Gluon提供的文档。

它详细描述了你能做什么。

请参阅此处以了解更多关于应用程序需要额外配置时需要做什么的一般细节。这不仅涉及反射,还涉及其他任何东西(目标平台、资源、特定于平台的构建信息等)。

我也有一个使用Jackson的小应用程序。

在您的maven资源(src/main/resources)下添加meta-inf/substar/config
添加一个名为reflectionconfig.jsonJSON文件,并添加以下内容:

[
  {
    "name": "com.fasterxml.jackson.databind.ObjectMapper",
    "methods": [
      { "name": "<init>", "parameterTypes": [] },
      { "name": "<init>", "parameterTypes": ["com.fasterxml.jackson.core.JsonFactory"] }
    ]
  }
]

这告诉GraalVM(我想,我不是百分之百肯定它,tbh),它需要初始化这个类和指定的方法,以便在得到的AOT本机可执行文件中进行反射。

更新您的client-maven-plugin 部分,以包含有关您希望用Jackson取消/序列化的类的更多信息。

<configuration>
  <!-- ... main class, etc. -->

  <reflectionList>

    <!-- ... -->

    <!-- our own JSON data classes below -->
    
    <!-- more Jackson stuff -->
    <list>com.fasterxml.jackson.core.JsonFactory</list>

    <!-- ... -->
  </reflectionList>
</configuration>

至少我的应用程序已经足够了。

例如:如果您使用FXMLs,就我所知,您的控制器和FXMLs中使用的所有小部件也需要添加到pom.xml中。

干杯

首先:很遗憾听到你还在纠结。我有点错过了关于Jackson javatimemodule的部分...

我不知道这是否可行,但您可以尝试将提到的方法手动添加到反射配置JSON中:

[
{
  "name":"com.fasterxml.jackson.databind.DeserializationContext",
  "methods":[{"name":"extractScalarFromObject","parameterTypes":["com.fasterxml.jackson.core.JsonParser","com.fasterxml.jackson.databind.JsonDeserializer","java.lang.Class"] }]
}
]

在JSON配置中添加一些资源也可能有所帮助:

{
  "resources":{
  "includes":[
    // others
    {"pattern":"META-INF/services/.*"}
  ]},
  "bundles":[]
}

为什么?因为模块中有一个服务加载器定义。请参阅此处

 类似资料:
  • 从4.6年级开始: https://docs.gradle.org/4.6/userguide/java_library_plugin.html#sec:java_library_deparition https://docs.gradle.org/4.6/release-notes.html#compile/runtime-scope-deparential-in-pom-consumment

  • 问题内容: 在我的文件中,我尝试实现一些映射,其中使用不同的分析器将属于一种类型的一个字段索引到其余字段。 目前,yaml文件具有以下结构: 这不会将自定义分析器应用于标题字段,因此我希望有人可以为我指出将自定义分析器应用于各个字段的正确方向? 问题答案: 我在ml中回答了这个问题: 如果您使用的是Java,则不必使用yml文件。您可以,但不必。 如果您使用的是Spring,则可以查看ES spr

  • 问题内容: 我在网上和YouTube上四处查看,出于某种原因,这是一些绝密信息或其他内容,但我试图找出从哪里开始制作Minecraft客户端模块,最好是可以打包的东西例如为用户提供简便性而喂食野兽或技术包,但两种方法都可以。 我将如何创建一个mod?我对eclipse和Java编程本身很熟悉,但是我不知道从哪里开始编写插件。 我曾尝试设置Minecraft Forge,但由于某种原因,它是如此令人

  • 将会有这么一种情况,你将有一个主要的管理面板,但是希望能够让独立的用户设定他们自己的偏好。在Devlounge PluginSeries 这个例子中,我们添加了一个是否把文字添加到文章末尾的选项。然而假如一个登录用户不希望看到这段文字呢?为什么不给他们一个选择,而且不影响到所有其他的用户呢? 这篇文章将会涉及到这个问题,让你可以添加你自己的用户面板。 命名你的选项 class DevloungeP

  • 这是使用Delphi(XE6)开发RTX客户端插件SDK, 使用Delphi快速的开发, 封装了原c++ sdk, 比用c++开发更方便, 而且提供好的模版生成工具.

  • 模块标记 coolie-cli 的模块构建方式应该是比较特殊的一类,与 webpack 一样,都是另辟蹊径。 webpack:依赖模块放到数组里,数组索引值就是模块 ID。 coolie-cli:依赖模块全局标记 ID(三十六进制)。 coolie-cli 可以将长长的物理路径压缩成最短的字符,达到压缩率最大化,而不是将模块直接合并。 // module1.js define(function(r