4

I'm working on a JavaFX application which is currently non-modular. If I would make my application modular then I would need to make many changes in other projects that are not fully under my command.

The problem is that I can't use the module java.smartcardio without a module-info.java. Luckily, Eclipse allows me to add it manually (screenshot attached below).

enter image description here

But after each Maven Update, I need to add it manually again. Is there another more convenient way to do it?

Code to reproduce the issue:

FxSmartCard:

package org.example.fxsmartcard;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import java.util.List;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import org.example.smartcardservice.SmartCardServices;

public class FxSmartCard extends Application {
  private SmartCardServices cardServices;
  public FxSmartCard() {
    super();
    this.cardServices = new SmartCardServices();
  }
  @Override
  public void start(Stage stage) {
    Label title = new Label("JavaFX meets SmartCard World!");
    title.setStyle("-fx-font-size: 32px;");
    final ComboBox < String > terminalComboBox = new ComboBox < String > ();
    List < CardTerminal > terminals = null;
    Button connect = new Button("Connect");
    try {
      terminals = cardServices.getTerminals();
      if (terminals != null && terminals.size() > 0) {
        for (CardTerminal terminal: terminals) {
          terminalComboBox.getItems().add(terminal.getName());
        }
        terminalComboBox.getSelectionModel().selectFirst();
        final List < CardTerminal > terminalList = terminals;
        connect.setOnAction(e -> {
          CardTerminal selectedTerminal = cardServices.getCardReader(terminalList,
            terminalComboBox.getSelectionModel().getSelectedItem());
          try {
            cardServices.connectToCard(selectedTerminal);
          } catch (CardException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
          }
        });
      } else {
        terminalComboBox.setValue("No Terminal present");
        connect.setDisable(true);
      }
    } catch (CardException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    GridPane gridpane = new GridPane();
    GridPane.setConstraints(terminalComboBox, 1, 0);
    GridPane.setConstraints(connect, 2, 0);
    gridpane.getChildren().addAll(terminalComboBox, connect);
    VBox layout = new VBox(10, title, gridpane);
    layout.setPadding(new Insets(12));
    Scene scene = new Scene(layout);
    stage.setScene(scene);
    stage.show();
  }
  public static void main(String[] args) {
    launch();
  }
}

SmartCardServices:

package org.example.smartcardservice;
import java.util.List;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
public class SmartCardServices {
  public List < CardTerminal > getTerminals() throws CardException {
    TerminalFactory factory = TerminalFactory.getDefault();
    return factory.terminals().list();
  }
  public void connectToCard(CardTerminal terninalSource) throws CardException {
    terninalSource.connect("*");
  }
  public CardTerminal getCardReader(List < CardTerminal > terminals, String name) {
    for (CardTerminal terminal: terminals) {
      if (terminal.getName().equals(name)) {
        return terminal;
      }
    }
    return null;
  }
}

Configuration:

<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>JavaFXmeetsSmartCard</groupId>
    <artifactId>JavaFXmeetsSmartCard</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>21.0.2</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
13
  • 2
    @Billie If I understand correctly, this is purely an IDE issue, yes? In other words, you can compile the project just fine with Maven, but Eclipse keeps forgetting that you added the Smart Card I/O module? If so, try configuring the compiler plugin to add an --add-modules java.smartcardio argument (as suggested by dan1st) to see if Eclipse can pick that up. Commented Apr 22, 2024 at 17:19
  • 1
    Just found a bug report which might mean adding <compilerArgs> may not work. Commented Apr 22, 2024 at 17:36
  • 1
    Similar bug report for Idea (fixed in Idea for an upcoming release of the IDE - not released yet). Issue is that although java.smartcardio module is in the standard JRE it is not added to the module graph by default by the JRE, so you need to add it manually for both compilation and execution --add-module java.smartcardio for both javac and java. In Idea you can add the module to javac in an IDE setting, but the setting is overwritten by a maven import, so you have to re-add the setting after each import. Works apart from that. Commented Apr 22, 2024 at 17:46
  • 2
    @Slaw yeah, this seems to be purely an IDE issue. I added ‘<compilerArgs>‘ to my pom File and updated the Project via ‘Maven > Update Project’. Eclipse still complains about the missing library ‘javax.smartcardio…‘ but Maven compiles the code with and without ‘<compilerArgs>‘ successfully. Commented Apr 26, 2024 at 11:01
  • 2
    There seems to be two alternative ways of dealing with this issue. First change manually the Eclipse .classpath file. Secondly uncheck 'Update project configuration from pom.xml' whenever you do a 'Maven > Update Project...' You can fine more information in the post link Commented Apr 26, 2024 at 11:24

1 Answer 1

1

It seems to be purely an IDE issue. I could not find a straightforward solution but two alternative ways of dealing with it.

First change manually the Eclipse .classpath file by replacing

<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
   <attributes>
      <attribute name="maven.pomderived" value="true" />
   </attributes>
</classpathentry>

with

<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
   <attributes>
      <attribute name="module" value="true" />
      <attribute name="limit-modules" value="java.se,jdk.accessibility,jdk.dynalink,jdk.httpserver,jdk.incubator.vector,jdk.jartool,jdk.javadoc,jdk.jconsole,jdk.jshell,jdk.jsobject,jdk.management.jfr,jdk.net,jdk.nio.mapmode,jdk.sctp,jdk.security.auth,jdk.security.jgss,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom,java.smartcardio" />
      <attribute name="maven.pomderived" value="true" />
   </attributes>
</classpathentry>

Secondly, you add the module 'java.smartcardio' to the project by using the functionality 'Configure Build Path'.

If you do not want to repeat configuring build path again and again, you need to uncheck the box 'Update project configuration from pom.xml' ( which is by default selected ) whenever you do a 'Maven > Update Project'.

enter image description here

You can find additional information in the post: Eclipse maven compiler not supporting compiler-plugin compilerArgs

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.