Come accedere a un modulo Java non esportato?

Aug 27 2020

Ho bisogno di localizzare i controlli integrati di JavaFX. Prima di Jigsaw c'erano dei modi per ottenere questo risultato:

  1. Tramite un file delle proprietà aggiuntivo che deve essere inserito nel com.sun.javafx...pacchetto
  2. Tramite l'API di riflessione, come mostrato qui

Entrambi i metodi non sono compatibili con i moduli Java, perché com/sun/javafx/scene/control/*non fanno parte dell'API pubblica e non c'è modo di creare due pacchetti con lo stesso nome anche se appartengono a progetti diversi.

Qualche possibilità di hackerare questo problema per ottenere l'accesso al pacchetto interno? Più specificamente, il classloader ControlResources .

Domande correlate:

Localizzazione dei controlli JavaFx

Risposte

Evan Aug 28 2020 at 13:00

Ok, ho perso l'intera giornata a scavare su questo argomento.

Risposta breve: non è possibile.

Risposta lunga

Puoi usare add-exportse add-opensper accedere a com.sun.javafx.scene.control.skin.resources, ma funzionerà solo se non stai usando moduli con nome, in altre parole, la tua app non deve essere modularizzata.

<plugin>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-maven-plugin</artifactId>
    <configuration>
        <mainClass>${bld.mainClass}</mainClass> <executable>${java.home}/bin/java</executable>
        <options>
            <option>--add-exports</option>
            <option>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</option>
            <option>--add-opens</option>
            <option>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</option>
        </options>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <compilerArgs>
            <arg>--add-exports</arg>
            <arg>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</arg>
            <arg>--add-opens</arg>
            <arg>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</arg>
        </compilerArgs>
    </configuration>
</plugin>

Se la tua app è modularizzata, otterrai questo.

Caused by: java.lang.UnsupportedOperationException: ResourceBundle.Control not supported in named modules
    at java.base/java.util.ResourceBundle.checkNamedModule(ResourceBundle.java:1547)
    at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:1508)

Questo perché l'unico modo per ottenere l'accesso alle risorse che si trovano in un altro modulo è SPI ( documenti qui ). OpenJFX non implementa ResourceBundleProviderper fornire l'accesso ai controlli di internazionalizzazione, perché fa parte dell'API interna.

Quindi, questo problema può essere risolto solo dagli sviluppatori di OpenJFX, ma a giudicare dagli ultimi changelog di OpenJFX, sono altamente concentrati sulla correzione di errori di battitura, non sulle funzionalità.