Results 1 to 5 of 5
  1. #1
    rude056 is offline Member
    Join Date
    Sep 2010
    Posts
    3
    Rep Power
    0

    Exclamation multiple response parameters in apache axis are not all not returned

    Hi all,

    I'm having an issue parsing a soap response message with multiple output
    parameters:
    An example of the soap response msg (notice it contains 4 sub nodes)
    Java Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="
    http://www.w3.org/2001/XMLSchema-instance">
     <soap:Body>
      <error xmlns="http://testcase/itpserver/wsdl">OK</error>
      <outKeyValues xmlns="http://testcase/itpserver/wsdl">
       <KeyValue>
        <key>Email</key>
        <value/>
       </KeyValue>
       <KeyValue>
        <key>Printer</key>
        <value/>
       </KeyValue>
      </outKeyValues>
      <outDocuments xmlns="http://testcase/itpserver/wsdl">
       <Doc>
        <id>PDF</id>
        <content>JVBERi0xLjQNJf////8NMSAwIG9iag08PA...</content>
       </Doc>
      </outDocuments>
      <progress xmlns="http://testcase/itpserver/wsdl"/>
     </soap:Body>
    </soap:Envelope>
    Problem is that the call.getOutputParams method returns a Map with only
    the first node directly under the soap body. I would expect that all 4 the
    subnodes are present in the returned Map. (the errorNode is in the Map)

    I have looked in to the source of the axis code how that map is filled and
    descovered the following:
    // call.invoke ==> soapenvelope.getfirstbody ==> body.getfirstboy ==>
    getChildren().get(0)!!! (see SOAPBODY.getFirstBody)
    ==> this confirms the result of my test case
    I expected however that the map contains ALL output parameters from the
    response body.
    Does anybody know what is going on here, why not put all these params in
    the Map, or is it a bug???

    The test code:
    Java Code:
    package client;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.rmi.RemoteException;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Vector;
    
    import javax.xml.rpc.ServiceException;
    
    import org.apache.axis.AxisFault;
    import org.apache.axis.Message;
    import org.apache.axis.client.Call;
    import org.apache.axis.client.Service;
    import org.apache.axis.description.OperationDesc;
    import org.apache.axis.description.ParameterDesc;
    import org.apache.axis.utils.XMLUtils;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import client.util.Base64;
    
    import com.testcase.www.itpserver.wsdl.ArrayOfDoc;
    import com.testcase.www.itpserver.wsdl.ArrayOfKeyValue;
    import com.testcase.www.itpserver.wsdl.ArrayOfString;
    import com.testcase.www.itpserver.wsdl.Doc;
    import com.testcase.www.itpserver.wsdl.KeyValue;
    
    public class testClient {
    
            private static String endPoint = "http://pcwin7:8080/?WSDL";
    //      private static String endPoint = "http://pcwin7:8082/";
     
            public static void main(String[] args) { 
                    try {
                            Service service = new Service();
                            service.setTypeMappingVersion("1.2");
     
                            OperationDesc oper = new 
    org.apache.axis.description.OperationDesc();
                        oper.setName("SubmitEx");
                        ParameterDesc param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "service"), 
    org.apache.axis.description.ParameterDesc.IN, new 
    javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), 
    java.lang.String.class, false, false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "parms"), 
    org.apache.axis.description.ParameterDesc.IN, new 
    javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", 
    "ArrayOfString"), com.testcase.www.itpserver.wsdl.ArrayOfString.class, 
    false, false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "inKeyValues"), 
    org.apache.axis.description.ParameterDesc.IN, new 
    javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", 
    "ArrayOfKeyValue"), com.testcase.www.itpserver.wsdl.ArrayOfKeyValue.class, 
    false, false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "inDocuments"), 
    org.apache.axis.description.ParameterDesc.IN, new 
    javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", 
    "ArrayOfDoc"), com.testcase.www.itpserver.wsdl.ArrayOfDoc.class, false, 
    false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "error"), 
    org.apache.axis.description.ParameterDesc.OUT, new 
    javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), 
    java.lang.String.class, false, false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "outKeyValues"), 
    org.apache.axis.description.ParameterDesc.OUT, new 
    javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", 
    "ArrayOfKeyValue"), com.testcase.www.itpserver.wsdl.ArrayOfKeyValue.class, 
    false, false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "outDocuments"), 
    org.apache.axis.description.ParameterDesc.OUT, new 
    javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", 
    "ArrayOfDoc"), com.testcase.www.itpserver.wsdl.ArrayOfDoc.class, false, 
    false);
                        oper.addParameter(param);
                        param = new 
    org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("
    http://www.testcase.com/itpserver/wsdl", "progress"), 
    org.apache.axis.description.ParameterDesc.OUT, new 
    javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", 
    "ArrayOfString"), com.testcase.www.itpserver.wsdl.ArrayOfString.class, 
    false, false);
                        oper.addParameter(param);
     oper.setReturnType(org.apache.axis.encoding.XMLType.AXIS_VOID);
     oper.setStyle(org.apache.axis.constants.Style.DOCUMENT);
                        oper.setUse(org.apache.axis.constants.Use.LITERAL);   
     
                            Call call = (Call)service.createCall();
                            call.setOperation(oper); 
                            call.setTargetEndpointAddress( new 
    java.net.URL(endPoint) );
                    call.setUseSOAPAction(true);
                    call.setSOAPActionURI("
    http://www.testcase.com/itpserver/wsdl/SubmitEx");
                    call.setEncodingStyle(null);
     call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, 
    Boolean.FALSE);
     call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, 
    Boolean.FALSE);
     call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
                    call.setOperationName(new javax.xml.namespace.QName("", 
    "SubmitEx"));
     
                            String theService = "CreateDocument";
                            ArrayOfString parms = new ArrayOfString(); // not 
    used
                            ArrayOfKeyValue inKeyValues = new 
    ArrayOfKeyValue();
                            inKeyValues.setKeyValue(new KeyValue[]{new 
    KeyValue("Email", "rude@sofico.be")}) ;
                            ArrayOfDoc inDocuments = new ArrayOfDoc();
                            inDocuments.setDoc(new Doc[]{new Doc("Data", new 
    byte[0])});
     
                            String ret = (String) call.invoke( new 
    Object[]{theService, parms, inKeyValues, inDocuments} );
     
                            // 1.log response msg ==> this message shows that 
    there are 4 elements:
                            // error
                            // outKeyValues
                            // outDocuments
                            // progres
                            logResponseMsg(call.getResponseMessage());
     
                            // 2.when i print ALL the outputparams I only see 
    the first param.
                            // when looking in the code that fills the map i 
    see:
                            // call.invoke ==> soapenvelope.getfirstbody ==> 
    body.getfirstboy ==> getChildren().get(0)!!! (see SOAPBODY.getFirstBody)
                            // ==> only the first param is put in the 
    outputparam ... I expected it would contain the 4 elements that are 
    present in the response MSG 
                            logOutputParams(call.getOutputParams());  
     
                            // 3.when manually parsing it is possible to 
    retrieve/decode/store the document from the response msg
                            parseMsgManual(call.getResponseMessage());
     
     
                    } catch (MalformedURLException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    } catch (ServiceException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    } catch (RemoteException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
            }
     
            private static void parseMsgManual(Message msg) throws AxisFault{
                    System.out.println("\n\n manual parsing of the received 
    params:");
                    Vector<Node> v = msg.getSOAPEnvelope().getBodyElements();
                    Iterator<Node> it2 = v.iterator();
                    while(it2.hasNext()){
                            Node cur= it2.next();
                            System.out.println(cur.getNodeName() );
                            if("outDocuments".equals(cur.getNodeName())){
                                    Node n = cur.getFirstChild();
                                    if(n != null){
                                            String docName = null;
                                            byte[] content = null;
                                            NodeList docInfo = 
    n.getChildNodes();
                                            Node docID = docInfo.item(0);
                                            Node doc = docInfo.item(1);
                                            if(docID != null)
                                                    docName = 
    docID.getFirstChild().getNodeValue();
                                            if(doc != null){   
                                                    String tmp = 
    doc.getFirstChild().getNodeValue();
                                                    content = 
    Base64.decodeBuffer(tmp);
                                            }
                                            if(docName != null && content != 
    null){
                                                    writeBytes(content, 
    "c:/output.pdf");
                                            }
                                    }
                            }
                    }
            }
     
            private static void logOutputParams(Map output){
                    System.out.println("Printing of all received output 
    params");
                    Iterator it = output.keySet().iterator();
                    while(it.hasNext()){
                            Object key = it.next();
                            String val = (String)output.get(key);
                            System.out.println(key + " : " + val);
                    }
            }
     
            private static void logResponseMsg(Message msg) throws AxisFault, 
    Exception{ 
                    String s = 
    XMLUtils.DocumentToString(msg.getSOAPEnvelope().getAsDocument());  
                    writeBytes(s.getBytes(), "c:/response.xml");
            }
     
     
            // this msg is not relevant to the issue, just required do write 
    the output in a file...
            private static final int BUFFER = 1024;
            private static boolean writeBytes(byte[] theBytes, String 
    filePath) {
                    boolean result = false;
                    FileOutputStream lRepOut = null;
                    try {
                            lRepOut = new FileOutputStream(filePath, false);
     
                            // Empty files are possible!
                            if(theBytes==null)
                                    theBytes = new byte[0];
     
                            int length = theBytes.length;
                            for (int i = 0; i < length; i += BUFFER) {
                                    int chunk = BUFFER;
                                    if(i+BUFFER > length){ // avoid index out 
    of bounds when writing last part of file
                                            chunk = length - i;
                                    }
                                    lRepOut.write(theBytes, i, chunk);
                            }
     
                            result = true;
                    } catch (java.io.IOException ex) {
                            System.out.println("Failed to write to file '" + 
    filePath + "' :" + ex.getMessage());
                            if (lRepOut != null) {
                                    try {
                                            lRepOut.close();
                                    } catch (Exception ignoreClosingExc) {
                                    }
                            }
                            // throw the error so the user is informed.
                            ex.printStackTrace();
                    } finally {
                            try {
                                    if (lRepOut != null) {
                                            lRepOut.flush();
                                            lRepOut.close();
                                    }
                            } catch (IOException e) {
                            }
                    }
                    return result;
            }
    }
    Any feedback is appreciated!

  2. #2
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,173
    Rep Power
    20

    Default

    What sort of Java would that wsdl generate, using wsdl2java for example?

    I can't think of a web service I've written that had multiple response nodes under the body, not that SOAP forbids that or anything...I'm just curious how it would be generated.

  3. #3
    rude056 is offline Member
    Join Date
    Sep 2010
    Posts
    3
    Rep Power
    0

    Default

    Hi thx for response :):
    Good question (which will clarify my concern about the missing params :)):
    The generate stub class contains the following operation:

    Java Code:
        public void submitEx(java.lang.String service, com.testcase.www.itpserver.wsdl.ArrayOfString parms, com.testcase.www.itpserver.wsdl.ArrayOfKeyValue inKeyValues, com.testcase.www.itpserver.wsdl.ArrayOfDoc inDocuments, javax.xml.rpc.holders.StringHolder submitExResult, com.testcase.www.itpserver.wsdl.holders.ArrayOfKeyValueHolder outKeyValues, com.testcase.www.itpserver.wsdl.holders.ArrayOfDocHolder outDocuments, com.testcase.www.itpserver.wsdl.holders.ArrayOfStringHolder progress)
    The last 4 arguments will be updated by reference, with the result values of the outputparams:
    The relevant code looks like this:
    Java Code:
    java.lang.Object _resp = _call.invoke(new java.lang.Object[] {service, parms, inKeyValues, inDocuments});
    
            if (_resp instanceof java.rmi.RemoteException) {
                throw (java.rmi.RemoteException)_resp;
            }
            else {
                extractAttachments(_call);
                java.util.Map _output;
                _output = _call.getOutputParams();
                try {
                    submitExResult.value = (java.lang.String) _output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "error"));
                } catch (java.lang.Exception _exception) {
                    submitExResult.value = (java.lang.String) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "error")), java.lang.String.class);
                }
                try {
                    outKeyValues.value = (com.testcase.www.itpserver.wsdl.ArrayOfKeyValue) _output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "outKeyValues"));
                } catch (java.lang.Exception _exception) {
                    outKeyValues.value = (com.testcase.www.itpserver.wsdl.ArrayOfKeyValue) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "outKeyValues")), com.testcase.www.itpserver.wsdl.ArrayOfKeyValue.class);
                }
                try {
                    outDocuments.value = (com.testcase.www.itpserver.wsdl.ArrayOfDoc) _output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "outDocuments"));
                } catch (java.lang.Exception _exception) {
                    outDocuments.value = (com.testcase.www.itpserver.wsdl.ArrayOfDoc) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "outDocuments")), com.testcase.www.itpserver.wsdl.ArrayOfDoc.class);
                }
                try {
                    progress.value = (com.testcase.www.itpserver.wsdl.ArrayOfString) _output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "progress"));
                } catch (java.lang.Exception _exception) {
                    progress.value = (com.testcase.www.itpserver.wsdl.ArrayOfString) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://www.testcase.com/itpserver/wsdl", "progress")), com.testcase.www.itpserver.wsdl.ArrayOfString.class);
                }
    This is code generated using axis 1.4.
    It implies that I have all params should be returned by _call.getOutputParams();.

    My code did not work, because i needed the 3th param (which contained a document) but I always only receive the first argument because that is the only one returned by _call.getOutputParams();

    So my code did not work, even though it should have (at least that is what I think :) . Currently I read the soap response and parse it manually to retrieve all params, but I would like to get it working using the generated stubs.

  4. #4
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,173
    Rep Power
    20

    Default

    Hmm.
    It does sort of imply that's how it should work.
    And thanks for showing the generated code...

    So that generated code does exactly what you say in the first post, that is only the submitExResult attribute gets populated (from error), and the rest is null?

    Did you step through the code to see that's what's happening by the way? I had a peek at the axis code but it's nto the neatest thing in the world...:)

  5. #5
    rude056 is offline Member
    Join Date
    Sep 2010
    Posts
    3
    Rep Power
    0

    Default

    Only the submitex contains a value because it is the only param in the returned map.
    I have looked into the axis code which fills the map and they actually only take the first node under the soapbody element.

    See the Call objects operation:

    public Object invoke( RPCElement body ) throws AxisFault
    You find:
    SOAPBodyElement bodyEl = resEnv.getFirstBody();

    Which uses eventually the SoapBody.getfirstbody:
    Java Code:
     SOAPBodyElement getFirstBody() throws AxisFault
        {
            if (!hasChildNodes())
                return null;
            return (SOAPBodyElement)getChildren().get(0);
        }
    The 0 indextaks the first child under the body.

    The code in the Call class then loops the children of that node.
    It seems the the getFirstBody method does not return the first body. But the first Node under the body. Could it be that they go 1 level to deep?

    PS: I have tried finding axis mailing lists or forums but with no success the mialing lists all moved or don't exist anymore and no forum was foudn :(

Similar Threads

  1. Server returned HTTP response code: 500.. i need help
    By hardc0d3r in forum Java Servlet
    Replies: 9
    Last Post: 03-12-2012, 09:08 PM
  2. Adding multiple sheets in Excel (apache POI)
    By javanewbie in forum Advanced Java
    Replies: 0
    Last Post: 06-22-2009, 05:51 AM
  3. Server returned HTTP response code: 500
    By fuliangQ in forum JavaServer Pages (JSP) and JSTL
    Replies: 1
    Last Post: 04-09-2009, 04:55 AM
  4. java.io.Exception: Server returned HTTP response code: 403
    By navishkumarb in forum Advanced Java
    Replies: 1
    Last Post: 01-05-2008, 02:33 PM
  5. Server returned HTTP response code: 500
    By Heather in forum Java Servlet
    Replies: 1
    Last Post: 07-09-2007, 05:32 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •