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 <javali...@cbfiddle.com> 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 <chris.ben...@oracle.com> wrote: >> >> >>> On Apr 11, 2017, at 10:43 AM, Alan Snyder <javali...@cbfiddle.com> 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: >> >> <fx:jvmuserarg name=“-classpath" value=“...”/> >> >> 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 >