Producing SOAP webservices with spring-ws with Soap v1.2 instead of the default v1.1
Asked Answered
H

4

22

I am currently working on Spring soap server project. I started off with the Getting Started guide from Spring here http://spring.io/guides/gs/producing-web-service/ to build a basic SOAP service.

The default SOAP protocol is SOAP v1.1. Is there a way I could set the protocol to v1.2, possibly via annotations?

I tried @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING) annotation on the @Endpoint class but it doesnt seem to work.

I also tried @Endpoint(value = SOAPBinding.SOAP12HTTP_BINDING) to set it, but this doesnt work either as seen in the logs on startup

INFO --- [nio-8080-exec-1] o.s.ws.soap.saaj.SaajSoapMessageFactory  :
 Creating SAAJ 1.3 MessageFactory with SOAP 1.1 Protocol

Ofcourse, if I post a SOAP request to the server, I get the following error

2015-01-19 15:50:17.610 ERROR 20172 --- [nio-8080-exec-1] c.sun.xml.internal.messaging.saaj.soap : SAAJ0533: Cannot create message: incorrect content-type for SOAP version. Got application/soap+xml;
 charset=utf-8, but expected text/xml
2015-01-19 15:50:17.611 ERROR 20172 --- [nio-8080-exec-1] c.sun.xml.internal.messaging.saaj.soap   :
 SAAJ0535: Unable to internalize message
2015-01-19 15:50:17.617 ERROR 20172 --- [nio-8080-exec-1] a.c.c.C.[.[.[.[messageDispatcherServlet] :
 Servlet.service() for servlet [messageDispatcherServlet] in context with path [] threw exception [R
equest processing failed; nested exception is org.springframework.ws.soap.SoapMessageCreationException: Could not create message from InputStream: Unable to internalize message; nested exception is com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to internalize message] with root cause

com.sun.xml.internal.messaging.saaj.soap.SOAPVersionMismatchException: Cannot create message: incorrect content-type for SOAP version. Got: application/soap+xml; charset=utf-8 Expected: text/xml
        at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.init(Unknown Source)
        at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.<init>(Unknown Source)
        at com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl.<init>(Unknown Source)
        at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl.createMessage(Unknown Source)

Any help is appreciated.

Thanks!

Headquarters answered 19/1, 2015 at 20:8 Comment(0)
R
42

You are mixing Spring-WS with annotations from JAX-WS (package javax.xml.ws). That won't work. To configure Spring-WS to use SOAP 1.2, add the following bean definition:

@Bean
public SaajSoapMessageFactory messageFactory() {
    SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
    messageFactory.setSoapVersion(SoapVersion.SOAP_12);
    return messageFactory;
}
Roughspoken answered 19/1, 2015 at 21:41 Comment(3)
Just a quick note that might catch some people out, the message factory should be declared as a separate bean (using @Bean) as it has been here. It will not work if you construct it manually as it relies of the Spring lifecycle method afterPropertiesSet()being called to construct the internal message factory. It's a bit of a strange design and might catch you out.Travistravus
I did it like this but when spring boot starts I still get o.s.w.s.saaj.SaajSoapMessageFactory.afterPropertiesSet - Creating SAAJ 1.3 MessageFactory with SOAP 1.1 ProtocolZipnick
@Zipnick That means you are failed to register the bean. Make sure the bean is registered with name messageFactory as the method name implies in this answer. You can also choose to register the bean like so @Bean(name= DEFAULT_MESSAGE_FACTORY_BEAN_NAME). Also make sure you are somehow not changing the default message factory name while registering the messageDispatcherServlet . The MessageDispatcherServlet has a method setMessageFactoryBeanName(), and if you are not registering a MessageFactory instance with name set here, you will get this error. Hope this helps someone.Tandratandy
R
2

If the messageFactory Bean is not in the singleton scope, then the afterPropertiesSet() method in the SaajSoapMessageFactory is not called on bean instantation.

The afterPropertiesSet() method sets up an internal message factory. So if your messageFactory bean has its own scope you need to set up the internal message factory like this:

@Bean
@Scope("custom-scope")
public SaajSoapMessageFactory messageFactory() {
    SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
    messageFactory.messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    return messageFactory;
}
Rollandrollaway answered 27/8, 2018 at 21:31 Comment(0)
L
2

As mentioned in the spring-ws issue 926, using a WebserviceGatewaySupport, the messageFactory @Bean injection does not work with many spring-ws versions because of the WebserviceTemplate encapsulation.

A workaround is both to set the SOAP version and affect the specific SOAPMessageFactory1_2Impl in order to send a proper SOAP 1.2 message :

WebServiceMessageFactory messageFactory = super.getWebServiceTemplate().getMessageFactory();
SaajSoapMessageFactory saajSoapMessageFactory = (SaajSoapMessageFactory)messageFactory;
saajSoapMessageFactory.setSoapVersion(SoapVersion.SOAP_12);
saajSoapMessageFactory.setMessageFactory(new SOAPMessageFactory1_2Impl());                super.getWebServiceTemplate().setMessageFactory(saajSoapMessageFactory);
super.getWebServiceTemplate().marshalSendAndReceive(message, soapActionHeader());
Lovettalovich answered 20/3, 2023 at 13:1 Comment(0)
A
1

The messageFactory() @Bean is a necessary step, but isn't it also fundamental to add

wsdl11Definition.setCreateSoap12Binding(true); 

to the service definition, to generate the appropriate soap 1.2 binding?

Anyway, thanks to Andreas Veithen

Approximation answered 29/10, 2020 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.