soapAction attribute in WSDL operation is empty
Solution 1
Problem was finally solved.
WSDL was autogenerated and made static.
Endpoint was changed like this (the main point here is @Action
annotation):
@Endpoint
public class NotifyEndPoint {
private static final String NAMESPACE_URL = "http://fer2.klab/notify";
@Autowired
MainController mainController;
@PayloadRoot(namespace = NAMESPACE_URL, localPart = "ServiceRequest")
@Action("http://fer2.klab/notify/ServiceRequest")
// @ResponsePayload
public void send(@RequestPayload ServiceRequest hlMessage) {
System.out.println("notify method");
mainController.notify(null, "", hlMessage.getHL7Message());
}
}
dispatcher-servlet.xml
changed to this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<sws:annotation-driven />
<bean id="notify" name="notify" class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<property name="wsdl" value="notify.wsdl" />
</bean>
<context:component-scan base-package="klab.fer2"/>
</beans>
Solution 2
The soapAction
attribute of the soap:operation
element is the value that will be included in the HTTP request message, as in:
POST /StockQuote HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "http://electrocommerce.org/abc#MyMessage"
As stated in the specification this value only indicates the intent of which operation will be called and it's not normally used by the web services frameworks when creating the stubs.
A common pattern is to set it to empty string as in <soap:operation soapAction=""
which means that the operation that the request is referring to is indicated inside the http request's payload. So your wsdl looks fine in that regard.
In Spring though, you can annotate a method with @SoapAction
and that method will be mapped using the soapAction header. But you are using @PayloadRoot
on your method, so it will be mapped using the local name 'ServiceRequest', therefore the value of the soapAction will be ""
and it will not be used.
Solution 3
For me it worked only (spring-boot app):
wsdl11Definition.setSoapActions(soapActions);
public class WebServiceConfig extends WsConfigurerAdapter {
@Bean(name = "someService")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema schema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
....
Properties soapActions = new Properties();
for (Method method : endpointController.class.getMethods() ) {
soapActions.setProperty(method.getName(), Const.NAMESPACE_URI + "/#" + method.getName());
}
wsdl11Definition.setSoapActions(soapActions);
return wsdl11Definition;
}
Mikhail Batcer
Front end developer. Previously - full stack developer with Java, PHP, Python and SQL.
Updated on June 04, 2022Comments
-
Mikhail Batcer almost 2 years
There is a web service with the following WSDL:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://fer2.klab/notify" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://fer2.klab/notify" targetNamespace="http://fer2.klab/notify"> <wsdl:types> <xs:schema xmlns:er="http://fer2.klab/notify" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://fer2.klab/notify"> <xs:element name="ServiceRequest"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="1" minOccurs="1" name="HL7message" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="ServiceResponse"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="1" minOccurs="1" name="response" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> </wsdl:types> <wsdl:message name="ServiceResponse"> <wsdl:part element="tns:ServiceResponse" name="ServiceResponse"> </wsdl:part> </wsdl:message> <wsdl:message name="ServiceRequest"> <wsdl:part element="tns:ServiceRequest" name="ServiceRequest"> </wsdl:part> </wsdl:message> <wsdl:portType name="NotifyPort"> <wsdl:operation name="Service"> <wsdl:input message="tns:ServiceRequest" name="ServiceRequest"> </wsdl:input> <wsdl:output message="tns:ServiceResponse" name="ServiceResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="NotifyPortSoap11" type="tns:NotifyPort"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="Service"> <soap:operation soapAction=""/> <wsdl:input name="ServiceRequest"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="ServiceResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="NotifyPortService"> <wsdl:port binding="tns:NotifyPortSoap11" name="NotifyPortSoap11"> <soap:address location="http://192.168.1.101:8080/fer2-0.0.1/ws"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
There is an endpoint:
@Endpoint public class NotifyEndPoint { private static final String NAMESPACE_URL = "http://fer2.klab/notify"; @Autowired MainController mainController; @PayloadRoot(namespace = NAMESPACE_URL, localPart = "ServiceRequest") @ResponsePayload public ServiceResponse send(@RequestPayload ServiceRequest hlMessage){ System.out.println("notify method"); Object resp = mainController.notify(null, "", hlMessage.getHL7Message()); ServiceResponse sr = new ServiceResponse(); if (resp != null){ sr.setResponse(resp.toString()); } else{ sr.setResponse("null"); } return sr; } }
dispatcher-servlet.xml:
<bean id="notify" name="notify" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition"> <!--<property name="createSoap12Binding" value="true" />--> <property name="portTypeName" value="NotifyPort" /> <property name="locationUri" value="/ws" /> <property name="schema"> <bean class="org.springframework.xml.xsd.SimpleXsdSchema"> <property name="xsd" value="notify.xsd" /> </bean> </property> <property name="targetNamespace" value="http://fer2.klab/notify" /> <!--<property name="soapActions">--> <!--<props>--> <!--<prop key="ServiceRequest">http://fer2.klab/notify/ServiceRequest"</prop>--> <!--</props>--> <!--</property>--> </bean>
application-config.xml:
<bean class="klab.backend.utils.MainConfig" id="mainConfig"> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/> <property name="locations"> <list> <value>/WEB-INF/main.properties</value> <value>/WEB-INF/build.properties</value> </list> </property> </bean> <mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="writeAcceptCharset" value="true"/> </bean> <bean class="klab.backend.utils.json.JacksonView2HttpMessageConverter"> <property name="objectMapper"> <bean class="klab.backend.utils.json.KJsonMapper"> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <context:component-scan base-package="klab.fer2"/> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"> <property name="validator" ref="validator"/> </bean> <bean class="klab.backend.controller.base.DefaultController"/> <bean name="CorsFilter" class="klab.backend.filter.CorsFilter"/>
Why does
Service
operation in generated WSDL has empty attributesoapAction
?SOAP-request to URL http://192.168.1.101:8080/fer2-0.0.1/ws with following content:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:not="http://fer2.klab/notify"> <soapenv:Header/> <soapenv:Body> <not:ServiceRequest> <not:HL7message>hdfghdfghdfgh</not:HL7message> </not:ServiceRequest> </soapenv:Body> </soapenv:Envelope>
results in the following error logged:
org.springframework.ws.server.EndpointNotFound- No endpoint mapping found for [SaajSoapMessage {http://fer2.klab/notify}ServiceRequest]