soapAction attribute in WSDL operation is empty

11,831

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

Resolve empty soapAction

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;
}
Share:
11,831
Mikhail Batcer
Author by

Mikhail Batcer

Front end developer. Previously - full stack developer with Java, PHP, Python and SQL.

Updated on June 04, 2022

Comments

  • Mikhail Batcer
    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 attribute soapAction?

    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]