Background:
In my organization there are a lot of Java based Windows desktop applications. In our proprietary software deployment system the applications don't contain an individual JRE / JDK. Rather a common JRE (so far Oracle 8 Java SE JRE) is deployed to the users machine, which is attached to the individual applications based on environment variables.
We would like to migrate the JRE from Oracle 8 Java SE JRE to OpenJDK 11 without having to modify the applications. From Java 8 to Java 11 various libraries got removed, e. g. JavaFX. Using the Java module system and the jlink tool, I can create my own proprietary JDK enhanced with OpenJFX:
jlink --module-path ..\mods;C:\Temp\javafx-jmods-11.0.2 --add-modules=ALL-MODULE-PATH,java.base,java.compiler,java.datatransfer,java.desktop,... --output C:\Temp\OpenJDK+OpenJFX
Applications, which need JavaFX can use this proprietary JDK without being changed.
When I try to apply the same method to the latest beta of JAXB, I get the following error:
jlink --module-path ..\mods;C:\Temp\jaxb-ri-2.4.0-b180830.0438\jaxb-ri\mod --add-modules=java.xml.bind,java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,... --output C:\Workspace\Java\OpenJDK_11.0.2_JFX_JAXB
Error: automatic module cannot be used with jlink: java.activation from file:///C:/Temp/jaxb-ri-2.4.0-b180830.0438/jaxb-ri/mod/javax.activation-api.jar
As per https://github.com/eclipse-ee4j/jaf/issues/13, "JAXB API uses activation-api as its dependency and is forced to use it as an automatic module or from classpath because of missing a module-info.java descriptor file."
Furtheron as per Is it possible to use jlink on JDK 11 to make a runtime including the Java SE EE modules that were removed? I can bundle the module java.xml.bind using jlink from Java 10, which still contained it. Indeed jlink succeeds, if I add two modules from OpenJDK 10.0.2 to the module path:
jlink --module-path ..\mods;C:\Temp\jdk-10.0.2\jmods\java.xml.bind.jmod;C:\Temp\jdk-10.0.2\jmods\java.activation.jmod --add-modules=java.xml.bind, ...
But when I run my application with the generated JDK, I get errors like this:
!ENTRY org.eclipse.osgi 4 0 2019-02-15 15:58:58.642
!MESSAGE Application error
!STACK 1
org.eclipse.e4.core.di.InjectionException: java.lang.NoClassDefFoundError: javax/annotation/PostConstruct
at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:410)
at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:318)
at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:162)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createDefaultHeadlessContext(E4Application.java:491)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createDefaultContext(E4Application.java:505)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:204)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:614)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:336)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:594)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:148)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:151)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:388)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:243)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:653)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:590)
at org.eclipse.equinox.launcher.Main.run(Main.java:1499)
Caused by: java.lang.NoClassDefFoundError: javax/annotation/PostConstruct
at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:124)
at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:399)
... 22 more
Caused by: java.lang.ClassNotFoundException: javax.annotation.PostConstruct cannot be found by org.eclipse.e4.core.di_1.6.100.v20170421-1418
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:433)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:395)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:387)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:150)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 24 more
Or this:
Feb. 15, 2019 2:49:03 NACHM. com.sun.xml.internal.bind.v2.runtime.reflect.opt.Injector <clinit>
SEVERE: null
java.security.PrivilegedActionException: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String, [B, int, int, java.lang.ClassLoader, java.security.ProtectionDomain)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.reflect.opt.Injector.<clinit>(Injector.java:182)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:66)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:164)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:270)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.property.ArrayProperty.<init>(ArrayProperty.java:53)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.<init>(ArrayERProperty.java:73)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.<init>(ArrayElementProperty.java:85)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.property.ArrayElementNodeProperty.<init>(ArrayElementNodeProperty.java:47)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:499)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:316)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1141)
at [email protected]/com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:150)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at [email protected]/javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:282)
at [email protected]/javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:271)
at [email protected]/javax.xml.bind.ContextFinder.find(ContextFinder.java:406)
at [email protected]/javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:706)
at [email protected]/javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:647)
at com.xxx.build.automation.utils.internal.CategoryFileHandler.unMarshalFile(CategoryFileHandler.java:17)
at com.xxx.build.automation.utils.common.GetComponentName.doExecuteInternal(GetComponentName.java:89)
at com.xxx.build.automation.utils.common.GetComponentName.execute(GetComponentName.java:72)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at jdk.internal.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.Main.runBuild(Main.java:758)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String, [B, int, int, java.lang.ClassLoader, java.security.ProtectionDomain)
at java.base/java.lang.Class.getMethod(Class.java:2109)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.reflect.opt.Injector$3.run(Injector.java:186)
at [email protected]/com.sun.xml.internal.bind.v2.runtime.reflect.opt.Injector$3.run(Injector.java:182)
... 48 more
Question:
Is there any possibility, how I can bundle the JAXB libraries with OpenJDK 11?
Hint:
Using the xjb and schemagen tools on JDK 11 The JAXB-specific xjc and schemagen tools, which you use to convert an XML Schema (*. xsd file) to a set of Java classes and vice versa, are included with the JDK up to version 10, but have been removed in JDK 11.
JAXB was integrated within the JVM itself, so you didn't need to add any code dependency to have the functionality within your application. But with the modularization performed in JDK 9, it was removed as the maintainers wanted to have a smaller JDK distribution that only contains the core concepts.
Set up Eclipse for JAXB It is pretty simple. All you need to do is installing the plugins under category "Web, XML, Java EE and OSGi Enterprise Development" available in the release repository of your current Eclipse version. To do so select Help -> Install New Software... from the eclipse main menu bar.
XOM, JDOM, dom4j, etc. etc. Projects like Castor and Apache XMLBeans predate JAXB, so you could have a look at those. Ulf Dittmer wrote: XOM, JDOM, dom4j, etc.
Try to include these two dependencies:
implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.0'
implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With