13

私はAndroid用のksoap2を使用して正しい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を初めて使用するので、他のアドバイスをいただければ幸いです。誰かが私がこれを修正する方法についての考えを持っていますか?

4

4 に答える 4

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;

私の場合、問題は解決しました。頭を悩ませましたが、debugtrueを設定することが問題の解決に役立つ理由を説明できませんでした。

なぜksoapを使用する必要があるのですか?SOAPリクエストの静的パーティを文字列として取得し、静的部分に値を追加するだけで、最終的に完全なSOAPリクエストを作成できます。最後に、HTTPメソッドを使用してPOSTリクエストを送信します。

追加のJARはありません

また、ksoapには、大きな応答のOOMなどの問題があります。

KSOAPOOMの問題

次のコードを使用できます

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

}
于 2012-10-26T13:43:19.987 に答える
1

ヘッダーを作成する別の方法が必要だと思います。これはjax-wsのように見えるので、数か月前に行ったjaxwsの実装を使用します。

まず、HeaderHandlerクラスが必要です。これは、soapヘッダー要素を作成します。次のようになります。


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

ちなみに、私はこの特定のヘッダーをテストしていませんでした。以前持っていたヘッダーハンドラーを変更したので、正確ではないかもしれませんが、かなり近いと思います。お役に立てば幸いです。試してみて、方法を教えてください。それでもうまくいかない場合は、お手伝いさせていただきます。

于 2012-09-10T17:55:51.820 に答える
0

parameters(すなわちi:type="n1:parameters")およびParameter(すなわち)ノードに対してkSOAPによって生成されたタイプi:type="n1:Parameter"が正しいかどうかを確認しましたか(それらはwsdlで定義されています)?

設定してみてください

envelope.implicitTypes = true;

そしてまた遊ぶ

envelope.setAddAdornments(false);

kSOAPにtype属性と名前空間を含めないように強制します。

于 2012-10-16T22:53:45.697 に答える
0

セットする

 envelope.implicitTypes = true;

設定しないでください

 envelope.setAddAdornments(false)

これは私のために働いた。

于 2015-04-29T15:17:08.973 に答える