Re: javapackager - partially self-contained apps in JDK 9
The code that I included below will do what you want with modular JARs. I hope to get this as a feature of the Java Packager which would be called Pugins, but there’s only so much time, which is why I provided you with a portion of my prototype code. Chris > On Apr 25, 2017, at 12:11 PM, Alan Snyder wrote: > > The whole point is not to include the connector JAR in the bundled app, so > that it can upgraded independently. > > I tried setting -classpath using fx:jvmuserarg, the app crashed (exit 1) on > startup. > > I really wonder why this case is not handled in some convenient way. > > > > >> On Apr 25, 2017, at 11:32 AM, Chris Bensen wrote: >> >> >>> On Apr 11, 2017, at 10:43 AM, Alan Snyder wrote: >>> >>> I have run into a problem in moving my macOS apps from JDK 8 to 9. The >>> issue relates to using MySQL via JDBC. >>> The connector class name is fixed. The class is loaded using >>> Class.forName(). However, there can be different versions >>> of the connector in different JAR files, and the proper version might need >>> to be synced with the currently installed version >>> of MySQL. >>> >>> In JDK 8, I used the extension mechanism to load the MySQL connector JAR >>> rather than building this JAR into the bundled app. >>> My thinking was that the connector might need to be updated in sync with >>> the database and I should not have to rebuild apps to do that. >>> >>> In JDK 9, the extension mechanism is gone. I have not found any way to >>> achieve the equivalent effect. It seems that javapackager >>> controls the setting of the CLASSPATH. I have not found an option that >>> would allow me to extend the CLASSPATH with a directory >>> where the connector JAR could be found. Is there a way to do this? >>> >>> Alan >>> >> >> >> Are you including the connector JAR in the app image? >> >> I think you could set the classpath if you us ant-javafx.jar: >> >> >> >> but honestly I’ve never tried it with JDK 9. >> >> A JDK 9 way of dynamically loading this would be to create a Layer. Here’s >> some semi working code you could use: >> >> >> public Plugin loadPlugin(String module, String classname) { >> Plugin result = null; >> Configuration cf = >> resolve(file.getAbsoluteFile().getParentFile().toPath(), name); >> ClassLoader scl = ClassLoader.getSystemClassLoader(); >> Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl); >> ClassLoader cl = layer.findLoader(name); >> >> try { >> result = createPlugin(layer, name, classname); >> result.load(); >> plugins.add(result); >> } >> catch (Exception e) { >> System.out.println("oh no!" + e.toString()); >> } >> >> return result; >> } >> >> private static Configuration resolve(Path modulepath, String... roots) { >> ModuleFinder finder = ModuleFinder.of(modulepath); >> return Layer.boot() >> .configuration() >> .resolve(finder, ModuleFinder.of(), Set.of(roots)); >> } >> >> private static Plugin createPlugin(Layer layer, String mn, String mc) >> throws Exception { >> ClassLoader loader = layer.findLoader(mn); >> Class c = loader.loadClass(mc); >> Plugin p = (Plugin)c.getConstructor().newInstance(); >> return p; >> } >> >> Chris >
Re: javapackager - partially self-contained apps in JDK 9
> On Apr 11, 2017, at 10:43 AM, Alan Snyder wrote: > > I have run into a problem in moving my macOS apps from JDK 8 to 9. The issue > relates to using MySQL via JDBC. > The connector class name is fixed. The class is loaded using Class.forName(). > However, there can be different versions > of the connector in different JAR files, and the proper version might need to > be synced with the currently installed version > of MySQL. > > In JDK 8, I used the extension mechanism to load the MySQL connector JAR > rather than building this JAR into the bundled app. > My thinking was that the connector might need to be updated in sync with the > database and I should not have to rebuild apps to do that. > > In JDK 9, the extension mechanism is gone. I have not found any way to > achieve the equivalent effect. It seems that javapackager > controls the setting of the CLASSPATH. I have not found an option that would > allow me to extend the CLASSPATH with a directory > where the connector JAR could be found. Is there a way to do this? > > Alan > Are you including the connector JAR in the app image? I think you could set the classpath if you us ant-javafx.jar: but honestly I’ve never tried it with JDK 9. A JDK 9 way of dynamically loading this would be to create a Layer. Here’s some semi working code you could use: public Plugin loadPlugin(String module, String classname) { Plugin result = null; Configuration cf = resolve(file.getAbsoluteFile().getParentFile().toPath(), name); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl); ClassLoader cl = layer.findLoader(name); try { result = createPlugin(layer, name, classname); result.load(); plugins.add(result); } catch (Exception e) { System.out.println("oh no!" + e.toString()); } return result; } private static Configuration resolve(Path modulepath, String... roots) { ModuleFinder finder = ModuleFinder.of(modulepath); return Layer.boot() .configuration() .resolve(finder, ModuleFinder.of(), Set.of(roots)); } private static Plugin createPlugin(Layer layer, String mn, String mc) throws Exception { ClassLoader loader = layer.findLoader(mn); Class c = loader.loadClass(mc); Plugin p = (Plugin)c.getConstructor().newInstance(); return p; } Chris
Re: javapackager - partially self-contained apps in JDK 9
> On Apr 11, 2017, at 1:43 PM, Alan Snyder wrote: > > I have run into a problem in moving my macOS apps from JDK 8 to 9. The issue > relates to using MySQL via JDBC. > The connector class name is fixed. The class is loaded using Class.forName(). > However, there can be different versions > of the connector in different JAR files, and the proper version might need to > be synced with the currently installed version > of MySQL. > > In JDK 8, I used the extension mechanism to load the MySQL connector JAR > rather than building this JAR into the bundled app. > My thinking was that the connector might need to be updated in sync with the > database and I should not have to rebuild apps to do that. > > In JDK 9, the extension mechanism is gone. I have not found any way to > achieve the equivalent effect. It seems that javapackager > controls the setting of the CLASSPATH. I have not found an option that would > allow me to extend the CLASSPATH with a directory > where the connector JAR could be found. Is there a way to do this? My application ran into classpath issues because it tried to dynamically add plugins to the classpath and that broke on Java 9. To work around it I created an agent so I could get access to the java.lang.Instrumentation interface to add to the classpath. You might try that approach. It’s ugly, but better than reflectively accessing private fields of URLClassLoader, which doesn’t work for Java 9 :-) Scott
javapackager - partially self-contained apps in JDK 9
I have run into a problem in moving my macOS apps from JDK 8 to 9. The issue relates to using MySQL via JDBC. The connector class name is fixed. The class is loaded using Class.forName(). However, there can be different versions of the connector in different JAR files, and the proper version might need to be synced with the currently installed version of MySQL. In JDK 8, I used the extension mechanism to load the MySQL connector JAR rather than building this JAR into the bundled app. My thinking was that the connector might need to be updated in sync with the database and I should not have to rebuild apps to do that. In JDK 9, the extension mechanism is gone. I have not found any way to achieve the equivalent effect. It seems that javapackager controls the setting of the CLASSPATH. I have not found an option that would allow me to extend the CLASSPATH with a directory where the connector JAR could be found. Is there a way to do this? Alan