groovy
  1. groovy
  2. GROOVY-2126

ClassCastException when using java.util.prefs package

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0
    • Fix Version/s: 1.1-rc-1
    • Component/s: XML Processing
    • Labels:
      None
    • Environment:
      tested on Mac OS X 10.4.10 with java version 1.5.0_07 and Fedora Core 5 (2.6.20-1.2320.fc5smp) with java version: 1.5.0_11
    • Testcase included:
      yes
    • Number of attachments :
      0

      Description

      The following code throws a java.lang.ClassCastException when run as a Groovy script, the same code compiled with groovyc and executed with java runs correctly.

      #prefsTest.groovy
      import java.util.prefs.*;
      def prefs = Preferences.userNodeForPackage(this.getClass());
      prefs.exportSubtree(System.out);
      #end prefsTest.groovy

      Test using the following:
      $ groovy prefsTest.groovy
      Caught: java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
      at prefsTest.run(prefsTest.groovy:4)
      at prefsTest.main(prefsTest.groovy)
      $groovyc prefsTest.groovy
      $java -cp .:$GROOVY_HOME/embeddable/groovy-all-1.0.jar prefsTest
      WARNING: Prefs file removed in background /home/mkennedy/.java/.userPrefs/<unnamed>/prefs.xml
      <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
      <preferences EXTERNAL_XML_VERSION="1.0"><root type="user"><map/><node name="<unnamed>"><map/></node></root></preferences>

      I'm not sure what causes this, I discovered it when converting some java code to Groovy that imports an xml preferences file and I reduced the case to this to reproduce the behavior in a clean environment.

      I apologize for the trouble if this is some stupid error on my part that I'm just not seeing my way around.

        Activity

        Hide
        blackdrag blackdrag added a comment -

        could you please try to remove the xerxes and xalan jars from the lib directory of groovy and then run it again? I think that will solve your problem

        Show
        blackdrag blackdrag added a comment - could you please try to remove the xerxes and xalan jars from the lib directory of groovy and then run it again? I think that will solve your problem
        Hide
        Matt Kennedy added a comment -

        Thanks for the guidance on this, for others that might read this, here is what eventually solved the issue:

        As per Jochen's suggestion, I removed xerces, though there was no obvious xalan jar in the groovy/lib directory I had, but I also had a file called 'groovysoap-all-1.0-0.3-snapshot_jdk1.5.0.jar' that doesn't seem to be in the current groovy-1.0 distribution so it must have been something I added. At any rate, it has xalan in it, so removing it solved the problem.

        Show
        Matt Kennedy added a comment - Thanks for the guidance on this, for others that might read this, here is what eventually solved the issue: As per Jochen's suggestion, I removed xerces, though there was no obvious xalan jar in the groovy/lib directory I had, but I also had a file called 'groovysoap-all-1.0-0.3-snapshot_jdk1.5.0.jar' that doesn't seem to be in the current groovy-1.0 distribution so it must have been something I added. At any rate, it has xalan in it, so removing it solved the problem.
        Hide
        Matt Kennedy added a comment -

        I'm reopening this issue in hopes of finding a workaround that will let me continue using Groovy 1.0. Below is a quick addition to the script I posted originally that seems to show that the workaround provided (removing xerces and xalan) will allow java.util.Preferences objects to work with XML, but seems to break other xml functionality.

        #prefsTest.groovy
        import java.util.prefs.*;
        import javax.xml.parsers.DocumentBuilderFactory;

        def prefs = Preferences.userNodeForPackage(this.getClass());
        prefs.exportSubtree(System.out);
        println '';
        println DocumentBuilderFactory.newInstance().getClass()

        $groovy prefsTest.groovy
        <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
        <preferences EXTERNAL_XML_VERSION="1.0"><root type="user"><map/><node name="<unnamed>"><map/></node></root></preferences>
        Caught: javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found
        at prefsTest.run(prefsTest.groovy:7)
        at prefsTest.main(prefsTest.groovy)

        Is there a way to set a Provider for the DocumentBuilderFactory that won't cause the original ClassCastException when using the xml methods in a prefs object?

        Show
        Matt Kennedy added a comment - I'm reopening this issue in hopes of finding a workaround that will let me continue using Groovy 1.0. Below is a quick addition to the script I posted originally that seems to show that the workaround provided (removing xerces and xalan) will allow java.util.Preferences objects to work with XML, but seems to break other xml functionality. #prefsTest.groovy import java.util.prefs.*; import javax.xml.parsers.DocumentBuilderFactory; def prefs = Preferences.userNodeForPackage(this.getClass()); prefs.exportSubtree(System.out); println ''; println DocumentBuilderFactory.newInstance().getClass() $groovy prefsTest.groovy <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"> <preferences EXTERNAL_XML_VERSION="1.0"><root type="user"><map/><node name="<unnamed>"><map/></node></root></preferences> Caught: javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found at prefsTest.run(prefsTest.groovy:7) at prefsTest.main(prefsTest.groovy) Is there a way to set a Provider for the DocumentBuilderFactory that won't cause the original ClassCastException when using the xml methods in a prefs object?
        Hide
        blackdrag blackdrag added a comment -

        sorry, I have a small problem in understanding... you did not remove the jars and want to get it working somehow? The flaw is, that java system itself has a parser and does normally load it from there, groovy comes with a parser and prefers that one over the parser from java system. But since loading the parser will use a class from the java system part and a class from the jars of groovy, that duplicates this class. The result is the ClassCastException. That's why suggested removing the jar, because there is no conflict then. removing the jar from RootLoader would work too, but I think there is no method to do something like that.... and in the end it would be the same. The cause for the duplication is the way RootLoader works... it is fine for all things but the xml parser. I am not sure about that, but I guess there is no usable way.

        Show
        blackdrag blackdrag added a comment - sorry, I have a small problem in understanding... you did not remove the jars and want to get it working somehow? The flaw is, that java system itself has a parser and does normally load it from there, groovy comes with a parser and prefers that one over the parser from java system. But since loading the parser will use a class from the java system part and a class from the jars of groovy, that duplicates this class. The result is the ClassCastException. That's why suggested removing the jar, because there is no conflict then. removing the jar from RootLoader would work too, but I think there is no method to do something like that.... and in the end it would be the same. The cause for the duplication is the way RootLoader works... it is fine for all things but the xml parser. I am not sure about that, but I guess there is no usable way.
        Hide
        Matt Kennedy added a comment -

        I'm sorry, I should have been more clear, I did remove the jars as suggested, which fixes the call to prefs.exportSubtree(System.out) - but if I then try to call DocumentBuilderFactory.newInstance(), it will fail with the following exception:

        Caught: javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found
        at prefsTest.run(prefsTest.groovy:7)
        at prefsTest.main(prefsTest.groovy)

        ...which happens because the jars have been removed. Setting the system property for javax.xml.parsers.DocumentBuilderFactory to anything other than the included xerces parser seems to cause a ClassCastException.

        I did manage to find a workaround though that allows me to continue working with Groovy 1.0 that only requires a small code workaround, which is as follows:

        1. Do not remove any of the files from the groovy-1.0/lib directory.
        2. Before calling any of the methods of the Preferences class that deal with xml (Preferences.exportSubtree() or Preferences.importPreferences for example... This may also apply to other standard Java API classes that use xml) use:
        System.setProperty('javax.xml.parsers.DocumentBuilderFactory','com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl');

        ...to bypass the xml parser included in Groovy. Once finished with the offending calls, use:
        System.setProperty('javax.xml.parsers.DocumentBuilderFactory','org.apache.xerces.jaxp.DocumentBuilderFactoryImpl');

        ...to reset the parser factory back to its original setting.

        This workaround allows me to continue to use Groovy 1.0 (and hence the eclipse plugin) so as far as I'm concerned the issue is closed, but I will leave it open in the issue tracker in case you have further comments on it. Feel free to close it if you don't. I did notice that Guillaume Laforge changed the fixed version from 1.1-beta2 to rc1, I just thought I should mention that I have tested it under beta 2 and my code did work, but I haven't tested it under rc1 at all.

        Thank you for your input in helping me solve this problem.

        Show
        Matt Kennedy added a comment - I'm sorry, I should have been more clear, I did remove the jars as suggested, which fixes the call to prefs.exportSubtree(System.out) - but if I then try to call DocumentBuilderFactory.newInstance(), it will fail with the following exception: Caught: javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found at prefsTest.run(prefsTest.groovy:7) at prefsTest.main(prefsTest.groovy) ...which happens because the jars have been removed. Setting the system property for javax.xml.parsers.DocumentBuilderFactory to anything other than the included xerces parser seems to cause a ClassCastException. I did manage to find a workaround though that allows me to continue working with Groovy 1.0 that only requires a small code workaround, which is as follows: 1. Do not remove any of the files from the groovy-1.0/lib directory. 2. Before calling any of the methods of the Preferences class that deal with xml (Preferences.exportSubtree() or Preferences.importPreferences for example... This may also apply to other standard Java API classes that use xml) use: System.setProperty('javax.xml.parsers.DocumentBuilderFactory','com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl'); ...to bypass the xml parser included in Groovy. Once finished with the offending calls, use: System.setProperty('javax.xml.parsers.DocumentBuilderFactory','org.apache.xerces.jaxp.DocumentBuilderFactoryImpl'); ...to reset the parser factory back to its original setting. This workaround allows me to continue to use Groovy 1.0 (and hence the eclipse plugin) so as far as I'm concerned the issue is closed, but I will leave it open in the issue tracker in case you have further comments on it. Feel free to close it if you don't. I did notice that Guillaume Laforge changed the fixed version from 1.1-beta2 to rc1, I just thought I should mention that I have tested it under beta 2 and my code did work, but I haven't tested it under rc1 at all. Thank you for your input in helping me solve this problem.
        Hide
        Matt Kennedy added a comment -

        Here is the original test case script with the fix implemented:

        import java.util.prefs.*;
        import javax.xml.parsers.DocumentBuilderFactory;

        System.setProperty('javax.xml.parsers.DocumentBuilderFactory','com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl');

        def prefs = Preferences.userNodeForPackage(this.getClass());
        prefs.exportSubtree(System.out);
        System.setProperty('javax.xml.parsers.DocumentBuilderFactory','org.apache.xerces.jaxp.DocumentBuilderFactoryImpl');
        println '';
        println DocumentBuilderFactory.newInstance().getClass()

        Show
        Matt Kennedy added a comment - Here is the original test case script with the fix implemented: import java.util.prefs.*; import javax.xml.parsers.DocumentBuilderFactory; System.setProperty('javax.xml.parsers.DocumentBuilderFactory','com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl'); def prefs = Preferences.userNodeForPackage(this.getClass()); prefs.exportSubtree(System.out); System.setProperty('javax.xml.parsers.DocumentBuilderFactory','org.apache.xerces.jaxp.DocumentBuilderFactoryImpl'); println ''; println DocumentBuilderFactory.newInstance().getClass()
        Hide
        Paul King added a comment -

        Added a Troubleshooting section to the Processing XML page on the wiki to document this workaround.

        Show
        Paul King added a comment - Added a Troubleshooting section to the Processing XML page on the wiki to document this workaround.

          People

          • Assignee:
            Paul King
            Reporter:
            Matt Kennedy
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: