Invoke a webservice from Android using SOAP - java

I'm consuming a webservice using java, i'm using the below WSDL, but i'm confused with the SOAP_ACTION:
NAMESPACE:
URL:
METHOD_NAME:
WSDL
<wsdl:definitions
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapjms="http://www.w3.org/2010/soapjms/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://cloudx623.company.com:5555/ws/Monish:TestWebservice/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"name="TestWebservice"
targetNamespace="http://cloudx623.company.com:5555/ws/Monish:TestWebservice/myTest">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://localhost:8080/Monish/TestWebservice"
targetNamespace="http://localhost:8080/Monish/TestWebservice">
<xsd:element name="myTest" type="tns:myTest"/>
<xsd:element name="myTestResponse" type="tns:myTestResponse"/>
<xsd:complexType name="myTest">
<xsd:sequence>
<xsd:element name="a" nillable="true" type="xsd:string"/>
<xsd:element name="b" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myTestResponse">
<xsd:sequence>
<xsd:element name="output" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="TestWebservice_PortType_myTestResponse">
<wsdl:part name="parameters" element="tns:myTestResponse"></wsdl:part>
</wsdl:message>
<wsdl:message name="TestWebservice_PortType_myTest">
<wsdl:part name="parameters" element="tns:myTest"></wsdl:part>
</wsdl:message>
<wsdl:portType name="TestWebservice_PortType">
<wsdl:operation name="myTest">
<wsdl:input message="tns:TestWebservice_PortType_myTest"></wsdl:input>
<wsdl:output message="tns:TestWebservice_PortType_myTestResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Monish_TestWebservice_Binder" type="tns:TestWebservice_PortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="myTest">
<soap:operation soapAction="Monish_TestWebservice_Binder_myTest" style="document"/>
<wsdl:input>
<soap:body parts="parameters" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body parts="parameters" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="TestWebservice">
<wsdl:port name="Monish_TestWebservice_Port" binding="tns:Monish_TestWebservice_Binder">
<soap:address location="http://192.28.50.46:5555/ws/Monish:TestWebservice/Monish_TestWebservice_Port"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The Java code using ksoap2 is as below
private static final String SOAP_ACTION = "http://cloudx623.company.com:5555/ws/Monish:TestWebservice/myTest";
private static final String METHOD_NAME = "myTest";
private static final String NAMESPACE = "Monish_TestWebservice_Binder_myTest";
// !!!!! IMPORTANT!!!!! THE URL OF THE CoLDFUSION WEBSERVER NOT LOCALHOST BECAUSE LOCALHOST IS THE ANDROID EMULATOR !!!!!
private static final String URL = "http://192.28.50.46:5555/ws/Monish:TestWebservice?WSDL";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
//CALL the web service method with the two parameters vname and nname
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("a", "3");
request.addProperty("b", "4");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE (URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
// Get the SAOP Envelope back and the extract the body
SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
Vector Vec = (Vector) resultsRequestSOAP.getProperty("getMessageReturn");
//Count of the arrays beneath starting from 0
//You can see the buildup with the php site with nusoap http://localhost/DA/nusoapclient_test2.php
int testat = Vec.size();
// It depends on how many arrays we have we can get to the attributs of one of them with get(0), get(1) ....
SoapObject test = (SoapObject) Vec.get(0);
System.out.println(envelope.getResponse());
//Get the attributes in the array
String tem = (String) test.getProperty("a");
tem = tem + " " + (String) test.getProperty("b");
//Just show it in a text area field called lblStatus
((TextView)findViewById(R.id.lblStatus)).setText(tem.toString());
// with androidhttptransport you need a catch block
} catch(Exception E) {
((TextView)findViewById(R.id.lblStatus)).setText("ERROR:" + E.getClass().getName() + ": " + E.getMessage());
}
}
Kindly let me know what the issue is. I'm getting a HTTP error status 500 in Android

I think you need to achieve like this.
You can see full example from here.
Part - 1 : Calling Web Service from Android
Part - 2: Webservice running in Android with Database
I hope this will help you.

Be sure that your are using right namespace or soap action. When you use wrong one, that error occures.

Related

How can I have two different endpoint with different namespace and same JAXB class?

