2012-08-01 16 views
13

He estado luchando durante horas tratando de construir la solicitud SOAP correcta utilizando ksoap2 para Android sin suerte. La solicitud ideales se ve así:Intentando construir una solicitud SOAP correcta

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Header> 
    <AuthorizationToken xmlns="http://www.avectra.com/2005/"> 
     <Token>string</Token> 
    </AuthorizationToken> 
    </soap:Header> 
    <soap:Body> 
    <ExecuteMethod xmlns="http://www.avectra.com/2005/"> 
     <serviceName>string</serviceName> 
     <methodName>string</methodName> 
     <parameters> 
     <Parameter> 
      <Name>string</Name> 
      <Value>string</Value> 
     </Parameter> 
     </parameters> 
    </ExecuteMethod> 
    </soap:Body> 
</soap:Envelope> 

estoy usando el siguiente código para generar mi solicitud:

SoapObject request = new SoapObject(NAMESPACE, METHOD); 
    request.addProperty("serviceName", SERVICENAME); 
    request.addProperty("methodName", METHODNAME); 

    SoapObject nestedParameters = new SoapObject(NAMESPACE, "parameters"); 
    SoapObject param = new SoapObject(NAMESPACE, "Parameter"); 
    param.addProperty("Name", name); 
    param.addProperty("Value", value); 
    nestedParameters.addSoapObject(param); 
    request.addSoapObject(nestedParameters); 

    SoapSerializationEnvelope envelope = 
      new SoapSerializationEnvelope(SoapEnvelope.VER11); 
    envelope.setOutputSoapObject(request); 
    envelope.dotNet = true; 
    envelope.implicitTypes = true; 

    envelope.headerOut = new Element[1]; 
    Element header = new Element().createElement(NAMESPACE, "AuthorizationToken"); 
    Element token = new Element().createElement(NAMESPACE, "Token"); 
    token.addChild(Node.TEXT, this.AUTH_TOKEN); 
    header.addChild(Node.ELEMENT, token); 
    envelope.headerOut[0] = header; 

Lo ksoap2 está construyendo es:

<v:Envelope xmlns:i="http://www.w3.org/1999/XMLSchema-instance" xmlns:d="http://www.w3.org/1999/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/"> 
    <v:Header> 
    <n0:AuthorizationToken xmlns:n0="http://www.avectra.com/2005/"> 
     <n0:Token>string</n0:Token> 
    </n0:AuthorizationToken> 
    </v:Header> 
    <v:Body> 
    <ExecuteMethod xmlns="http://www.avectra.com/2005/" id="o0" c:root="1"> 
     <serviceName>AHAWebServices</serviceName> 
     <methodName>MemberDirectory</methodName> 
     <parameters i:type="n1:parameters" xmlns:n1="http://www.avectra.com/2005/"> 
     <Parameter i:type="n1:Parameter"> 
      <Name>string</Name> 
      <Value>string</Value> 
     </Parameter> 
     </parameters> 
    </ExecuteMethod> 
    </v:Body> 
</v:Envelope> 

Tengo la sensación de que el problema está en el encabezado con los prefijos n0 pero no tengo ni idea de cómo deshacerme de ellos. Los eliminé del cuerpo estableciendo implicitTypes en verdadero, pero no puedo encontrar una configuración similar para el encabezado. Soy nuevo en SOAP, por lo que cualquier otro consejo es muy apreciado. ¿Alguien tiene una idea de cómo podría solucionar esto?

Respuesta

5

Al utilizar KSOAP Esto funcionó para mí

SoapObject request = new SoapObject(WEBSERVICE_NAMESPACE, methodName); 
    if(null != parameterMap && !parameterMap.isEmpty()){ 
     for(Entry<String, String> entry: parameterMap.entrySet()){ 
      request.addProperty(entry.getKey(), entry.getValue()); 
     } 
    } 
    // Declare the version of the SOAP request 

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
    envelope.implicitTypes = true; 
    envelope.dotNet = true; 
    envelope.setOutputSoapObject(request); 


    HttpTransportSE androidHttpTransport = new HttpTransportSE(ApplicationConstants.WEBSERVICE_WSDL_URL); 

    // this is the actual part that will call the webservice 
    try { 

     androidHttpTransport.debug = true; 
     androidHttpTransport.call(soapActionUrl, envelope); 
     String ss = androidHttpTransport.responseDump; 

     // Get the SoapResult from the envelope body. 

     Log.d(TAG, "request: " + androidHttpTransport.requestDump); 
     Log.d(TAG, "response: "+ androidHttpTransport.responseDump); 


     SoapObject result = (SoapObject) envelope.getResponse(); 

     Log.d("soap response", "" + result);    
    } catch (IOException e) { 
     Log.e(TAG, "IOException", e); 
    } 

NOTA:

androidHttpTransport.debug = true; 

resuelto el problema en mi caso. Me golpeó la cabeza pero no pude razonar sobre por qué configurar la depuración correcta me ayudó a resolver el problema.

¿Por qué necesita usar ksoap? Simplemente tenga la parte estática de su solicitud SOAP como una Cadena, agregue los valores a la parte estática y finalmente puede tener la solicitud SOAP completa. Finalmente, use los métodos HTTP para enviar su solicitud de publicación.

