[英]The value of the HTTP header ' SOAPAction ' was not recognized by the server
當我向服務器發送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.index
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");
}
}
);
SOAP Version 1.1要求SOAP請求中的HTTP標頭指定SOAP操作。 它不在實際的XML中,它是請求的一部分(在HTTP頭中),這就是為什么你沒有看到你的SoapUI請求xml和你使用WebServiceTemplate發送的請求之間有任何區別。 Soap 1.2允許您將其設置為媒體類型的屬性,但這對1.1服務器無效。 請注意,根據規范 ,您使用的值不必是可解析的。
SOAP對URI的格式或特性沒有限制,也沒有可解析的限制。 發出SOAP HTTP請求時,HTTP客戶端必須使用此頭字段。
通常,它在您的WSDL中指定,類似於(取自此處 ):
<soap:operation
soapAction="http://www5v80.elsyarres.net/searchFlights"
style="document" />
如果這不在您的WSDL中,您可以在Web服務端點類中使用spring中的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.1時,我還注意到您正在連接的服務接受SOAP 1.2連接。 您可以通過在工廠中設置SOAP來強制客戶端使用SOAP 1.2。
messageFactory.setSoapVersion(SoapVersion.SOAP_12);
messageFactory.afterPropertiesSet();
看起來服務器使用相同的端點,因此應該是唯一的更改。
我有同樣的問題,我的修復是:
@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));
使用WebServiceGatewaySupport
時添加SOAPAction
標頭的另一種方法是執行以下操作:
getWebServiceTemplate().marshalSendAndReceive(request, new SoapActionCallback("http://httpheader/"));
這是使用messageFactory.setSoapVersion(SoapVersion.SOAP_12);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.