3

I'm trying to call a SOAP webservice with credentials username and password, but it's giving an error, I tried in different ways but it's the same output, it's giving this error:

//error

expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG <html>@2:44 in java.io.InputStreamReader@54570a0)

No response is returned.

//variables

private static final String NAMESPACE = "http://tempuri.org/";
private static final String METHOD_NAME = "method";
private static final String SOAP_ACTION = NAMESPACE + METHOD_NAME;
private static final String URL = "https://example.com/and/service.asmx";
private static final String USER_NAME = "username";
private static final String PASSWORD = "password";
//calling web service
 SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
 PropertyInfo deviceIdPI = new PropertyInfo();
        deviceIdPI.setName("device_id");
        deviceIdPI.setValue(deviceId);
        deviceIdPI.setType(String.class);
        request.addProperty(deviceIdPI);
  SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

        // add header to envelope
        envelope.headerOut = getHeaderElement();

        System.out.println("HeaderValue " + Arrays.toString(envelope.headerOut));

        envelope.dotNet = false;
        envelope.bodyOut = request;
        envelope.setOutputSoapObject(request);
        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
        System.out.println("BodyOut " + envelope.bodyOut.toString());

        androidHttpTransport.debug = true;
        androidHttpTransport.call(SOAP_ACTION, envelope);

        SoapPrimitive response = (SoapPrimitive)envelope.getResponse();
        System.out.println("ResponseMessage" +  response.toString());
        responseMsg = String.valueOf(response);
        System.out.println("ResponseMessage" +  response.toString());
 public static Element[] getHeaderElement() {
        // create header
        Element[] header = new Element[1];
        header[0] = new Element().createElement("http://docs.oasis-open.org/wss/2004/01/oasis- 200401-wss-wssecurity-secext-1.0.xsd","Security");
        header[0].setAttribute(null, "mustUnderstand","1");

        //username
        Element username = new Element().createElement(null, USER_NAME);
        username.addChild(Node.IGNORABLE_WHITESPACE,"CBROWN");
        header[0].addChild(Node.ELEMENT, username);

        //password
        Element pass = new Element().createElement(null,PASSWORD);
        pass.setAttribute(null, "Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
//        pass.addChild(Node.TEXT, PASSWORD);
        username.addChild(Node.ELEMENT, pass);

        return header;
    }
}
M.Jamous
  • 41
  • 1
  • 2

1 Answers1

0

You can authenticate a Web Service call in two ways:

  • On one hand, you can authenticate your Web Service call at the message level, as in your code, including the necessary WS-Security related headers.
  • On the other, a Web Service call can be authenticated at the transport level, normally using the HTTP/S transport protocol and Authorization headers.

Both authentication mechanisms are in fact complementary, and the use of one of another depends on the Web Service provider.

In my opinion, the provider of your Web Service expects authentication at the transport level at least and, when you send the SOAP request without the necessary headers, it is returning a 401 HTML page, which is causing the error you are describing:

expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG <html>@2:44 in java.io.InputStreamReader@54570a0)

According to this related SO question, you can provide the necessary headers with something like this:

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

// add header to envelope: probably you can get rid of it
// when using HTTP transport authentication
// envelope.headerOut = getHeaderElement();

System.out.println("HeaderValue " + Arrays.toString(envelope.headerOut));

envelope.dotNet = false;
envelope.bodyOut = request;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
System.out.println("BodyOut " + envelope.bodyOut.toString());

androidHttpTransport.debug = true;

// Note the inclusion of the required headers
List<HeaderProperty> headerList = new ArrayList<HeaderProperty>();
headerList.add(new HeaderProperty(
        "Authorization",
        "Basic " + org.kobjects.base64.Base64.encode((USER_NAME + ":" + PASSWORD).getBytes())
        // Or, using android.util.Base64
        // "Basic " + Base64.encodeToString((USER_NAME + ":" + PASSWORD).getBytes(), Base64.DEFAULT)
));

androidHttpTransport.call(SOAP_ACTION, envelope, headerList);

SoapPrimitive response = (SoapPrimitive)envelope.getResponse();
System.out.println("ResponseMessage" +  response.toString());
responseMsg = String.valueOf(response);
System.out.println("ResponseMessage" +  response.toString());
jccampanero
  • 50,989
  • 3
  • 20
  • 49
  • Would you please clarify how to use this: getHeaderElement() as it's not a built in method – coder Mar 13 '23 at 10:15
  • @coder In fact, if the problem has to do with the use of HTTP authentication, you can get rid of this code fragment, I updated the answer with that information. Just in case, the `getHeaderElement` method is the one provided by the OP in the question. Note the whitespace error indicated by Olivier in his comment in `oasis- 200401`. – jccampanero Mar 13 '23 at 10:32
  • Tried the above code exactly, still giving the exact error. – coder Mar 14 '23 at 11:10
  • 1
    Thank you for the feedback @coder. I am sorry to hear that the problem is still there. I think that without further knowledge of the actual error is very difficult to say what is going on. I am not sure if it will help or work but, please, try configuring [`debug=true`](http://kobjects.org/ksoap2/doc/api/org/ksoap2/transport/Transport.html#debug) in your transport, and analyze the obtained `responseDump` searching for the error explanation. I am not sure if `bodyIn` could be of help as well. I hope it helps. – jccampanero Mar 14 '23 at 22:35
  • Creating a correct SOAP request code is fairly difficult and error prone task. In the past I used https://easywsdl.com/ to generate stubs to communicate with SOAP webservice from my Android app. It worked like a charm. – robocik May 21 '23 at 19:13
  • Thank you very much @robocik. Yes, I agree with you, if possible, it is preferable to use the stubs generated by a third party system or library/plugin, think in CXF, for instance. – jccampanero May 21 '23 at 21:38