Adding a Custom Http Header to a Spring Boot Ws Call (Wstemplate)

Setting a custom HTTP header dynamically with Spring-WS client

public class AddHttpHeaderInterceptor implements ClientInterceptor {

public boolean handleFault(MessageContext messageContext)
throws WebServiceClientException {
return true;
}

public boolean handleRequest(MessageContext messageContext)
throws WebServiceClientException {
TransportContext context = TransportContextHolder.getTransportContext();
HttpComponentsConnection connection =(HttpComponentsConnection) context.getConnection();
connection.addRequestHeader("name", "suman");

return true;
}

public boolean handleResponse(MessageContext messageContext)
throws WebServiceClientException {
return true;
}

}

config:

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
...
<property name="interceptors">
<list>
<bean class="com.blah.AddHttpHeaderInterceptor" />
</list>
</property>
</bean>

Cannot Add Http Headers to Message with Spring's WebServiceTemplate

Use the HeadersAwareSenderWebServiceConnection interface instead of the actual underlying connection.

TransportContext context = TransportContextHolder.getTransportContext();
HeadersAwareSenderWebServiceConnection connection = (HeadersAwareSenderWebServiceConnection) context.getConnection();
connection.addRequestHeader("Authorization", String.format("Bearer %s", "********"));

Now if you upgrade/switch HTTP library you don't need to change this code.

To answer your question about what you are doing wrong is that you are casting to the wrong class. Yes the class you are using is deprecated but it is part of the library you are using, you cannot just cast to a different class without changing the underlying HTTP library.

Webservice template : How to pass headers in webservice template

There is no way to pass headers and body separately in a webservice call. Instead, there are mechanisms that can alter the constructed messages, which we can leverage for adding an authentication to header and also custom elements to header. For this we need additional spring-ws dependencies.

<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-support</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-parent</artifactId>
<version>2.3.0</version>
<type>pom</type>
</dependency>

Then create a bean that does the auth (Here, I am giving a sample of basic auth)

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

Then add a WebServiceMessageCallback instance to override the finished message,

webServiceTemplate.marshalSendAndReceive(url, request, new CustomWebServiceMessageCallback());

Inside the CustomWebServiceMessageCallback, by using the following way, we can access the header and modify it.

@Override
public void doWithMessage(WebServiceMessage webServiceMessage) throws IOException, TransformerException {
SoapMessage soapMessage = (SoapMessage) webServiceMessage;
SoapHeader header = soapMessage.getSoapHeader();
StringSource headerSource = new StringSource("<additional-header-element>HEADER_TEXT</additional-header-element>");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(headerSource, header.getResult());
}

Add SoapHeader to org.springframework.ws.WebServiceMessage

Basically, you need to use a WebServiceMessageCallback in your client to modify the message after its creation but before it is sent. To rest of the code has been described pretty accurately by @skaffman so the whole stuff might look like this:

public void marshalWithSoapActionHeader(MyObject o) {

webServiceTemplate.marshalSendAndReceive(o, new WebServiceMessageCallback() {

public void doWithMessage(WebServiceMessage message) {
try {
SoapMessage soapMessage = (SoapMessage)message;
SoapHeader header = soapMessage.getSoapHeader();
StringSource headerSource = new StringSource("<credentials xmlns=\"http://example.com/auth\">\n +
<username>"+username+"</username>\n +
<password>"+password"+</password>\n +
</credentials>");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(headerSource, header.getResult());
} catch (Exception e) {
// exception handling
}
}
});
}

Personally, I find that Spring-WS sucks hard for such a basic need, they should fix SWS-479.



Related Topics



Leave a reply



Submit