Let's assume an OpenJDK 11 + OpenJFX 11 based application. The codebase is organized in a single java module (see A Guide to Java 9 Modularity for reference).
Until now I combined all my JavaFX based projects with Google's dependency injection framework Guice. For modular projects, this doesn't seem to work...
SQLiteCompassApplication.java
public class SQLiteCompassApplication extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) throws Exception {
Injector injector = Guice.createInjector(new MyModule());
FXMLLoader fxmlLoader = injector.getInstance(FXMLLoader.class);
try(InputStream fxmlStream = getClass().getResourceAsStream("/view/View.fxml")) {
Parent root = fxmlLoader.load(fxmlStream);
stage.setScene(new Scene(root));
stage.setTitle("SQLite Compass");
stage.setOnCloseRequest(event -> System.exit(0));
stage.show();
}
}
}
module-info.java
module org.x1c1b.sqlitecompass {
requires javafx.controls;
requires javafx.fxml;
requires com.google.guice;
exports org.x1c1b.sqlitecompass;
}
To keep it simple the Guice configuration, which means the declared Guice modules (not to confuse with java modules), isn't pasted but still working for non-modular projects.
When executing this code I receive the following exception:
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field com.google.inject.Injector org.x1c1b.sqlitecompass.config.provider.FXMLLoaderProvider.injector accessible: module org.x1c1b.sqlitecompass does not "opens org.x1c1b.sqlitecompass.config.provider" to module com.google.guice
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:340)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:280)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:176)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:170)
at [email protected]/com.google.inject.internal.SingleFieldInjector.<init>(SingleFieldInjector.java:38)
at [email protected]/com.google.inject.internal.MembersInjectorStore.getInjectors(MembersInjectorStore.java:126)
at [email protected]/com.google.inject.internal.MembersInjectorStore.createWithListeners(MembersInjectorStore.java:93)
at [email protected]/com.google.inject.internal.MembersInjectorStore.access$000(MembersInjectorStore.java:36)
at [email protected]/com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:45)
at [email protected]/com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:41)
at [email protected]/com.google.inject.internal.FailableCache$1.load(FailableCache.java:40)
at [email protected]/com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3444)
at [email protected]/com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2193)
at [email protected]/com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2152)
at [email protected]/com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2042)
... 39 more
Exception running application org.x1c1b.sqlitecompass.SQLiteCompassApplication
I could fix this issue by pasting opens org.x1c1b.sqlitecompass.config.provider; to module-info.java. But this results in further exceptions...
How should I configure my module/module-info.java to use it with Google Guice in general? Is it possible to use Google Guice and Modularity in combination?
EDIT
It seems to work when I change the following lines:
- Add
exports org.x1c1b.sqlitecompass.config, where my Guice modules are declared, tomodule-info.java - Execute the program with the additional VM option
--add-opens java.base/java.lang=com.google.guice
But I would guess it's more a workaround found here than an official solution...
org.x1c1b.sqlitecompass.config.provider.FXMLLoaderProvider.injector. Apart from which, it seems like something that needs to be fixed at guice end as well for the use ofField.setAccessible. Worth reporting to their issues. (you might find one already reported)--add-opens...shall still work. But until what extend really could be determined by the code.opens org.x1c1b.sqlitecompass.config.provider to com.google.guice;)