SOAPAction HTTP Header Value Not Recognized by Server

When I send a SOAP request to the server, it returns the following error, although I am sending a similar request using the SoapUI, and it works. It seems I need to change my SOAP request to the one I'm sending using SoapUI. WSDL is here .

[ 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 

I am sending the following request using 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> 

I can send the following request using SoapUI and it works

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

I'm not sure how to make a request that I create using Java, just like what I send using SoapUI.

code

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 

Request

 @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 

Code for sending a request

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

Update

I removed package-info.java and was able to use the suggested code, but it still sends the same header.

 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
source share
1 answer

SOAP version 1.1 requires an HTTP header in the SOAP request to indicate the SOAP action. This is not in the actual XML, it is part of the request (in the HTTP header), so you do not see any difference between your SoapUI xml request and the request you send using WebServiceTemplate. Soap 1.2 allows you to set it as an attribute for a media type, but this is not valid for server 1.1. Please note that according to the specification, the value you use should not be resolvable.

SOAP does not impose restrictions on the format or specification of a URI or that it is solvable. The HTTP client MUST use this header field when issuing an SOAP HTTP request.

Usually it is listed in your WSDL, something like (taken from here ):

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

If it is not in your WSDL, you can add it using the action annotation in spring in your webservice endpoint class.

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

If it is in your WSDL, you will want to put this value in your client side HTTP header. To do this, you need to access the message on the client side after creating it, but before sending it, to add an action header. spring provides a callback interface for this, which is described here . What you want to do is something like:

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

It discusses the SOAP action headers here and the point (or lack of a point) for them if you want to know more.

Edit: So, let's look at wsdl here:

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

You will need the following action:

 ElsyArres.API/searchFlights 

Now just update the code to read

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

and you are good to go!

Edit 2: I also noticed that the service you are connecting to accepts SOAP 1.2 connections while you are using SOAP 1.1. You can force your client to use SOAP 1.2 by installing it in a factory.

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

It looks like the server is using the same endpoint, so this should be the only change.

+6
source

Source: https://habr.com/ru/post/1239996/


All Articles