GraalVM javafx.f xml .LoadException: ошибка при разрешении onAction = '# loginAction', либо обработчик событий не находится в пространстве имен - PullRequest
1 голос
/ 28 мая 2020

Я столкнулся с ошибкой при запуске собственного образа, созданного GraalVM (последняя версия GraalVM, построенная на JDK 11) через подключаемый модуль клиента Gluon.

javafx.f xml .LoadException: Error разрешение onAction = '# loginAction', либо обработчик событий не находится в пространстве имен, либо в сценарии есть ошибка. fxml / LoginScreen.f xml: 17

Шаг компиляции работает нормально:

mvn clean client: build

Я вижу двоичный файл в папке с именем « имя проекта / target / client / x86_64-linux / двоичное имя »

Вышеупомянутая ошибка возникает, когда я запускаю исполняемый файл через »./ двоичное имя"

Строка кода F XML, на которую он жалуется в строке 17:

<Button fx:id="_loginButton" layoutX="516.0" layoutY="174.0" mnemonicParsing="false" onAction="#loginAction" prefHeight="28.0" prefWidth="94.0" text="Login" />

Код поддержки logi c выглядит следующим образом и отмечены @ F XML:

@FXML
void loginAction(ActionEvent event) throws InterruptedException {

    LoginService loginservice = new LoginService(_usernameTextField.getText(), _passwordTextField.getText());

Согласно списку распространенных ошибок JavaFX проблема обычно связана с тем, что событие onAction не имеет того же имени, что указано в контроллере - Введение в JavaFX для начинающих программистов - стр. 27 . Однако это не так, название моей программы точное. Используя подключаемый модуль JavaFX maven (отдельно от GluonClient) с использованием

maven javafx: запустите

программа запускается правильно и работает должным образом. Если мне нужно опубликовать дополнительную информацию, дайте мне знать.

Вот мой пом. xml (я заменил только название своего пакета ниже)

<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>
<groupId>com.demo</groupId>
<artifactId>com-demo-management-ui</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <client.plugin.version>0.1.26</client.plugin.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>11</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>11</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.12</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <release>11</release>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>0.0.3</version>
            <configuration>
                <mainClass>com.demo.Launcher</mainClass>
            </configuration>
        </plugin>
        <plugin>
            <groupId>com.gluonhq</groupId>
            <artifactId>client-maven-plugin</artifactId>
            <version>${client.plugin.version}</version>
            <configuration>
                <!-- Uncomment to run on iOS: -->
                <!-- <target>ios</target> -->
                <mainClass>com.demo.Launcher</mainClass>
                <graalvmHome>/opt/graalvm-ce-java11-20.2.0-dev/</graalvmHome>
            </configuration>
        </plugin>
    </plugins>
</build>

<pluginRepositories>
    <pluginRepository>
        <id>gluon-releases</id>
        <url>http://nexus.gluonhq.com/nexus/content/repositories/releases/</url>
    </pluginRepository>
</pluginRepositories>

И, наконец, вот код, в котором я устанавливаю контроллер (это вызов метода, которым я обмениваюсь своими представлениями по мере необходимости, поэтому контроллер передается в качестве аргумента при создании представления):

        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/"+baseController.getFxmlFile()));
        fxmlLoader.setController(baseController);
        Parent parent =  fxmlLoader.load();
        Scene scene = new Scene(parent);
        Stage stage = new Stage();
        stage.setFullScreen(fullScreen);
        stage.setMaximized(setMaximized);
        stage.setScene(scene);
        stage.show();

1 Ответ

2 голосов
/ 29 мая 2020

Если вы посмотрите на образец HelloFXML в репозитории образцов клиента , вы увидите, что он использует типичный файл F XML с контроллером:

<AnchorPane fx:id="pane" ... fx:controller="hellofx.HelloController">

В вашем случае у вас нет контроллера в файле F XML, но вы предоставляете его как:

fxmlLoader.setController(new hellofx.HelloController());

Как вы знаете, FXMLLoader использует отражение для создания экземпляра контроллера, элементов управления и методы, обнаруженные при разборе файла F XML.

В любом случае, когда вы нажимаете кнопку, которая запускает метод loginAction, FXMLLoader обрабатывает этот вызов :

MethodHelper.invoke(method, controller, params);

, который использует отражение для обработки такого события.

С GraalVM отражение является проблемой, и вам нужно немного «помочь» ей, предоставив классы / методы / поля, которые в какой-то момент будут использоваться рефлексивно. Узнайте больше об этом здесь .

Клиентский плагин уже позаботится о добавлении основных классов и методов JavaFX. Вы можете увидеть, что добавлено в target/client/x86_64-darwin/gvm/reflectionconfig-x86_64-darwin.json.

Однако в этот файл необходимо добавить свои собственные классы. Есть два способа сделать это:

  • Как и в HelloF XML, через конфигурацию / reflectionList вы предоставите пользовательский класс / классы, которые будут использоваться рефлексивно:
<plugin>
    <groupId>com.gluonhq</groupId>
    <artifactId>client-maven-plugin</artifactId>
    <version>${client.plugin.version}</version>
    <configuration>
          <reflectionList>
               <list>hellofx.HelloController</list>   <!-- your custom classes -->
          </reflectionList>
          <mainClass>${mainClassName}</mainClass>
    </configuration>
</plugin>

Это приводит к открытию всех методов / полей класса для отражения. Вы увидите результат в файле json как:

  {
    "name" : "hellofx.HelloController",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredFields" : true,
    "allPublicFields" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true
  }
...

Этого должно быть достаточно, чтобы решить вашу проблему.

  • Через файлы конфигурации. Как вы можете прочитать в клиентской документации , вместо этого вы можете добавить файл конфигурации (reflectionconfig.json) в META-INF/substrate/config:
[
  {
    "name":"hellofx.HelloController",
    "methods":[{"name":"loginAction","parameterTypes":["javafx.event.ActionEvent"] }]
  }
]

Это тоже исправит . Конечно, это может потребовать добавления других методов, которые есть в контроллере (например, initialize).

Это откроет для отражения только этот метод, поэтому он будет иметь меньшее влияние на объем памяти и следует за тем, что плагин работает с базовыми классами JavaFX.

...