1

I am very new in SOAP WebService development in Java and I have the following problem.

I have a webservice that expose 2 methods, the first (that is simpler) is already implemented (by an other person) and is named getVersion() and, in SoapUI have the following request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:getVersion/>
   </soapenv:Body>
</soapenv:Envelope>

Then I have a Java project that exeute the call to the webservice and in a class I have the followin method for the previous webservice method:

public String getVersion() { java.net.URL url = null; java.net.URLConnection conn = null;

java.io.BufferedReader rd = null;
String soapResponse = "";

String risultato = "";

// SOAP ENVELOP for the request:
String soapRequest;
soapRequest = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">" + "<soapenv:Header/>" + "<soapenv:Body> " + "<tem:getVersion/>" + "</soapenv:Body>" + "</soapenv:Envelope>";

try {

    // Try to open a connection
    url = new java.net.URL(_webServiceUrl);
    conn = url.openConnection();

    // Set the necessary header fields
    conn.setRequestProperty("SOAPAction", "http://tempuri.org/IMyService/getVersion");
    conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
    conn.setDoOutput(true);

    // Send the request:
    java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(conn.getOutputStream());
    wr.write(soapRequest);
    wr.flush();
    // Read the response
    rd = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream()));

    // Put the entire response into the soapResponse variable:
    String line;
    while ((line = rd.readLine()) != null) {
        //System.out.println(line);
        soapResponse = soapResponse + line + System.getProperty("line.separator");
    }

    rd.close();

    // elaboro la risposta
    SAXBuilder builder = new SAXBuilder();

    org.jdom.Document documentXML = null;
    documentXML = builder.build(new StringReader(soapResponse));

    XPath xPath;
    Element objectElement;
    //xPath = XPath.newInstance("s:Envelope/s:Body/getVersionResponse/getVersionResult");
    xPath = XPath.newInstance("s:Envelope/s:Body");
    xPath.addNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");

    objectElement = (Element) xPath.selectSingleNode(documentXML);

    if (objectElement != null) {
        risultato = objectElement.getValue();
    }

} catch (Exception ex) {
    ex.printStackTrace();
}

return risultato;

}

Now I have to replicate the same thing creating a new method (in the Java project that call the ws method) for the second method (that is more complex because, unlike the previous one, requires the passing some parameters) and I have some doubts about it.

So the situation is the following one: in SoapUI there is this WS method named getConfigSettings and its request is:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
       <soapenv:Header/>
       <soapenv:Body>
          <tem:getConfigSettings>
             <!--Optional:-->
             <tem:login>?</tem:login>
             <!--Optional:-->
             <tem:password>?</tem:password>
             <!--Optional:-->
             <tem:ipAddress>?</tem:ipAddress>
             <!--Optional:-->
             <tem:clientVersion>?</tem:clientVersion>
             <!--Optional:-->
             <tem:lastUpdateTime>?</tem:lastUpdateTime>
          </tem:getConfigSettings>
       </soapenv:Body>
    </soapenv:Envelope>

As you can see it requires some parameters (in SoapUi I have to replace characters with the correct parameter value)

So, in the Java project, I have create the following method that execute this call creating the SOAP Envelop for my request (but I have many doubtsa about its correctness)

    public String authentication(String login, String password, String ipAddress, String clientVersion) {


        java.net.URL url = null;
        java.net.URLConnection conn = null;

        java.io.BufferedReader rd = null;
        String myResponse = "";
        String soapXml; 

        // SOAP ENVELOP for the request:
        //soapXml = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"> " + "<s:Header>" + "<Action s:mustUnderstand=\"1\" xmlns=\"http://schemas.microsoft.com/ws/2005/05/addressing/none\">http://tempuri.org/IMyService/getVersion</Action>" + "</s:Header>" + "<s:Body>" + "<getVersion xmlns=\"http://tempuri.org/\" />" + "</s:Body>" + "</s:Envelope>";
        soapXml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">" 
                  + "<soapenv:Header/>" 
                       + "<soapenv:Body> "
                            + "<tem:login>" + login + "</tem:login>"
                            + "<tem:password>" + password + "</tem:password>"
                            + "<tem:ipAddress>" + ipAddress + "</tem:ipAddress>"
                       + "</soapenv:Body>"
                  + "</soapenv:Envelope>";
........................................................
........................................................
........................................................
DO SOME OTHER STUFF
........................................................
........................................................
........................................................
}

As you can see I have created this SOAP Envelop for my request in which I have inserted the parameter recived as input parameter of the method:

    soapXml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">" 
              + "<soapenv:Header/>" 
                   + "<soapenv:Body> "
                        + "<tem:login>" + login + "</tem:login>"
                        + "<tem:password>" + password + "</tem:password>"
                        + "<tem:ipAddress>" + ipAddress + "</tem:ipAddress>"
                   + "</soapenv:Body>"
              + "</soapenv:Envelope>";

Is it correct or am I taking a wrong solution? Some suggestion?

Tnx

Andrea

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596

1 Answers1

0

Your approach looks straight forward but you need to XML-escape the strings you are inserting.

Otherwise, the receiver may not parse your request if the strings contains reserved XML characters such as <. Just consider somebody using </tem:login> as his password :)

Libraries such as Guava or Apache commons contain XML escapers, see this thread for pointers: Best way to encode text data for XML in Java?

Alternatively, you could just include your own:

public static String xmlEscape(String s) {
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < sb.length(); i++) {
    char c = s.charAt(i);
    if ("<&\">'".indexOf(c) != -1) {
      sb.append("&#" + ((int) c) + ";");
    } else {
      sb.append(c);
    }
  }
  return sb.toString();
}

So your fill code would look similar to this:

soapXml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">" 
          + "<soapenv:Header/>" 
               + "<soapenv:Body> "
                    + "<tem:login>" + xmlEscape(login) + "</tem:login>"
                    + "<tem:password>" + xmlEscape(password) + "</tem:password>"

p.s. Never send login data over the net in clear text! You probably want to use https instead of http for your service.

Community
  • 1
  • 1
Stefan Haustein
  • 18,427
  • 3
  • 36
  • 51