web-dev-qa-db-ja.com

HTTPヘッダー「SOAPAction」の値がサーバーによって認識されませんでした

SOAPリクエストをサーバーに送信すると、次のエラーが返されますが、SoapUIを使用して同様のリクエストを送信すると機能します。これは、SOAPを変更する必要があるようです。 = SoapUIを使用して送信しているサーバーへのリクエスト。[〜#〜] wsdl [〜#〜]ここ です。

 [ truncated ] System.Web.Services.Protocols.SoapException : The value of the 
    HTTP header ' SOAPAction ' was not recognized by the server . \ r \ n at 
    System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest ( ) 
    \ r \ n at System.Web.Servic

次のリクエストを送信していますJavaを使用

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns2:SearchFlights xmlns:ns2="ElysArres.API">
         <ns2:SoapMessage>
            <ns2:Username>Test</ns2:Username>
            <ns2:Password>TestPassword</ns2:Password>
            <ns2:LanguageCode>EN</ns2:LanguageCode>
            <ns2:Request>
               <ns2:Departure>ONT</ns2:Departure>
               <ns2:Destination>EWR</ns2:Destination>
               <ns2:DepartureDate>2016-01-20</ns2:DepartureDate>
               <ns2:ReturnDate>2016-01-28</ns2:ReturnDate>
               <ns2:NumADT>1</ns2:NumADT>
               <ns2:NumINF>0</ns2:NumINF>
               <ns2:NumCHD>0</ns2:NumCHD>
               <ns2:CurrencyCode>EUR</ns2:CurrencyCode>
               <ns2:WaitForResult>true</ns2:WaitForResult>
               <ns2:NearbyDepartures>true</ns2:NearbyDepartures>
               <ns2:NearbyDestinations>true</ns2:NearbyDestinations>
               <ns2:RROnly>false</ns2:RROnly>
               <ns2:MetaSearch>false</ns2:MetaSearch>
            </ns2:Request>
         </ns2:SoapMessage>
      </ns2:SearchFlights>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

次のリクエストを送信できますSoapUIを使用そしてそれ動作

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:els="ElsyArres.API">
   <soap:Header/>
   <soap:Body>
      <els:SearchFlights>
         <els:SoapMessage>
            <els:Username>Test</els:Username>
            <els:Password>TestPassword</els:Password>
            <els:LanguageCode>EN</els:LanguageCode>
            <els:Request>
               <els:Departure>ONT</els:Departure>
               <els:Destination>EWR</els:Destination>
               <els:DepartureDate>2016-01-20</els:DepartureDate>
               <els:ReturnDate>2016-01-28</els:ReturnDate>
               <els:NumADT>1</els:NumADT>
               <els:NumINF>0</els:NumINF>
               <els:NumCHD>0</els:NumCHD>
               <els:CurrencyCode>EUR</els:CurrencyCode>
               <els:WaitForResult>true</els:WaitForResult>
               <els:NearbyDepartures>true</els:NearbyDepartures>
               <els:NearbyDestinations>true</els:NearbyDestinations>
               <els:RROnly>false</els:RROnly>
               <els:MetaSearch>false</els:MetaSearch>
            </els:Request>
         </els:SoapMessage>
      </els:SearchFlights>
   </soap:Body>
</soap:Envelope>

Javaで作成しているリクエストを、SoapUIで送信しているものと同じにする方法がわかりません。

コード

SearchFlights

@XmlRootElement(name = "SearchFlights")
@XmlAccessorType(XmlAccessType.FIELD)
public class SearchFlights {
    @XmlElement(name = "SoapMessage")
    private SoapMessage soapMessage;

    getter and setter

SoapMessage

@XmlRootElement(name = "SoapMessage")
@XmlAccessorType(XmlAccessType.FIELD)
public class SoapMessage {
    @XmlElement(name = "Username")
    private String username;
    @XmlElement(name = "Password")
    private String password;
    @XmlElement(name = "LanguageCode")
    private String languageCode;
    @XmlElement(name = "Request")
    private Request request;

    getters and setters

リクエスト

@XmlRootElement(name = "Request")
@XmlAccessorType(XmlAccessType.FIELD)
public class Request {
    @XmlElement(name = "Departure")
    private String departure;
    @XmlElement(name = "Destination")
    private String destination;
    @XmlElement(name = "DepartureDate")
    private String departureDate;
    @XmlElement(name = "ReturnDate")
    private String returnDate;
    @XmlElement(name = "NumADT")
    private int numADT;
    @XmlElement(name = "NumINF")
    private int numInf;
    @XmlElement(name = "NumCHD")
    private int numCHD;
    @XmlElement(name = "CurrencyCode")
    private String currencyCode;
    @XmlElement(name = "WaitForResult")
    private boolean waitForResult;
    @XmlElement(name = "NearByDepartures")
    private boolean nearByDepartures;
    @XmlElement(name = "NearByDestinations")
    private boolean nearByDestinations;
    @XmlElement(name = "RROnly")
    private boolean rronly;
    @XmlElement(name = "MetaSearch")
    private boolean metaSearch;

getters and setters

package-info.Java

@XmlSchema( 
    namespace = "ElsyArres.API",
    elementFormDefault = XmlNsForm.QUALIFIED) 
package com.myproject.flights.wegolo;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

jaxb.in​​dex

SearchFlights
Flight
Flights
Leg
Legs
Outbound
Request
Response
SoapMessage

リクエストを送信するコード

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;

import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
......
    // populate searchFlights and other classes to create request
    try {
        SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(
                MessageFactory.newInstance());
        messageFactory.afterPropertiesSet();

        WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
                messageFactory);
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

        marshaller.setContextPath("com.myproject.flights.wegolo");
        marshaller.afterPropertiesSet();

        webServiceTemplate.setMarshaller(marshaller);
        webServiceTemplate.afterPropertiesSet();

        Response response = (Response) webServiceTemplate
                .marshalSendAndReceive(
                        "http://www5v80.elsyarres.net/service.asmx",
                        searchFlights);

        Response msg = (Response) response;
        System.err.println("Wegolo >>>"
                + msg.getFlights().getFlight().size());
    } catch (Exception s) {
        s.printStackTrace();
    }

更新

私は削除しました package-info.Javaそして提案されたコードをなんとか使用しましたが、それでも同じヘッダーを送信しています。

Response response = (Response) webServiceTemplate
                    .marshalSendAndReceive(
                            "http://www5v80.elsyarres.net/service.asmx",
                            searchFlights,
                            new WebServiceMessageCallback() {
                                public void doWithMessage(WebServiceMessage message) 
                                {
                                    ((SoapMessage)message).setSoapAction("http://www5v80.elsyarres.net/searchFlights");
                                }
                           }
                       );

enter image description here

5
Daniel Newtown

SOAPバージョン1.1では、SOAPリクエストでSOAPアクションを指定するためにHTTPヘッダーが必要です。実際のXMLではなく、リクエストの一部です( HTTPヘッダー)、そのため、SoapUIリクエストxmlとWebServiceTemplateを使用して送信するリクエストの間に違いは見られません。Soap1.2では、メディアタイプの属性として設定できますが、そうではありません。 1.1サーバーに有効です。 仕様 に従って、使用する値は解決可能である必要はないことに注意してください。

SOAPは、URIの形式や特異性、またはURIが解決可能であることを制限しません。 HTTPクライアントは、SOAP HTTPリクエストを発行するときに、このヘッダーフィールドを使用する必要があります。

通常、WSDLで次のように指定されます( ここ から取得):

<soap:operation
        soapAction="http://www5v80.elsyarres.net/searchFlights"
        style="document" />

それがWSDLにない場合は、Webサービスエンドポイントクラスで春にactionアノテーションを使用して追加できます。

@Endpoint
public class MyFlightEndpoint{
    @Action("http://www5v80.elsyarres.net/searchFlights")
    public SearchFlights request() {
        ...
    }
}

それがWSDLにある場合は、その値をクライアント側のHTTPヘッダーに配置する必要があります。これを行うには、メッセージが作成された後、アクションヘッダーを追加するために送信される前に、クライアント側でメッセージにアクセスする必要があります。 Springは、そのためのメッセージコールバックインターフェイスを提供します。これについては、 ここ で説明されています。あなたがしたいことは次のようなものです:

Response response = (Response) webServiceTemplate
            .marshalSendAndReceive(
                    "http://www5v80.elsyarres.net/service.asmx",
                    searchFlights,
                    new WebServiceMessageCallback() {
                        public void doWithMessage(WebServiceMessage message) 
                        {
                            ((SoapMessage)message).setSoapAction("http://www5v80.elsyarres.net/searchFlights");
                        }
                   }
               );

SOAPアクションヘッダー ここ 、および詳細を知りたい場合はそれらのポイント(またはポイントの欠如)についての議論があります。

編集:ここでwsdlを見てください:

<soap:operation soapAction="ElsyArres.API/SearchFlights" style="document"/>

次のアクションが必要になります。

ElsyArres.API/searchFlights

コードを更新して読み取ります

((SoapMessage)message).setSoapAction("ElsyArres.API/searchFlights");

そして、あなたは行ってもいいです!

編集2:接続しているサービスがSOAP 1.2接続を受け入れる一方で、SOAP 1.1を使用していることにも気づきました。クライアントに工場で設定してSOAP 1.2を使用します。

messageFactory.setSoapVersion(SoapVersion.SOAP_12);
messageFactory.afterPropertiesSet();

サーバーが同じエンドポイントを使用しているように見えるので、それが唯一の変更点であるはずです。

12
AndyN

私は同じ問題を抱えていました、私の修正は:

  @Configuration
  public class SoapConfiguration {
      private static final String SOAP_1_2_PROTOCOL= "SOAP 1.2 Protocol";

  @Bean
   public WebServiceTemplate webServiceTemplate() throws Exception {

   SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(javax.xml.soap.MessageFactory.newInstance(SOAP_1_2_PROTOCOL));
   messageFactory.setSoapVersion(SoapVersion.SOAP_12);
   messageFactory.afterPropertiesSet();

   WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
           messageFactory);
   Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

   marshaller.setContextPath("YOUR_WSDL_GENERATED_PATH");
   marshaller.afterPropertiesSet();
   webServiceTemplate.setMarshaller(marshaller);
   webServiceTemplate.setUnmarshaller(marshaller);
   webServiceTemplate.afterPropertiesSet();
   return webServiceTemplate;
}

そして私のSoapService

@Service
@RequiredArgsConstructor
public class SoapDomainBoxService extends WebServiceGatewaySupport {
 private final WebServiceTemplate webServiceTemplate;

public void searchFlights(SearchFlights searchFlights) {

    String url = "YOUR.URL.asmx";
   Response response = (Response) webServiceTemplate.marshalSendAndReceive(url, searchFlights, new SoapActionCallback("ACTION.CALLBACK"));
}

メッセージファクトリ使用の作成で非常に重要

   SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(javax.xml.soap.MessageFactory.newInstance(SOAP_1_2_PROTOCOL));
1
sashanet buryk

SOAPActionを使用するときにWebServiceGatewaySupportヘッダーを追加する別の方法は、次のようにすることです。

_getWebServiceTemplate().marshalSendAndReceive(request, new SoapActionCallback("http://httpheader/"));
_

これはmessageFactory.setSoapVersion(SoapVersion.SOAP_12);を使用しています

0
adnans