Spring-ws SoapHeader fields access in endpoint method

3.4k views Asked by At

We are developing a contract-first WebService using spring-ws 2.2.0. We are trying to manage the authentication using a custom tag, named AuthToken, located in the SoapHeader. The AuthToken has the following structure:

<authToken>
    <username>USERNAME</xa:username>
    <password>PASSWORD</xa:password>
</authToken>

We are able to generate a WSDL schema containing the specified custom authentication tag inside the SoapHeader. The problem is that when the client performs the call towards our server we are not able to unmarshal the AuthToken tag (located in the SoapHeader) in our Ws Endpoint implementation.

Using the @RequestPayload annotation in the binding method signature (handleMethodRequest as specified in the example below), we are able to access the unmarshalled payload content (located in the SoapBody). We tried to make the same thing with the SoapHeader content without success. In the following code examples we show you what we would like to obtain:

1
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "methodRequest")
@ResponsePayload
public MethodResponse handleMethodRequest(@RequestPayload MethodRequest request, @SoapHeader(value = "authToken") AuthToken authToken) { }

2
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "methodRequest")
@ResponsePayload
public MethodResponse handleMethodRequest(@RequestPayload MethodRequest request, AuthToken authToken) { }

3
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "methodRequest")
@ResponsePayload
public MethodResponse handleMethodRequest(@RequestPayload MethodRequest request, org.springframework.ws.soap.SoapHeader header) { }

4
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "methodRequest")
@ResponsePayload
public MethodResponse handleMethodRequest(@RequestPayload MethodRequest request, MessageContext messageContext) { }

In case 1, 2 we obtain the following error:

No adapter for endpoint [MethodResponse EndpointImplementation.handleMethodRequest(MethodRequest, AuthToken) throws java.lang.Exception]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?

In case 3, 4 we have no errors but we are not able to handle SoapHeader or MessageContext (respectively in case 3 and 4) to reach our purposes, accessing the AuthToken to retrieve username and password sub element.

Looking for a solution in the web we found that many people having the same problem uses Spring Interceptors to handle the authentication. Following the "Interceptors-way" we should access the AuthToken inside the interceptor. Unfortunately we need to use AuthToken field inside handleMethodRequest method for other purposes, for example loading user specific data, not accessible outside handleMethodRequest. Therefore we cannot follow this way because we need to refer user specific data inside the handleMethodRequest method.

Does anyone know how can we solve the problem? Thanks in advance.

2

There are 2 answers

2
Andreas Veithen On BEST ANSWER

For that use case, the only supported combination of annotation and parameter type is @SoapHeader and SoapHeaderElement. Spring-WS currently doesn't support unmarshalling headers.

0
Abe On

A hacky way of getting the value from interceptor to the handleMethodRequest is using a static ThreadLocal instance. Since the same thread that invokes the interceptor also invokes the handleMethodRequest you can use

ThreadLocal.set(AuthToken); // in interceptor.
ThreadLocal.get();// in handler and then clear it after use.

Also, I noticed that @SoapHeader(value = "{authToken") in your example does not have } is that a typo here or in your code?