No JAR adicionales

también ksoap tiene problemas como OOM para grandes respuestas, etc.

KSOAP OOM issue

Usted puede utilizar el código siguiente

import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.util.HashMap; 
import java.util.Map.Entry; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.protocol.HTTP; 
import org.apache.http.util.EntityUtils; 

import android.util.Log; 

public final class SOAPRequest{ 

private static final String TAG = "SOAPRequest"; 
private static final String TAG_SOAP_HEADER_START = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Header>"; 
private static final String TAG_AUTHORIZATION_START = "<AuthorizationToken xmlns=\"http://www.avectra.com/2005/\">"; 
private static final String TAG_TOKEN_START = "<TOKEN>"; 
private static final String TAG_TOKEN_END = "</TOKEN>"; 
private static final String TAG_AUTORIZATION_END = "</AuthorizationToken>"; 
private static final String TAG_SOAPHEADER_END = "</soap:Header>"; 
private static final String TAG_SOAP_BODY_START = "<soap:Body>"; 
private static final String TAG_PARAM_NAME_START = "<Name>"; 
private static final String TAG_PARAM_NAME_END = "</Name>"; 
private static final String TAG_PARAM_VALUE_START = "<Value>"; 
private static final String TAG_PARAM_VALUE_END = "</Value>"; 
private static final String TAG_METHOD_START = "<methodName>"; 
private static final String TAG_METHOD_END = "</methodName>"; 
private static final String TAG_SERVICE_START = "<serviceName>"; 
private static final String TAG_SERVICE_END = "</serviceName>"; 
private static final String TAG_PARAMS_START = "<parameters><Parameter>"; 
private static final String TAG_EXE_METHOD_START = "<ExecuteMethod xmlns=\"http://www.avectra.com/2005/\">"; 
private static final String TAG_SOAP_REQ_END = "</Parameter></parameters></ExecuteMethod></soap:Body></soap:Envelope>"; 

/** 
* Constructor intentionally made private 
*/ 
private SOAPRequest() { 

} 
/** 
* Builds a SOAP request with the specified value 
* @param token Value of token 
* @param serviceName Value of servicename 
* @param methodName Value of methodName 
* @param paramsMap Collection of parameters as set of name value pair which needs to be sent 
* @return the complete soap request 
*/ 
public static String buildRequest(String token, String serviceName, String methodName, HashMap<String, String> paramsMap){ 
    StringBuilder requestBuilder = new StringBuilder(TAG_SOAP_HEADER_START); 
    requestBuilder.append(TAG_AUTHORIZATION_START); 
    requestBuilder.append(TAG_TOKEN_START); 
    requestBuilder.append(token); 
    requestBuilder.append(TAG_TOKEN_END); 
    requestBuilder.append(TAG_AUTORIZATION_END); 
    requestBuilder.append(TAG_SOAPHEADER_END); 
    requestBuilder.append(TAG_SOAP_BODY_START); 
    requestBuilder.append(TAG_EXE_METHOD_START); 
    requestBuilder.append(TAG_SERVICE_START); 
    requestBuilder.append(serviceName); 
    requestBuilder.append(TAG_SERVICE_END); 
    requestBuilder.append(TAG_METHOD_START); 
    requestBuilder.append(methodName); 
    requestBuilder.append(TAG_METHOD_END); 
    requestBuilder.append(TAG_PARAMS_START); 
    for(Entry<String, String> param :paramsMap.entrySet()){ 
     requestBuilder.append(TAG_PARAM_NAME_START); 
     requestBuilder.append(param.getKey()); 
     requestBuilder.append(TAG_PARAM_NAME_END); 
     requestBuilder.append(TAG_PARAM_VALUE_START); 
     requestBuilder.append(param.getValue()); 
     requestBuilder.append(TAG_PARAM_VALUE_END); 
    } 
    requestBuilder.append(TAG_SOAP_REQ_END); 
    return requestBuilder.toString(); 
} 

/** 
* Connection timeout set for the HttpClient 
*/ 
private static final int CONNECTION_TIMEOUT= 6000; 
/** 
* Socket timeout set for the HttpClient 
*/ 
private static final int SOCKET_TIMEOUT = 10000; 

/** 
* @return httpClient An instance of {@link DefaultHttpClient} 
*/ 
private static DefaultHttpClient getHttpClient() { 
    HttpParams httpParameters = new BasicHttpParams(); 
    // Set the timeout in milliseconds until a connection is established. 
    // The default value is zero, that means the timeout is not used. 
    HttpConnectionParams.setConnectionTimeout(httpParameters,CONNECTION_TIMEOUT); 
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data. 
    HttpConnectionParams.setSoTimeout(httpParameters, SOCKET_TIMEOUT); 

    return new DefaultHttpClient(httpParameters); 
} 

/** 
* Sends a SOAP request to the specified service endpoint. 
* 
* @param serviceEndpoint The service endpoint which will be hit 
* @param soapRequest The SOAP request 
* @return The string representing the response for the specified SOAP request. 
*/ 
public static String send(String serviceEndpoint, String soapRequest){ 
    HttpPost httppost = new HttpPost(serviceEndpoint);   
    StringEntity se = null; 
    try { 
     se = new StringEntity(soapRequest,HTTP.UTF_8); 
    } catch (UnsupportedEncodingException e) { 
     Log.e(TAG,"send", e); 
     return null; 
    } 

    se.setContentType("text/xml"); 
    httppost.setHeader("Content-Type","application/soap+xml;charset=UTF-8"); 
    httppost.setEntity(se); 
    String result = null; 
    HttpClient httpclient = getHttpClient(); 
    try { 
     HttpResponse httpResponse = httpclient.execute(httppost); 
     HttpEntity responseEntity = httpResponse.getEntity(); 
     if(null!= responseEntity){ 
      //if you have a huge chunk of data read it using a buffer 
      result =EntityUtils.toString(responseEntity); 
     } 
    } catch (ClientProtocolException e) { 
     Log.e(TAG,"send", e); 
    } catch (IOException e) { 
     Log.e(TAG,"send", e); 
    } catch (Exception e){ 
     Log.e(TAG,"send", e); 
    } 

    return result; 
} 

} 
+0

¿Puede decirme acerca de SoapObject y los valores lo transmiten ...? –

1

Creo que necesitas otra forma de crear el encabezado, parece jax-ws, así que iré con una implementación de jax ws que hice hace un par de meses.

Lo primero que necesita una clase HeaderHandler, cosa que crea el elemento de cabecera de jabón, que debería tener este aspecto:


import javax.xml.namespace.QName; 
    import javax.xml.soap.SOAPElement; 
    import javax.xml.soap.SOAPEnvelope; 
    import javax.xml.soap.SOAPHeader; 
    import javax.xml.ws.handler.MessageContext; 
    import javax.xml.ws.handler.soap.SOAPHandler; 
    import javax.xml.ws.handler.soap.SOAPMessageContext; 


    public class HeaderHandler implements SOAPHandler<SOAPMessageContext> { 

     public boolean handleMessage(SOAPMessageContext smc) { 
      Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
      String AUTH_TK = "http://www.avectra.com/2005/"; 
      String PREFIX="";//no prefix 
      String PREFIX_XMLNS="xmlns"; 
      String value = "123456"; 
      if (outboundProperty.booleanValue()) { 
       try { 
        SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope(); 
        SOAPHeader header = envelope.addHeader(); 
        //<AuthorizationToken xmlns="http://www.avectra.com/2005/"> 
        SOAPElement authorizationToken = header.addChildElement("AuthorizationToken", PREFIX_XMLNS, AUTH_TK); 
        //<Token>value</Token> 
        SOAPElement usernameToken = 
         authorizationToken.addChildElement("Token", PREFIX); 
         usernameToken.addTextNode(value); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
      return outboundProperty; 
     } 


     public Set<QName> getHeaders() { 
      return null; 
     } 

     public void close(MessageContext arg0) { 

     } 

     public boolean handleFault(SOAPMessageContext arg0) { 
      return false; 
     } 
    } 

Después de que se crea un HeaderHandlerResolver para manejar la creación de cabecera y la inserta en una cadena manejador:


import java.util.ArrayList; 
    import java.util.List; 
    import javax.xml.ws.handler.Handler; 
    import javax.xml.ws.handler.HandlerResolver; 
    import javax.xml.ws.handler.PortInfo; 

    public class HeaderHandlerResolver implements HandlerResolver { 

    @SuppressWarnings("unchecked") 
    public List<Handler> getHandlerChain(PortInfo portInfo) { 
      List<Handler> handlerChain = new ArrayList<Handler>(); 
      HeaderHandler hh = new HeaderHandler(); 
      handlerChain.add(hh); 
      return handlerChain; 
     } 
    } 

Después de eso, se agrega en el cliente:


 try{ 
      //new service instance (your service should be extending javax.xml.ws.Service;) 
      YourServiceProxy service = new YourServiceProxy(); 
      //calls the header handler resolver ;) 
      service.setHandlerResolver(new HeaderHandlerResolver()); 
      //get the service 
      YourService port = (YourService)service.getYourService(); 
      //call the service 
      port.yourMethod() 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

Por cierto, no he probado esta cabecera en particular, he modificado un controlador de cabecera anterior que tenía, por lo que puede no ser exacta, pero creo que es bastante estrecha, realmente espero que te ayuda, pruébalo y cuéntanos cómo sucede, intentaré ayudarte si todavía no funciona.

0

Ha comprobado si los tipos generados por kSOAP para parameters (es decir i:type="n1:parameters") y Parameter (es decir i:type="n1:Parameter") nodos son correctas (que se definen en el WSDL)?

establecer

envelope.implicitTypes = true; 

Y también jugar con

envelope.setAddAdornments(false); 

para forzar kSOAP no incluir el atributo tipo y espacios de nombres intento.

0

conjunto

envelope.implicitTypes = true; 

Así que no se

envelope.setAddAdornments(false) 

esto funcionó para mí.

Cuestiones relacionadas