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
How to Retrieve Element Value from Soap Response Using Java
Iterate Through Each Digit in a Number
Multiple Scanner Inputs (Java)
How to Solve Maven 2.6 Resource Plugin Dependency
Java: Getting a Substring from a String Starting After a Particular Character
Where Does Gradle Save Dependencies' Jars
How to Mock Resultset and Populate It Using Mockito in Java
How to Add Multiple Components to a Jframe
Spring-Boot @Autowired Interface (Crudrepository) in My Service Class => Null Pointer Exception
How to Send Parallel Get Requests and Wait for Result Responses
How to Pass Bundle With Arraylist from Fragment to Activity
How to Combine Date and Time into a Single Object
Splitting String With Parentheses
Why Is Git Bash Not Using the Correct Java Path as Defined in the Path Environment Variable
Hibernate Error - Querysyntaxexception: Users Is Not Mapped [From Users]