简体   繁体   中英

How to create a SOAP request envelop for this WS in Java?

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

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>"

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM