2012-08-01 2 views
13

Я часами пытаюсь создать правильный SOAP-запрос, используя ksoap2 для Android, без везения. Идеальный запрос выглядит следующим образом:Попытка построить правильный запрос SOAP

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

Я использую следующий код для генерации моего запроса:

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; 

Что ksoap2 строят является:

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

У меня есть ощущение, что проблема в заголовке с префиксами n0, но я не знаю, как избавиться от них. Я удалил их из тела, установив implicitTypes в true, но я не могу найти аналогичную настройку для заголовка. Я новичок в SOAP, поэтому любой другой совет очень ценится. Кто-нибудь имеет представление о том, как я могу это исправить?

ответ

5

При использовании KSOAP Это работает для меня

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); 
    } 

ПРИМЕЧАНИЕ:

androidHttpTransport.debug = true; 

решен вопрос в моем случае. Ударил головой, но не мог понять, почему установка debug true помогла решить проблему.

Зачем вам нужно использовать ksoap? Просто укажите статическую сторону вашего запроса SOAP в виде строки, добавьте значения в статическую часть, и вы можете, наконец, получить полный запрос SOAP. Наконец, используйте HTTP-методы для отправки вашего почтового запроса.

Никаких дополнительных JAR-

Также ksoap не имеет проблем, как ООМ для больших ответов и т.д.

KSOAP OOM issue

Вы можете использовать следующий код

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

Можете ли вы рассказать мне о SoapObject И значения передаются на него .... –

1

Я думаю, вам нужен другой способ создания заголовка, он выглядит как jax-ws, поэтому я пойду с реализацией jax ws, которую я сделал пару месяцев назад.

Сначала вам нужен класс HeaderHandler, которым создает элемент заголовка мыла, он должен выглядеть следующим образом:


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; 
     } 
    } 

После этого вы создаете HeaderHandlerResolver для обработки создания заголовка и вставить его в обработчик цепи:


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; 
     } 
    } 

После этого добавьте в клиенте:


 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(); 
     } 

Кстати, я не проверял этот конкретный заголовок, я изменил предыдущий обработчик заголовка я имел, так что это может быть не точным, но я думаю, что это довольно близко, я действительно надеюсь, что это поможет вам, попробуйте и расскажите, как это происходит, я постараюсь вам помочь, если он все еще не работает.

0

Вы проверили ли правильны типы, порожденные kSOAP для parameters (т.е. i:type="n1:parameters") и Parameter (т.е. i:type="n1:Parameter") узлов (они определены в WSDL)?

Try установка

envelope.implicitTypes = true; 

А также играть с

envelope.setAddAdornments(false); 

заставить kSOAP не включать атрибут типа и пространства имен.

0

набор

envelope.implicitTypes = true; 

и НЕ установлен

envelope.setAddAdornments(false) 

это работало для меня.

Смежные вопросы