Menu

Trouble parsing XML-RPC response

Halcyon
2006-11-27
2013-04-25
  • Halcyon

    Halcyon - 2006-11-27

    I'm attempting to use Redstone 1.0 (have also tried 1.0.1) in a Spring/Spring WebFlow project.  When my code invokes the XML-RPC call, I receive the following exception:

    redstone.xmlrpc.XmlRpcException: The response could not be parsed.
            at redstone.xmlrpc.XmlRpcClient.handleResponse(Unknown Source)
            at redstone.xmlrpc.XmlRpcClient.endCall(Unknown Source)
            at redstone.xmlrpc.XmlRpcClient.invoke(Unknown Source)
            ...
    Caused by: redstone.xmlrpc.XmlRpcException: Could not instantiate XMLReader parser
            at redstone.xmlrpc.XmlRpcParser.parse(Unknown Source)
            ...
    Caused by: java.lang.ClassNotFoundException: org.apache.xerces.parsers.SAXParser
            at org.xml.sax.helpers.XMLReaderFactory.loadClass(XMLReaderFactory.java:189)
            at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(XMLReaderFactory.java:150)
            ...

    Thinking that I needed to specifically include the Xerces 2 libraries in my JAR, I did so and received the same error.  Then I realized that Xerces 2 does not have a "org.apache.xerces.parsers.SAXParsers" class, however, Xerces 1 does.  Upon including Xerces 1 in my JAR, it causes my Spring framework to fail since it requires features available in Xerces 2.

    For context, here's a snippet of my code:
    ----------------------------------------
    Vector xmlRpcAttrbs = new Vector();
    XmlRpcClient xmlRpcClient = null;
                                           
    xmlRpcAttrbs = new Vector();
    xmlRpcAttrbs.addElement("...");
    xmlRpcAttrbs.addElement("...");

    try{
        xmlRpcClient = new XmlRpcClient( "http://crow.csun.edu:65533", false );
        Object token = xmlRpcClient.invoke( "add_service", xmlRpcAttrbs );
    }
    catch(MalformedURLException mue){ log.error("", mue); }
    catch(XmlRpcFault xpf){ log.error("", xpf); }
    catch(XmlRpcException xre){ log.error("", xre); }
    catch(Exception e){ log.error("", e ); }
    ----------------------------------------

    Error is thrown on the "xmlRpcClient.invoke" line.  Is there a way to tell Redstone to use "javax.xml.parsers.SAXParser" instead of "org.apache.xerces.parsers.SAXParser"?

     
    • Greger Ohlson

      Greger Ohlson - 2006-11-27

      Hi,

      The XmlRpcParser in the Redstone library uses XMLReaderFactory.createXMLReader()
      to instantiate the SAX parser. Normally this would mean that the default SAX
      parser in the JDK is used, but in your case this is not working for some reason.
      Which Java SDK and JRE are you using?

      You should be able to explicitly set the name of the parser you want to use
      by setting the system property "org.xml.sax.driver";

      System.setProperty( "org.xml.sax.driver", "fully.qualified.name.of.Parser" );

      This should be done at some point, prior to using the XML-RPC library. The
      following JUnit test case works for me out of the box, without specifying
      the system property. You can use it to test your settings.

      import java.io.ByteArrayInputStream;
      import java.io.InputStream;
      import junit.framework.TestCase;

      public class XmlRpcParserTest extends TestCase
      {   
          public XmlRpcParserTest( String name )
          {
              super( name );
          }
        
          final public void testParse() throws Exception
          {
              String message =
                  "<?xml version=\&quot;1.0\&quot;?>" +
                  "<methodCall>" +
                      "<methodName>examples.getStateName</methodName>" +
                      "<params>" +
                          "<value>" +
                              "<struct>" +
                                  "<member>" +
                                      "<name>integer</name>" +
                                      "<value><i4>42</i4></value>" +
                                  "</member>" +
                                  "<member>" +
                                      "<name>double</name>" +
                                      "<value><double>3.14</double></value>" +
                                  "</member>" +
                              "</struct>" +
                          "</value>" +
                      "</params>" +
                  "</methodCall>";
             
              InputStream input =  new ByteArrayInputStream(  message.getBytes() );
              XmlRpcParser parser = new TestParser();

              parser.parse( input );
              assertTrue( parsedValue != null );
              assertTrue( parsedValue instanceof XmlRpcStruct );
             
              XmlRpcStruct struct = ( XmlRpcStruct ) parsedValue;
              assertEquals( struct.get( "integer" ), new Integer( 42 ) );
              assertEquals( struct.get( "double" ), new Double( 3.14 ) );
          }

          class TestParser extends XmlRpcParser
          {
              /* (non-Javadoc)
               * @see marquee.xmlrpc.XmlRpcParser#handleParsedValue(java.lang.Object)
               */
              
              protected void handleParsedValue( Object value )
              {
                  parsedValue = value;
              }
          }
             
          /** The value parsed by the XmlRpcParser. */
          private Object parsedValue;
      }

      Regards,
      Greger.

       
    • Halcyon

      Halcyon - 2006-11-27

      Well, when I output the system property for the SAX driver before doing a "setProperty" I get "org.apache.xerces.parsers.SAXParser".  I'm using 1.5 for JDK and JRE in development.

      When I set the SAX driver with System.setProperty("org.xml.sax.driver", "javax.xml.parsers.SAXParser"), I get a new error:

      Caused by: java.lang.IllegalAccessException: Class org.xml.sax.helpers.NewInstance can not access a member of class javax.xml.parsers.SAXParser with modifiers "protected"

       
      • Greger Ohlson

        Greger Ohlson - 2006-11-28

        I get null when I output "org.xml.sax.driver" by default (when everything is working), and I get the same
        error as you get if I set it to "org.apache.xerces.parsers.SAXParser". I'm also using Java SE 5. Can you
        please try to clear the property:

          System.clearProperty( "org.xml.sax.driver" );

        And then try again. It sounds strange but I think that might work since it should fall back on the default
        parser shipped with Java SE 5.

        Regards,
        Greger.

         
    • Halcyon

      Halcyon - 2006-11-27

      I also tried:

      System.setProperty( "org.xml.sax.driver", "org.xml.sax.Parser" );

      which returns:

      Caused by: redstone.xmlrpc.XmlRpcException: Could not instantiate XMLReader parser
              at redstone.xmlrpc.XmlRpcParser.parse(Unknown Source)
              ... 51 more
      Caused by: java.lang.InstantiationException: org.xml.sax.Parser
              at org.xml.sax.helpers.XMLReaderFactory.loadClass(XMLReaderFactory.java:195)
              at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(XMLReaderFactory.java:150)

       
    • Halcyon

      Halcyon - 2006-11-29

      Well, that does give me a different error:

      redstone.xmlrpc.XmlRpcFault: Invalid type conversion
              at redstone.xmlrpc.XmlRpcClient.handleResponse(Unknown Source)
              at redstone.xmlrpc.XmlRpcClient.endCall(Unknown Source)
              at redstone.xmlrpc.XmlRpcClient.invoke(Unknown Source)
              ...

      However, I'm not casting the response to anything yet, simply setting it to type Object:

      Object token = xmlRpcClient.invoke( "add_service", xmlRpcAttrbs );

      The only thing I can think of is that my "xmlRpcAttrbs" object is of type Vector.  A co-worker of mine who is also using Redstone (without the Spring/Spring WebFlow frameworks) uses Vector and does not experience this same error.  I've tried this code with 1.0 and 1.0.1 and the error is the same.

       
      • Greger Ohlson

        Greger Ohlson - 2006-11-30

        Hi,

        OK it seems the problem with your SAX parser is solved. The default parser in the Java SE 5
        is now being used.

        Regarding your new problem; since your xmlRpcAttrbs argument is a Vector which implements
        the java.util.Collection interface, it is serializable by the framework by default, so there
        is no problem there. The XmlRpcFault gives us a clue as to what is going on; the XmlRpcFault
        exception is thrown on the client side to reflect problems that occur on the server side.
        If, for example, there was a problem with the network connection, or if the server responded
        with unparsable garbage, or if you supply an argument which cannot by default be serialized
        by the XmlRpcClient, and XmlRpcException would have been thrown. But since an XmlRpcFault
        is thrown it means that something has gone wroing in the server and an XML-RPC Fault has
        been returned.

        I think your problem might be this;

          1. The XmlRpcClient has two versions of invoke:
             XmlRpcClient.invoke( String method, Object[] arguments ) and
             XmlRpcClient.invoke( String method, List arguments );

          2. You are using the second version of invoke() when you supply your Vector in the call.
             What is happening here is that XmlRpcClient thinks that the elements in your Vector
             are the argument*s* that should be passed to add_service.

        I suspect that you actually want to pass the Vector as a single XML-RPC list argument
        to add_service, in which case you must do this;

             Object token = xmlRpcClient.invoke( "add_service", new Object[] { xmlRpcAttrbs } );

        In other words, you invoke add_service with a single argument which is the Vector which
        will be serialized into an XML-RPC array and deserialized at the terminating end to
        whatever type representation the implementation is useing for arrays. As it stands now
        the add_service method must have as many parameters as there are elements in your
        Vector.

        Regards,
        Greger.

         
        • Halcyon

          Halcyon - 2006-11-30

          The "add_service" method on the server side takes 5 parameters, all strings.  So my Vector contains 5 elements of type String.  I'm trying to pass each of those elements as parameters to "add_service".  That's why I'm not passing one object of type Vector.  I'll have to see what level of debugging I can get from the server... maybe I can find out more from there.  Thanks for your input Greger.. I appreciate you taking the time to look into my issue!

           
    • Halcyon

      Halcyon - 2006-11-30

      Is there a way to output the raw response from the XML-RPC server?  I'd like to see what the actual response is.  I recompiled the XML-RPC client source to include debugging information and it seems as though the error thrown is related to the actual parameters that I'm sending to the remote method.  I'd like to see if "Invalid type conversion" is coming from the server or if it's something Redstone is throwing due to an odd response from the server.

       
      • Greger Ohlson

        Greger Ohlson - 2006-11-30

        Unfortunately not. However, as explained in the previous post; sice you are getting
        and XmlRpcFault you can be certain that the fault is on the server side. The XML-RPC
        message that has been received contains an XML-RPC Fault struct containing the
        "Invalid type conversion" string as faultString. I'd recommend looking on the server
        side to see if any errors are visible if you get further XmlRpcFaults.

        Cheers,
        Greger.

         

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.