I am using spring soap ws.
I have following JAXB domain classes correspond to complex types
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"reference",
"reason"
})
#XmlRootElement(name = "request-message")
public class RequestMessageType {
#XmlElement(name = "reference", required = true)
protected String reference;
#XmlElement(name = "reason")
protected String reason;
// I have getters and setters but removed here.
}
I have following class with #XmlRegistry annotations
#XmlRegistry
public class ObjectFactory {
private final static QName _RequestMessage_QNAME = new QName("http://namespace/url", "request-message");
public ObjectFactory() {
}
#XmlElementDecl(namespace = "http://namespace/url", name = "request-message")
public JAXBElement<RequestMessageType> createDisconnectRequestMessage(RequestMessageType value) {
return new JAXBElement<RequestMessageType>(_RequestMessage_QNAME, RequestMessageType.class, null, value);
}
}
Following are endpoints
#Endpoint
public class FirstEndPoint {
private static final String NAMESPACE_URI = "http://first/url/version";
private static final Logger LOG = Logger.getLogger(FirstEndPoint.class);
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "request-message")
#ResponsePayload
public JAXBElement<ResponseMessageType> requestMessage(#RequestPayload JAXBElement<RequestMessageType> requestMessage) {
LOG.info("request-message : first version ID : " + requestMessage.getValue().getReference());
//Preparing response and return response
}
}
#Endpoint
public class SecondEndPoint {
private static final String NAMESPACE_URI = "http://second/url/version";
private static final Logger LOG = Logger.getLogger(SecondEndPoint.class);
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "request-message")
#ResponsePayload
public JAXBElement<ResponseMessageType> requestMessage(#RequestPayload JAXBElement<RequestMessageType> requestMessage) {
LOG.info("request-message : second version ID : " + requestMessage.getValue().getReference());
//Preparing response and return response
}
}
When I make Soap request, I am using NAMESPACE_URI given in endpoints in soap request.
Here, in this case, I am getting following response
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring xml:lang="en">unexpected element (uri:"http://first/url/version", local:"request-message"). Expected elements are <{http://namespace/url}request-message></faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
If I use "http://namespace/url" as NAMESPACE_URI in endpoint and in soap request I am getting the proper response but I try to make it different for two endpoints with two different namespaces then it is not working and gives above response.
How can I use two different namespaces for two different endpoints with same JAXB class? I am completely new to spring and web service.
Additional info : RequestMessageType class and ObjectFactory class are in one package and in package-info.java namespace is
#javax.xml.bind.annotation.XmlSchema(namespace="http://namespace/url",elementFormDefault=javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.example
Do I need to change anything in package-info.java file ?
I created a sample project. I hope it can be useful to you. You can give a look at it here: https://github.com/angeloimm/spring-ws-sample
Basically this is my WSDL file (in SOAP Web Service all is ruled by WSDL):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ss="http://www.example.org/SpringSample/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SpringSample"
targetNamespace="http://www.example.org/SpringSample/">
<wsdl:types>
<xsd:schema targetNamespace="http://www.example.org/SpringSample/">
<xsd:complexType name="abstractRequest">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="reqName" type="xsd:string" nillable="false"
maxOccurs="1" minOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="abstractResponse">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="responseName" type="xsd:string"
nillable="false" maxOccurs="1" minOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="requestImplementation" type="ss:abstractRequest" />
<xsd:element name="responseImplementation" type="ss:abstractResponse" />
<xsd:element name="requestImplementation2" type="ss:abstractRequest" />
<xsd:element name="responseImplementation2" type="ss:abstractResponse" />
</xsd:schema>
</wsdl:types>
<wsdl:message name="OperationRequest">
<wsdl:part element="ss:requestImplementation" name="request" />
</wsdl:message>
<wsdl:message name="OperationResponse">
<wsdl:part element="ss:responseImplementation" name="response" />
</wsdl:message>
<wsdl:message name="OperationRequest2">
<wsdl:part element="ss:requestImplementation2" name="request2" />
</wsdl:message>
<wsdl:message name="OperationResponse2">
<wsdl:part element="ss:responseImplementation2" name="response2" />
</wsdl:message>
<wsdl:portType name="SpringSample">
<wsdl:operation name="Operation1">
<wsdl:input message="ss:OperationRequest" />
<wsdl:output message="ss:OperationResponse" />
</wsdl:operation>
<wsdl:operation name="Operation2">
<wsdl:input message="ss:OperationRequest2" />
<wsdl:output message="ss:OperationResponse2" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SpringSampleSOAP" type="ss:SpringSample">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Operation1">
<soap:operation style="document" soapAction="http://www.example.org/SpringSample/Operation1" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Operation2">
<soap:operation style="document" soapAction="http://www.example.org/SpringSample/Operation2" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SpringSample">
<wsdl:port binding="ss:SpringSampleSOAP" name="SpringSampleSOAP">
<soap:address location="http://www.example.org/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
As you can see I defined 2 complex type: abstractRequest and abstractResponse. Then I implemented them by using the elements requestImplementation,requestImplementation2,responseImplementation,responseImplementation2 According to WS-I specification you need to use separate operations and elements
Then I wrote this endpoint:
#Endpoint
public class SampleEndpoint
{
private static final Logger logger = LoggerFactory.getLogger(SampleEndpoint.class.getName());
private static final String NAME_SPACE_URI = "http://www.example.org/SpringSample/";
#PayloadRoot(namespace = NAME_SPACE_URI, localPart="requestImplementation")
#ResponsePayload
public JAXBElement<AbstractResponse> operationOneResp(#RequestPayload JAXBElement<AbstractRequest> ar)
{
if( logger.isDebugEnabled() )
{
logger.debug("Operation 1 request "+ar.getValue().getReqName());
}
ObjectFactory of = new ObjectFactory();
AbstractResponse aResp = of.createAbstractResponse();
aResp.setResponseName("operation 1 response");
JAXBElement<AbstractResponse> result = of.createResponseImplementation(aResp);
return result;
}
#PayloadRoot(namespace = NAME_SPACE_URI, localPart="requestImplementation2")
#ResponsePayload
public JAXBElement<AbstractResponse> operationTwoResp(#RequestPayload JAXBElement<AbstractRequest> ar)
{
if( logger.isDebugEnabled() )
{
logger.debug("Operation 2 request "+ar.getValue().getReqName());
}
ObjectFactory of = new ObjectFactory();
AbstractResponse aResp = of.createAbstractResponse();
aResp.setResponseName("operation 2 response");
JAXBElement<AbstractResponse> result = of.createResponseImplementation(aResp);
return result;
}
}
As you can see now I always use AbstractRequest and AbstractResponse JAXBElement in both methods. The 2 methods can also be in 2 different endpoints
I hope it's what you needed and it's useful
Angelo

WebFault and Web Service in different namespaces

I need to define custom exception in different namespace than a web service. But when I generate a wsdl, some wrapper appears in the namespace of webservice. Is it possible to use exception from another namespace without this wrapper?
Exception:
#WebFault(targetNamespace = "http://somenamespace/server/faults",
faultBean = "my.package.SoapBadRequestException.FaultBean")
public class SoapBadRequestException extends Exception {
private FaultBean faultBean;
#XmlType(name = "FaultBean", namespace = "http://somenamespace/server/faults")
public static class FaultBean {}
public SoapBadRequestException() { super(); }
public SoapBadRequestException(String message, FaultBean faultBean, Throwable cause) {
super(message, cause);
this.faultBean = faultBean;
}
public SoapBadRequestException(String message, FaultBean faultBean) {
super(message);
this.faultBean = faultBean;
}
public FaultBean getFaultInfo() { return faultBean; }
}
Web service:
#WebService(targetNamespace = "http://somenamespace/server/ws")
public interface MyWebService {
void someOperation(
#WebParam(name = "param1") String param1,
#WebParam(name = "param2") String param2) throws SoapBadRequestException;
}
Resulting wsdl (FaultBean is undefined, also don't know why):
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://somenamespace/server/ws"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://somenamespace/server/faults"
name="MyWebServiceImpl"
targetNamespace="http://somenamespace/server/ws">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://somenamespace/server/faults"
attributeFormDefault="unqualified"
elementFormDefault="unqualified"
targetNamespace="http://somenamespace/server/faults">
<xsd:element name="SoapBadRequestFault" nillable="true" type="tns:FaultBean"/>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://somenamespace/server/ws"
attributeFormDefault="unqualified"
elementFormDefault="unqualified"
targetNamespace="http://somenamespace/server/ws">
<xsd:element name="someOperation" type="tns:someOperation"/>
<xsd:complexType name="someOperation">
<xsd:sequence>
<xsd:element name="param1" type="xsd:string"/>
<xsd:element name="param2" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="someOperationResponse" type="tns:someOperationResponse"/>
<xsd:complexType name="someOperationResponse">
<xsd:sequence/>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="someOperationResponse">
<wsdl:part element="tns:someOperationResponse" name="parameters"></wsdl:part>
</wsdl:message>
<!-- This is the redundant wrapper in the web service namespece -->
<wsdl:message name="SoapBadRequestException">
<wsdl:part element="ns1:SoapBadRequestFault" name="SoapBadRequestException"></wsdl:part>
</wsdl:message>
<wsdl:message name="someOperation">
<wsdl:part element="tns:someOperation" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="MyWebService">
<wsdl:operation name="someOperation">
<wsdl:input message="tns:someOperation" name="someOperation"></wsdl:input>
<wsdl:output message="tns:someOperationResponse" name="someOperationResponse"></wsdl:output>
<wsdl:fault message="tns:SoapBadRequestException" name="SoapBadRequestException"></wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MyWebServiceImplSoapBinding" type="tns:MyWebService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="someOperation">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="someOperation">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="someOperationResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SoapBadRequestException">
<soap:fault name="SoapBadRequestException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MyWebServiceImpl">...</wsdl:service>
I saw this and this but nothing helped.

Creating and sending a SOAP message in java to a very simple web service

I am currently trying to create and send a SOAP message to a very simple web service I've created myself.
Obviously the webservice have a wsdl file, which you can see here:
wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns="http://service.com" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://service.com">
<wsdl:documentation>Please Type your service description here</wsdl:documentation>
<wsdl:types>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://service.com">
<xs:element name="echoTest">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="echoString" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="echoTestResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="echoTestRequest">
<wsdl:part name="parameters" element="ns:echoTest"/>
</wsdl:message>
<wsdl:message name="echoTestResponse">
<wsdl:part name="parameters" element="ns:echoTestResponse"/>
</wsdl:message>
<wsdl:portType name="RequestHandlerPortType">
<wsdl:operation name="echoTest">
<wsdl:input message="ns:echoTestRequest" wsaw:Action="urn:echoTest"/>
<wsdl:output message="ns:echoTestResponse" wsaw:Action="urn:echoTestResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="RequestHandlerSoap11Binding" type="ns:RequestHandlerPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="echoTest">
<soap:operation soapAction="urn:echoTest" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="RequestHandlerSoap12Binding" type="ns:RequestHandlerPortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="echoTest">
<soap12:operation soapAction="urn:echoTest" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="RequestHandlerHttpBinding" type="ns:RequestHandlerPortType">
<http:binding verb="POST"/>
<wsdl:operation name="echoTest">
<http:operation location="echoTest"/>
<wsdl:input>
<mime:content type="application/xml" part="parameters"/>
</wsdl:input>
<wsdl:output>
<mime:content type="application/xml" part="parameters"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="RequestHandler">
<wsdl:port name="RequestHandlerHttpSoap11Endpoint" binding="ns:RequestHandlerSoap11Binding">
<soap:address location="http://localhost:8181/PayCheckHandlerMainWebService/services/RequestHandler.RequestHandlerHttpSoap11Endpoint/"/>
</wsdl:port>
<wsdl:port name="RequestHandlerHttpSoap12Endpoint" binding="ns:RequestHandlerSoap12Binding">
<soap12:address location="http://localhost:8181/PayCheckHandlerMainWebService/services/RequestHandler.RequestHandlerHttpSoap12Endpoint/"/>
</wsdl:port>
<wsdl:port name="RequestHandlerHttpEndpoint" binding="ns:RequestHandlerHttpBinding">
<http:address location="http://localhost:8181/PayCheckHandlerMainWebService/services/RequestHandler.RequestHandlerHttpEndpoint/"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
I've then used the google chrome plugin called Wizdler, to find out how the structure of soap messages should look like. THe Soap message for this example, should look like this.
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
<Body>
<echoTest xmlns="http://service.com">
<echoString>[string?]</echoString>
</echoTest>
</Body>
</Envelope>
So a pretty simple and straightforward SOAP message.. Nevertheless, Ican get it to work.
I am trying to create the SOAP message with the following code:
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://service.com";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
// SOAP Body
SOAPBody soapBody = envelope.getBody();
soapBody.addNamespaceDeclaration("", serverURI);
SOAPElement soapBodyElem = soapBody.addChildElement("echoTest");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("echoString");
soapBodyElem1.addTextNode("HELLO?!?");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("RequestHandler", serverURI);
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println();
The above code, produces the following SOAP message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/>
<SOAP-ENV:Header/>
<SOAP-ENV:Body xmlns="http://service.com">
<echoTest xmlns="">
<echoString xmlns="http://service.com">HELLO?!?</echoString>
</echoTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I don't know why the echoString get the xmlns="http://service.com".. it should be in the echoTest tag instead.. and I guess this could be a part of the problem.
The response message looks like this:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>namespace mismatch require http://service.com found none</faultstring>
<detail />
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
As can figure out, there is a problem with the namespace, but i seems like no matter what I do, the problem still occurs.
I hope someone can see the problem and maybe can provide a solution.
Any help will be greatly appreciated.
SOAPElement soapBodyElem = soapBody.addChildElement("echoTest","", serverURI);
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("echoString","", serverURI);
But why are you constructing your SOAP explicitly?
If there is no particular reason, then use wsimport. Java classes + JAXB annotations will help you.
Anyways, after trying for a loooong time, I finally got it to work.. and of course just right after posting this question, I got it to work. So here is the complete java code for the problem described in the question:
public class PayCheckHandler {
public PayCheckHandler() throws Exception {
// TODO Auto-generated method stub
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http://localhost:8181/PayCheckHandlerMainWebService/services/RequestHandler?wsdl";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// print SOAP Response
System.out.println();
System.out.print("Response SOAP Message:");
soapResponse.writeTo(System.out);
soapConnection.close();
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://service.com";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
// SOAP Body
SOAPBodyElement element = body.addBodyElement(envelope.createName("echoTest", "", serverURI));
element.addChildElement("echoString").addTextNode("Hello!!!");
return soapMessage;
}
public static void main(String[] args) throws Exception {
new PayCheckHandler();
}
}
Btw. if I absolutely didn't have to create my own SOAP messages manually, I would do as artem.ponchakov suggested.

How to get string array with KSOAP2 in Java, Android?

I use KSOAP2 library, and web-service returns me string array:
<GetChanelResult>
<string>
string
</string>
<string>
string
</string>
</GetChanelResult>
But how can I transform Object (which I got with envelope.getResponce()) to string array? Thank you.
I have the code:
package com.nda.ut;
import java.io.IOException;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.AndroidHttpTransport;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class UTPlayerActivity extends Activity {
/** Called when the activity is first created. */
public static String SOAP_ACTION="http://tempuri.org/GetChanel";
public static String METHOD_NAME="GetChanel";
public static String NAMESPACE="http://tempuri.org/";
public static String URL="http://www.mcds.co.il/YouTube/ChanelApi.asmx";
TextView view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view=(TextView)findViewById(R.id.view);
SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME);
SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet=true;
envelope.setOutputSoapObject(request);
AndroidHttpTransport aht=new AndroidHttpTransport(URL);
try {
aht.call(SOAP_ACTION, envelope);
SoapPrimitive result=(SoapPrimitive)envelope.getResponse();
//if (result!=null)
view.setText("123");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("IO", "1");
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
Log.e("XmlPullParser", "2");
}
}
}
But this code returned exception
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="GetChanel">
<s:complexType />
</s:element>
<s:element name="GetChanelResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetChanelResult" type="tns:ArrayOfString" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ArrayOfString">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
</wsdl:types>
<wsdl:message name="GetChanelSoapIn">
<wsdl:part name="parameters" element="tns:GetChanel" />
</wsdl:message>
<wsdl:message name="GetChanelSoapOut">
<wsdl:part name="parameters" element="tns:GetChanelResponse" />
</wsdl:message>
<wsdl:portType name="ChanelApiSoap">
<wsdl:operation name="GetChanel">
<wsdl:input message="tns:GetChanelSoapIn" />
<wsdl:output message="tns:GetChanelSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ChanelApiSoap" type="tns:ChanelApiSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetChanel">
<soap:operation soapAction="http://tempuri.org/GetChanel" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="ChanelApiSoap12" type="tns:ChanelApiSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetChanel">
<soap12:operation soapAction="http://tempuri.org/GetChanel" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ChanelApi">
<wsdl:port name="ChanelApiSoap" binding="tns:ChanelApiSoap">
<soap:address location="http://www.mcds.co.il/YouTube/ChanelApi.asmx" />
</wsdl:port>
<wsdl:port name="ChanelApiSoap12" binding="tns:ChanelApiSoap12">
<soap12:address location="http://www.mcds.co.il/YouTube/ChanelApi.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
This code for page
To get the string array from ksoap response,
First parse the response to SoapObject like this,
SoapObject result = (SoapObject) envelope.bodyIn;
and then retrieve the first element from response. In this case it is your String array like this,
String str = ((SoapObject)result.getProperty(0)).getPropertyAsString(1);
i) getProperty will return your whole String array (parse it to SoapObject) and
ii) getPropertyAsString(int index) will return your String at index 1 from String array and so on.
you have to parse the elements then only you can transform that in to an array.
Xml.parse(response.toString(), parser);
Please follow the link and the subsequent ones to have a good idea of how to do it,
http://android.vexedlogic.com/2011/04/17/android-lists-iv-accessing-and-consuming-a-soap-web-service-i/
if you are still stuck get back to me.
//For retrieving Single dimensional array from SOAP Response Envelope, use :
public String[] getStringArray() throws Exception
{
SoapObject Table = (SoapObject)getEnvelope().bodyIn;
String []output=null;
if(Table!=null)
{
int count= Table.getPropertyCount();
output = new String[count];
for(int i=0;i<count;i++)
{
output[i]=Table.getProperty(i).toString();
}
}
return output;
}
// or if you want 2 dimensional array ,
public String[][] getStringTable() throws Exception
{
SoapObject Table =(SoapObject)getEnvelope().bodyIn;
String [][]output=null;
if(Table!=null)
{
SoapObject row = (SoapObject) Table.getProperty(0);
if(row!=null)
{
int rCount = Table.getPropertyCount();
int cCount = ((SoapObject)Table.getProperty(0)).getPropertyCount();
output = new String[rCount][cCount];
for(int i=0;i<rCount;i++)
{
for(int j=0;j<cCount;j++)
output[i][j] =((SoapObject) Table.getProperty(i)).getProperty(j).toString();
}
}
}
return output;
}
//Here, getEnvelope() is the method for retrieving envelope using ksoap2
subclass Soap object
import java.util.ArrayList;
import java.util.List;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
public class CustomSoapObject extends SoapObject {
public CustomSoapObject(String namespace, String name) {
super(namespace, name);
}
public CustomSoapObject(SoapObject soap) {
super(soap.getNamespace(), soap.getName());
for (int i = 0; i < soap.getPropertyCount(); i++) {
try {
PropertyInfo propertyInfo = new PropertyInfo();
soap.getPropertyInfo(i, propertyInfo);
this.addProperty(propertyInfo);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
public PropertyInfo[] getPropertyAsArray(String propertyName) {
List<PropertyInfo> res = new ArrayList<PropertyInfo>();
for (Object property : properties) {
if (property instanceof PropertyInfo) {
if (((PropertyInfo) property).getName().equals(propertyName)) {
res.add(((PropertyInfo) property));
}
} else {
System.out.println(property.toString());
}
}
return res.toArray(new PropertyInfo[res.size()]);
}
}

Problem with deserialization of String sent over wire with XStream

I am trying to create a simple webservice which takes a String as input and returns string as output.
I am using Ecelipse Helios and Axis 2.15.
I am writing simple WSDL for the same.
I am generating the stubs using code generator.
New ->code generator -> java class from wsdl-> give WSDL and generates the java skeletons.
And in the skelton I am just print the value what is coming as parameter. and returning the same value.
I have written client code to invoke the method of the webservice. which takes a String.
but when I am trying to invoke the method I am getting following exception and it's not hitting the webservice.
Infact I am using XStream along with Client/WebService.
Code goes like this for the webservice skeleton:
public com.url.pkg.ShowInputResponse showInput(
com.url.pkg.ShowInput showInput) {
// TODO : fill this with the necessary business logic
String inputString = showInput.getInputString();
System.out.println("INput String is :\n" + inputString);
XStream xStream = new XStream();
System.out.println("After XStream Declaration...");
SOVO vo = null;
try {
vo = (SOVO) xStream.fromXML(inputString);
} catch (Throwable e) {
System.out.println(e);
e.printStackTrace();
}
System.out.println("After SOVO casting from XML");
System.out.println(vo.getName());
System.out.println(vo.getParams());
// TODO: business logic
ShowInputResponse response = new ShowInputResponse();
response.set_return(inputString);
return response;
}
My client code goes like this :
public static void main(String[] args) throws Exception {
BasicServiceStub stub = new BasicServiceStub();
ShowInput request = new ShowInput();
SOVO sovo = new SOVO();
sovo.setName("I am the post for SO");
Map params = new HashMap();
params.put("key1", "val1");
params.put("key2", "val2");
sovo.setParams(params);
XStream xStream = new XStream();
String soVoString = xStream.toXML(sovo);
// System.out.println(soVoString);
request.setInputString(soVoString);
ShowInputResponse response = stub.showInput(request);
System.out.println("....................................");
System.out.println("response = " + response.get_return());
}
SOVO is a simple POJO which is present at both client and webservice side.
public class SOVO {
private String name;
private Map params;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map getParams() {
return params;
}
public void setParams(Map params) {
this.params = params;
}
}
And last but most important WSDL is here:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns="http://pkg.url.com" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://pkg.url.com">
<wsdl:types>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://pkg.url.com">
<xs:element name="showInput">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="inputString" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="showInputResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="showInputRequest">
<wsdl:part name="parameters" element="ns:showInput"/>
</wsdl:message>
<wsdl:message name="showInputResponse">
<wsdl:part name="parameters" element="ns:showInputResponse"/>
</wsdl:message>
<wsdl:portType name="BasicServicePortType">
<wsdl:operation name="showInput">
<wsdl:input message="ns:showInputRequest" wsaw:Action="urn:showInput"/>
<wsdl:output message="ns:showInputResponse" wsaw:Action="urn:showInputResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BasicServiceSoap11Binding" type="ns:BasicServicePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="showInput">
<soap:operation soapAction="urn:showInput" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="BasicServiceSoap12Binding" type="ns:BasicServicePortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="showInput">
<soap12:operation soapAction="urn:showInput" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="BasicServiceHttpBinding" type="ns:BasicServicePortType">
<http:binding verb="POST"/>
<wsdl:operation name="showInput">
<http:operation location="BasicService/showInput"/>
<wsdl:input>
<mime:content type="text/xml" part="showInput"/>
</wsdl:input>
<wsdl:output>
<mime:content type="text/xml" part="showInput"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BasicService">
<wsdl:port name="BasicServiceHttpSoap11Endpoint" binding="ns:BasicServiceSoap11Binding">
<soap:address location="http://localhost:8080/axis2/services/BasicService"/>
</wsdl:port>
<wsdl:port name="BasicServiceHttpSoap12Endpoint" binding="ns:BasicServiceSoap12Binding">
<soap12:address location="http://localhost:8080/axis2/services/BasicService"/>
</wsdl:port>
<wsdl:port name="BasicServiceHttpEndpoint" binding="ns:BasicServiceHttpBinding">
<http:address location="http://localhost:8080/axis2/services/BasicService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
And the Stack trace for the exception I must modify :
I am not very sure if its hitting the webservice layer.
Caused by: org.apache.axis2.AxisFault: string
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:446)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:371)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:417)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
at com.url.pkg.BasicServiceStub.showInput(BasicServiceStub.java:184)
at com.url.pkg.Client.main(Client.java:30)
It looks like more its some problem with XStream desirialization. Even though SOVO is in the classpath why its happening? Am I missing something?
When I try sending XXXXX as string it tells:
only whitespace content allowed before start tag and not X (position: START_DOCUMENT seen X... #1:1)
When i try sending "some value" it says:
only whitespace content allowed before start tag and not s (position: START_DOCUMENT seen s... #1:1)
I am not sure what's wrong.
I would suggest the following:
Test the service with another client
Use soapUI to generate a valid test request for your showInput method. If you don't get any errors using this tool, you know your service is working fine. If you do get an error, then you know to start digging around in your service code.
Enable client side logging for SOAP messages
Add these JVM options when running your client:
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
-Dorg.apache.commons.logging.simplelog.showdatetime=true
-Dorg.apache.commons.logging.simplelog.log.httpclient.wire=debug
-Dorg.apache.commons.logging.simplelog.log.org.apache.commons.httpclient=debug
This will let you to see the SOAP messages that get transmitted. Pay close attention to content appearing before your start tags like the error message says.

Categories