Details
-
Type:
Bug
-
Status:
Open
-
Priority:
Minor
-
Resolution: Unresolved
-
Affects Version/s: 1.6-rc-3
-
Fix Version/s: None
-
Component/s: groovy-jdk, XML Processing
-
Labels:None
-
Environment:Groovy 1.6.0 RC3, Java 1.6.0_10
-
Number of attachments :0
Description
With Groovy versions 1.5.7 onwards there is a problem where Groovy loads
DOM classes from the Java SDK in its RootLoader constructor.
This makes it incompatible with XML parsing libraries having different
versions of DOM interfaces. For example, with Oracle XML Parser I get:
Caught: java.lang.LinkageError: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a different type with name "org/w3c/dom/NamedNodeMap"
$groovy -e "println javax.xml.parsers.DocumentBuilderFactory.newInstance().getClass()"
class oracle.xml.jaxp.JXDocumentBuilderFactory
$jar tvf ~/.groovy/lib/xmlparserv2-10.2.0.2.0.jar |grep "org/w3c/dom/NamedNodeMap"
581 Tue Dec 23 12:53:38 NZDT 2003 org/w3c/dom/NamedNodeMap.class
$jar tvf $JAVA_HOME/jre/lib/rt.jar |grep "org/w3c/dom/NamedNodeMap"
566 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/NamedNodeMap.class
This is caused by change r12189, comment:
adds a special hack for org.w3c.dom.Node, to avoid violation of class loader constraints
The troublesome lines are:
// major hack here...!
try
catch (Exception e) {}
If I undo this change in trunk, I get a version of Groovy which works happily
with the Oracle XML Parser.
For what it's worth, I need to use the Oracle XML Parser because it contains
code required by the Oracle XDK, required to use Oracle XML functionality in
the JDBC driver.
Activity
FWIW I stumbled upon this bug recently while using jedit 4.2 and Griffon 0.1-SNAPSHOT (based on groovy 1.6-rc1).
With the Console plugin enabled, ran the following system command: griffon install-plugin easyb
------------------------------------------------------------
This shell runs operating system processes.
Press TAB with an empty command line to list built-in commands.
Run built-in with --help argument to get a brief usage message.
Run %help to view Console plugin online help.
Errors generated by compilers and some other programs are listed
for easy one-click access in the 'Plugins->Error List->Error List'
window.
/tmp/Simple> griffon install easyb
Welcome to Griffon 0.1-SNAPSHOT - http://griffon.codehaus.org/
Licensed under Apache Standard License 2.0
Griffon home is set to: /usr/local/griffon
Base Directory: /tmp/Simple
Running pre-compiled script
Unable to load script 'Install' (error: Install)
Run 'griffon help' for a complete list of available scripts.
Process griffon exited with code 1
/tmp/Simple> griffon install-plugin easyb
Welcome to Griffon 0.1-SNAPSHOT - http://griffon.codehaus.org/
Licensed under Apache Standard License 2.0
Griffon home is set to: /usr/local/griffon
Base Directory: /tmp/Simple
Running script /usr/local/griffon/scripts/InstallPlugin.groovy
Environment set to development
Found events script in plugin rest-0.1
Configured HTTP proxy: www-proxy.us.oracle.com:80(andres.almiray)
Reading remote plug-in list ...
Error executing script InstallPlugin: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a different type with name "org/w3c/dom/Document"
java.lang.LinkageError: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a different type with name "org/w3c/dom/Document"
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.getDeclaredMethods(Class.java:1791)
at java.security.AccessController.doPrivileged(Native Method)
at org.codehaus.groovy.util.LazySoftReference.getLocked(LazySoftReference.java:28)
at org.codehaus.groovy.util.LazySoftReference.get(LazySoftReference.java:17)
at _PluginDependencies_groovy$_parsePluginList_closure27.doCall(_PluginDependencies_groovy:269)
at _PluginDependencies_groovy$_parsePluginList_closure27.doCall(_PluginDependencies_groovy)
at _GriffonSettings_groovy$_run_closure9.doCall(_GriffonSettings_groovy:220)
at _PluginDependencies_groovy.parsePluginList(_PluginDependencies_groovy:260)
at _PluginDependencies_groovy$_run_closure6.doCall(_PluginDependencies_groovy:225)
at _PluginDependencies_groovy$_run_closure6.doCall(_PluginDependencies_groovy)
at _PluginDependencies_groovy$_run_closure23.doCall(_PluginDependencies_groovy:494)
at _GriffonPlugins_groovy$_run_closure2.doCall(_GriffonPlugins_groovy:72)
at _GriffonPlugins_groovy$_run_closure2.doCall(_GriffonPlugins_groovy)
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:306)
at gant.Gant.dispatch(Gant.groovy:316)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:446)
at gant.Gant.processTargets(Gant.groovy:430)
Process griffon exited with code 1
/tmp/Simple>
there is of course a obvious workaround when using the groovy command and that is to put these jars in the bootloader instead of the RootLoader. So it should not go into $GROOVY_HOME/lib, but given as command line argument to the -cp option for the groovy command.
I tried your suggested workaround, specifying "-cp xmlparserv2-10.1.0.2.0.jar". It gave me the same error. (Using 1.6 RC-3.)
Maybe I don't understand how to apply this workaround. I think "-cp" is placing the class into the RootLoader, not the BootLoader.
I can report the class loader for NamedNodeMap with a script thus:
def printClassLoader(Class cls) {
ClassLoader loader = cls.classLoader
while (loader)
}
printClassLoader(org.w3c.dom.NamedNodeMap.class)
When I run this without options, I get no output. I believe this is because on my system the boot loader is returned as null from Class#getClassLoader().
When I run this script with "-cp xmlparserv2-10.1.0.2.0.jar", it outputs (among other things):
interface org.w3c.dom.NamedNodeMap
org.codehaus.groovy.tools.RootLoader@4741d6
class org.codehaus.groovy.tools.RootLoader
file:/home/hurstj/redx/lib/runtime/xmlparserv2-10.1.0.2.0.jar
This indicates to me that the class is now in the RootLoader. This won't fix the problem, right?
John Hurst
When I said "the class is now in the RootLoader", I should have been more clear.
The version I want is in the RootLoader, but the SDK version is still in the BootLoader. Thus the 1.5.7 patch loads the boot loader version.
John Hurst
true, I forgot, that that won't work. Now it is more clear to me why we did came up with that hack. Because in the issue I mentioned you could put the jaxen.jar in the bootloader and it would behave well, but that won't be easy using the groovy command alone. And for here it is really the opposite of what we want.
What I don't get atm is how that jar is normally used. For jaxen I know if it is in the same loader as the xml parser there is no problem. And if the loader is a normal one, then it is the same. Now for xmlparserv I am not allowed to use the parent loader because... well why? I guess because there are other classes that duplicate xml parser classes as well. Is there no xmlparserv2 without that part?
First off: Thanks very much for putting time into this issue. I feel like I ought to be paying you guys. You rock.
My understanding with the Oracle XML classes is that Oracle ships a back-level implementation of the Java DOM APIs. Thus, the interfaces are older versions than those in the current JDK, and the implementations do not necessarily implement all the required signatures in the current JDK. Thus the incompatibility.
The Oracle JAR includes classes/interfaces from
javax.xml.parsers
javax.xml.transform
javax.xml.namespace
org.w3c.dom
org.xml.sax
oracle.xml
The javax and org.w3c classes/interfaces mirror JDK classes/interfaces, but are different versions. For example, from JDK 1.6.0_10:
432 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/Attr.class
141 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/CDATASection.class
558 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/CharacterData.class
140 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/Comment.class
445 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/DOMConfiguration.class
470 Fri Sep 26 01:26:44 NZST 2008 org/w3c/dom/DOMError.class
173 Fri Sep 26 01:26:44 NZST 2008 org/w3c/dom/DOMErrorHandler.class
1078 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/DOMException.class
561 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/DOMImplementation.class
213 Fri Sep 26 01:26:44 NZST 2008 org/w3c/dom/DOMImplementationList.class
317 Fri Sep 26 01:26:44 NZST 2008 org/w3c/dom/DOMImplementationSource.class
306 Fri Sep 26 01:26:44 NZST 2008 org/w3c/dom/DOMLocator.class
227 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/DOMStringList.class
2096 Fri Sep 26 01:22:26 NZST 2008 org/w3c/dom/Document.class
...
From xmlparserv2,jar:
387 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/Attr.class
159 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/CDATASection.class
583 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/CharacterData.class
158 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/Comment.class
385 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMConfiguration.class
452 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMError.class
244 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMErrorHandler.class
951 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMException.class
506 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMImplementation.class
238 Mon Nov 10 15:17:48 NZDT 2003 org/w3c/dom/DOMImplementationList.class
342 Mon Nov 10 15:17:48 NZDT 2003 org/w3c/dom/DOMImplementationSource.class
331 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMLocator.class
209 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/DOMStringList.class
1500 Mon Nov 10 15:17:46 NZDT 2003 org/w3c/dom/Document.class
...
The oracle.xml classes are, of course, the Oracle implementations.
If I try to run my application, using Oracle XML dev kit, without the Oracle XML classes, I get
Caught: java.lang.NoClassDefFoundError: oracle/xml/parser/v2/XMLParseException
This class is in xmlparserv2.jar.
I could try to create a JAR with just the Oracle implementation classes, and not the interfaces. I suspect it would not work, because the implementations would not be compatible with the JDK interfaces.
Obviously, a good solution for this would be if Oracle updated their package to include the latest DOM APIs! The latest version of Oracle XML Developer's kit I can find is 10.2.0.2.0, dated 2006-03-31, and this has DOM API versions similar to the one I've been using.
Thanks for your suggestions.
John Hurst
I tried removing the standard javax.xml/dom/sax/ interfaces and classes from Oracle's xmlparserv2.jar. Hey, it worked! This is good enough for me. (I thought that the class load/validation was stricter than it is.)
If anyone wants to do the same, here is an Ant step to create your new JAR:
<!-- Create xmlparserv2-local: with SDK classes/interfaces omitted, works better with Groovy 1.5.7+. -->
<!-- See http://jira.codehaus.org/browse/GROOVY-3356 -->
<jar destfile="xmlparserv2-local.jar">
<zipfileset src="xmlparserv2.jar">
<exclude name="javax/**"/>
<exclude name="org/w3c/**"/>
<exclude name="org/xml/**"/>
</zipfileset>
<zipfileset src="xmlparserv2.jar">
<include name="org/w3c/dom/validation/*.class"/>
</zipfileset>
</jar>
I found that I needed to include org.w3c.dom.validation.*; those aren't present in my JDK.
Thanks!
John Hurst
I have a similar problem with html-unit-2.4. Being new to java and groovy, I really have no idea what this means. I'm getting this message:
Caught: java.lang.LinkageError: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a different type with name "org/w3c/dom/NamedNodeMap"
at groovy1.run(groovy1.grv:4)
from this program:
import com.gargoylesoftware.htmlunit.WebClient;
def webClient = new WebClient()
def page = webClient.getPage('http://www.google.com')
// check page title
assert 'Google' == page.titleText
// fill in form and submit it
def form = page.getFormByName('f')
def field = form.getInputByName('q')
field.setValueAttribute('Groovy')
def button = form.getInputByName('btnG')
def result = button.click()
// check groovy home page appears in list (assumes it's on page 1)
assert result.anchors.any
The HtmlUnit 2.4 download package includes a bunch of JARs, including xml-apis-1.3.04.jar. This JAR includes the NamedNodeMap class, in a different version from JDK 1.6.0. I tried your program after removing this JAR from the classpath, and that fixes it.
(Move it out of the directory if your app is including all JARs in a directory in the classpath. E.g. you may have put the JAR in ~/.groovy/lib/.)
John Hurst
Wellington, New Zealand
Thanks John! I wasn't expecting such a timely response.
That change you mentioned did get me past the problem.
Got warning message
Feb 20, 2009 8:39:48 PM com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl
notify
WARNING: Obsolete content type encountered: 'text/javascript'.
But, I think the script did what it was supposed to do.
I've had a hard time finding examples for htmlunit. There seems to be a lot more for httpunit, which I presume is a predecessor. If anyone could point me in the right direction, I'd be much obliged.
For what it's worth I'm using the work around described here:
http://www.jroller.com/hasant/entry/how_to_change_oracle_xml
The difference is that I'm substituting the META-INF/services from the newer xerces and xalan and not the classes specified in the article. This works fine for me and I can use the XDB XMLType in my code. The other applications on the server seem perfectly fine with this substitution.
Caught: java.lang.LinkageError: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a different type with name "org/w3c/dom/NamedNodeMap"
I'm having this problem with groovy and htmlunit-2.6. In the past, I've simply deleted the xml-apis-1.3.04.jar file from the groovy lib directory, but this isn't working anymore.
java version "1.6.0_17"
Groovy Version: 1.6-RC-3 JVM: 1.6.0_01
htmlunit-2.6
@zuzum2:
You may need to find out where in your classpath you have org/w3c/dom/NamedNodeMap, and thus look for clashes.
Also, have you tried a more recent Groovy?
John Hurst
I've encountered this with Groovy 1.7.5 when trying to use HTMLUnit 2.8.
/usr/lib/jvm/java-6-sun/bin/java -Dtools.jar=/usr/lib/jvm/java-6-sun/lib/tools.jar -Dgroovy.home=/home/ondra/.m2/repository/org/codehaus/groovy/groovy-all/1.7.5 -Dgroovy.starter.conf=/home/ondra/Plocha/idea-IU-103.255/plugins/Groovy/lib/groovy-starter.conf -Didea.launcher.port=7535 -Didea.launcher.bin.path=/home/ondra/Plocha/idea-IU-103.255/bin -Dfile.encoding=UTF-8 -classpath /home/ondra/.m2/repository/org/codehaus/groovy/groovy-all/1.7.5/groovy-all-1.7.5.jar:/home/ondra/Plocha/idea-IU-103.255/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain org.codehaus.groovy.tools.GroovyStarter --conf /home/ondra/Plocha/idea-IU-103.255/plugins/Groovy/lib/groovy-starter.conf --main groovy.ui.GroovyMain --classpath /home/ondra/work/JON/scripts/JonGroovyInstaller/target/classes:/home/ondra/.m2/repository/net/sourceforge/htmlunit/htmlunit/2.8/htmlunit-2.8.jar:/home/ondra/.m2/repository/xalan/xalan/2.7.1/xalan-2.7.1.jar:/home/ondra/.m2/repository/xalan/serializer/2.7.1/serializer-2.7.1.jar:/home/ondra/.m2/repository/xml-apis/xml-apis/1.3.04/xml-apis-1.3.04.jar:/home/ondra/.m2/repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar:/home/ondra/.m2/repository/commons-lang/commons-lang/2.4/commons-lang-2.4.jar:/home/ondra/.m2/repository/org/apache/httpcomponents/httpclient/4.0.1/httpclient-4.0.1.jar:/home/ondra/.m2/repository/org/apache/httpcomponents/httpcore/4.0.1/httpcore-4.0.1.jar:/home/ondra/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/home/ondra/.m2/repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar:/home/ondra/.m2/repository/org/apache/httpcomponents/httpmime/4.0.1/httpmime-4.0.1.jar:/home/ondra/.m2/repository/org/apache/james/apache-mime4j/0.6/apache-mime4j-0.6.jar:/home/ondra/.m2/repository/net/sourceforge/htmlunit/htmlunit-core-js/2.8/htmlunit-core-js-2.8.jar:/home/ondra/.m2/repository/xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar:/home/ondra/.m2/repository/net/sourceforge/nekohtml/nekohtml/1.9.14/nekohtml-1.9.14.jar:/home/ondra/.m2/repository/net/sourceforge/cssparser/cssparser/0.9.5/cssparser-0.9.5.jar:/home/ondra/.m2/repository/org/w3c/css/sac/1.3/sac-1.3.jar:/home/ondra/.m2/repository/commons-io/commons-io/1.4/commons-io-1.4.jar:/home/ondra/.m2/repository/org/codehaus/groovy/groovy-all/1.7.5/groovy-all-1.7.5.jar /home/ondra/work/JON/scripts/JonGroovyInstaller/src/main/groovy/test.groovy http://amd-toonie2-01.rhts.eng.bos.redhat.com:7080/
Caught: java.lang.LinkageError: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a different type with name "org/w3c/dom/NamedNodeMap"
at org.jboss.jon.qa.test.run(test.groovy:12)
But now I got the same error, only this time it's Ant, brought in by Maven.
loader (instance of org/codehaus/classworlds/RealmClassLoader) previously initiated loading for a different type with name "org/apache/tools/ant/Project"
For the record, still occurs w Groovy 1.8.1. I had to remove the offending jar from my classpath, which for me was xml-apis-1.3.04.jar
this XML parser stuff is really a PITA. I added that hack to avoid problems with class loading and in your case it is causing exactly that. You can find the discussion from back in http://markmail.org/message/hn3tv6s2jeyjslcb#query:org.w3c.dom.Node%20rootloader+page:1+mid:5nw3tlvar5pmcmc4+state:results
related issues are
GROOVY-2303andGANT-34