Intereting Posts
Быстрый доступ к изображениям и манипуляции с Android Обои ImageView внутри пользовательского представления не отображаются на некоторых устройствах Можете ли вы установить несколько соединений Bluetooth между одними и теми же двумя устройствами в Android? Ленивая загрузка из SQLite SetRetainInstance (true) + setCustomAnimations (…) = анимация для каждого изменения ориентации? Как я могу исключить нижний колонтитул ListView? OnRestart против OnResume – вопрос жизненного цикла Android Библиотека Android – Публикация нескольких вариантов в локальный репозиторий Maven с использованием Gradle Как написать драйверы для Android? Соединение Bluetooth RFCOMM / SDP с адаптером RS232 в Android SQLite запрос на обновление Android Android + эспрессо + асинхронный HTTP-запрос -> как протестировать? App-debug-unaligned.apk для свойства 'inputFile' не существует Как добиться перекрытия / отрицательной границы в макете ограничений? TextAppearance в теме

Попытка создать правильный запрос SOAP

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

<?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, поэтому любой другой совет очень ценится. Кто-нибудь имеет представление о том, как я могу это исправить?

Solutions Collecting From Web of "Попытка создать правильный запрос SOAP"

При использовании 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 как String, добавьте значения в статическую часть, и вы можете, наконец, получить полный запрос SOAP. Наконец, используйте HTTP-методы для отправки вашего почтового запроса.

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

Кроме того, у ksoap есть такие проблемы, как OOM для больших ответов и т. Д.

Проблема KOMAP OOM

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

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

Я думаю, вам нужен другой способ создания заголовка, он выглядит как 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(); } 

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

Вы проверили, правильны ли типы, сгенерированные parameters kSOAP для parameters (например, i:type="n1:parameters" ) и Parameter (т.е. i:type="n1:Parameter" ) (они определены в wsdl)?

Попробуйте установить

 envelope.implicitTypes = true; 

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

 envelope.setAddAdornments(false); 

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

задавать

  envelope.implicitTypes = true; 

И НЕ устанавливайте

  envelope.setAddAdornments(false) 

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