1

I'm using Spring Boot to consume a SOAP WS which I generate from a WSDL. I added the spring-ws-security so I can pass the user/password as security header as shown in the configuration:

@Configuration
public class ClientConfig {

    public static final String SIEBEL_ENDPOINT = "http://...";

    @Bean
    public CustomerClient customerClient() {
        CustomerClient client = new CustomerClient();
        client.setDefaultUri(SIEBEL_ENDPOINT);
        client.setWebServiceTemplate(webServiceTemplate(marshaller()));
        return client;
    }

    @Bean
    public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller) {
        WebServiceTemplate template = new WebServiceTemplate(marshaller, marshaller);
        template.setDefaultUri(SIEBEL_ENDPOINT);
        ClientInterceptor[] interceptors = new ClientInterceptor[] {new LogHttpHeaderClientInterceptor(), wsSecurityInterceptor()};
        template.setInterceptors(interceptors);
        return template;
    }

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("com.test.dms.gen");
        return marshaller;
    }

    @Bean
    public Wss4jSecurityInterceptor wsSecurityInterceptor() {
        Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
        wss4jSecurityInterceptor.setSecurementActions(WSHandlerConstants.USERNAME_TOKEN);
        wss4jSecurityInterceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
        wss4jSecurityInterceptor.setSecurementUsername("rf_USER");
        wss4jSecurityInterceptor.setSecurementPassword("rf_USER");
        return wss4jSecurityInterceptor;
    }

}

And the service call:

public class CustomerClient extends WebServiceGatewaySupport {
 
    public CustomerInfoOutput getCustomerInfo(String vin) {
        ObjectFactory request = new ObjectFactory();
        final CustomerInfoInput custInfoInput = request.createCustomerInfoInput();
        custInfoInput.setVINNumber(vin);


        return (CustomerInfoOutput) getWebServiceTemplate().marshalSendAndReceive(ClientConfig.SIEBEL_ENDPOINT, custInfoInput);
    }
}

everything is well generated, and this logged output:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                   SOAP-ENV:mustUnderstand="1">
        <wsse:UsernameToken wsu:Id="UsernameToken-e8f183db-44db-4c0b-90d9-ca57e89225fd">
            <wsse:Username>rf_USER</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">rf_USER</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
    <ns3:CustomerInfo_Input xmlns:ns2="http://siebel.com/testdashboard"
                            xmlns:ns3="http://test.com/rf/customerinfo" xmlns:ns4="http://test.com/rf"
                            xmlns:ns5="http://www.siebel.com/xml/IBM%20test%20Dashboard">
        <ns3:VINNumber>123456789</ns3:VINNumber>
    </ns3:CustomerInfo_Input>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

When I send this request using SOAP UI, it works perfectly. But when it's sent using the generated objects from the WSDL, I have this error:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
            <faultcode>SOAP-ENV:Server</faultcode>
            <faultstring>There is no active Web Service with operation named
                'http://test.com/rf/customerinfo:CustomerInfo_Input'.(SBL-EAI-04313)
            </faultstring>
            <detail>
                <siebelf:siebdetail xmlns:siebelf="http://www.siebel.com/ws/fault">
                    <siebelf:logfilename>EAIObjMgr_enu_0023_24117286.log</siebelf:logfilename>
                    <siebelf:errorstack>
                        <siebelf:error>
                            <siebelf:errorcode>SBL-EAI-04313</siebelf:errorcode>
                            <siebelf:errorsymbol>IDS_EAI_WS_OP_NOT_FOUND</siebelf:errorsymbol>
                            <siebelf:errormsg>There is no active Web Service with operation named
                                'http://test.com/rf/customerinfo:CustomerInfo_Input'.(SBL-EAI-04313)
                            </siebelf:errormsg>
                        </siebelf:error>
                    </siebelf:errorstack>
                </siebelf:siebdetail>
            </detail>
        </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Any ideas please?

PS: please don't focus on URIs because I changed them, but the generated request works fine in SOAPUI.

Marouane Gazanayi
  • 5,063
  • 6
  • 39
  • 58
  • 1
    Can you trace the RAW request going out ? Look for the part which says SOAPAction. – Ranjith R Jun 29 '20 at 01:19
  • Thanks @RanjithR: I traced through Wireshark and didn't find it. I added it thrgough WebServiceMessageCallback as mentionned in the wsdl for soap:operation attribute soapAction (document/http://test.com/rf/customerinfo:CustomerInfo) but also it said that There is no active Web Service with operation named as mentionned in the soapAction – Marouane Gazanayi Jun 30 '20 at 11:50
  • @RanjithR It works! The problem is that spring ws removes from the soapaction "document", and because Siebel is waiting for document or rpc, it doesn't work. – Marouane Gazanayi Jun 30 '20 at 15:25

2 Answers2

3

With the hint of @RanjithR I processed as follow:

I traced the SOAP Call using Wireshark, and I discovered that Spring WS doesn't include the header SOAPAction. The following SOF question talks about this, and how to configure it (it sends you to the spring documentation which explains well the thing). Spring-WS client not setting SOAPAction header

The second thing is that, even if I added the header, it continues to tell me that the endpoint is not sent.

In my WSDL, the SOAPAction is defined as follows:

<soap:operation soapAction="document/http://test.com/rf/customerinfo:CustomerInfo"></soap:operation>

And my Spring ws call was like that:

return getWebServiceTemplate().marshalSendAndReceive(ClientConfig.SIEBEL_ENDPOINT,
                customerInfoInput,
                webServiceMessage -> ((SoapMessage)webServiceMessage).setSoapAction("document/http://ripl.com/rforce/customerinfo:CustomerInfo"));

In Wireshark, I had:

SOAPAction: "http://ripl.com/rforce/customerinfo:CustomerInfo"

But when I trace the same call from SOAP UI I have: SOAPAction: "document/http://ripl.com/rforce/customerinfo:CustomerInfo"

So I tried to send a string literal as a SOAPAction:

"\"document/http://ripl.com/rforce/customerinfo:CustomerInfo\""; Note the \"\" around the action and it works :)

Maybe it can help someone that have to integrate with Jurasik Park systems...

Marouane Gazanayi
  • 5,063
  • 6
  • 39
  • 58
1

This post saved me a lot of time by pointing me in the right direction. The Action header was not added for me using the method described above, but the following method worked fine:

// add action header

final String ActionHeaderName = "Action";
final String ActionHeaderPrefix = "wsa";
final String ActionHeaderNamespace = "http://www.w3.org/2005/08/addressing";
final String ActionHeaderContent = "http://example/ActionHeader";
var actionName = soapEnvelope.createName(ActionHeaderName, ActionHeaderPrefix, ActionHeaderNamespace);
var actionHeader = soapEnvelope.getHeader().addHeaderElement(actionName);
                                actionHeader.setTextContent(ActionHeaderContent);

Thanks a lot @Marouane

Marius S
  • 267
  • 3
  • 21