I have been trying to consume a SOAP service using a Spring application, but I've been absolutely stuck for a while. I expect the solution will be very simple and I'm hoping to be pointed in the right direction.
I am able to successfully make requests via SoapUI. I simply loaded the .WSDL file, selected the method to use, and added the username and password with basic authorization from the 'Auth' menu in SoapUI.
In the Spring application, I've gotten to the point of getting a 401 error, so I believe it's almost there. I referenced these two nice examples below to first add the username and password, and secondly to log the HTTP headers to verify that they are populated correctly.
https://codenotfound.com/spring-ws-log-client-server-http-headers.html
Setting a custom HTTP header dynamically with Spring-WS client
However, neither setting the 'usernamePasswordCredentials', nor setting the connection's request header seems to have any effect. I've also confirmed that the XML body is correct by testing the logged output in SoapUI. So I believe it's just an authorization issue.
Bean/Configuration Class:
@Bean
public Jaxb2Marshaller marshaller() {
System.out.println("BEAN CREATED: MARSHALLER...");
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("..."); // omitted for example
return marshaller;
}
@Bean
public UsernamePasswordCredentials usernamePasswordCredentials() {
return new UsernamePasswordCredentials("testu", "test");
}
@Bean
@DependsOn({"usernamePasswordCredentials"})
public HttpComponentsMessageSender httpComponentsMessageSender(UsernamePasswordCredentials usernamePasswordCredentials) {
HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
httpComponentsMessageSender.setCredentials(usernamePasswordCredentials);
return httpComponentsMessageSender;
}
@Bean
@DependsOn({"marshaller"})
public TicketDetailsClient ticketDetailsClient(Jaxb2Marshaller marshaller) {
System.out.println("BEAN CREATED: TICKETDETAILSCLIENT...");
TicketDetailsClient ticketDetailsClient = new TicketDetailsClient();
ticketDetailsClient.setDefaultUri("..."); // omitted for example
ticketDetailsClient.setMarshaller(marshaller);
ticketDetailsClient.setUnmarshaller(marshaller);
return ticketDetailsClient;
}
Bean Method:
public GetTicketDetailsResponse getTicketDetails(long definitionId, long itemId) {
ObjectFactory of = new ObjectFactory();
this.template.setInterceptors(new ClientInterceptor[] {new LogHttpHeaderClientInterceptor()});
GetItemDetailsRequest itemDetailsRequest = new GetItemDetailsRequest();
itemDetailsRequest.setItemDefinitionId(definitionId);
itemDetailsRequest.setItemId(itemId);
GetTicketDetails getTicketDetails = new GetTicketDetails();
getTicketDetails.setGetItemDetailsRequest(itemDetailsRequest);
JAXBElement<GetTicketDetails> elGetTicketDetails = of.createGetTicketDetails(getTicketDetails);
System.out.println("ABOUT TO MARSHALSENDANDRECEIVE...");
GetTicketDetailsResponse ticketDetailsResponse = (GetTicketDetailsResponse) this.template.marshalSendAndReceive(elGetTicketDetails);
return ticketDetailsResponse;
}
Interceptor:
@Override
public boolean handleRequest(MessageContext arg0) throws WebServiceClientException {
// TODO Auto-generated method stub
TransportContext context = TransportContextHolder.getTransportContext();
HttpComponentsConnection connection =(HttpComponentsConnection) context.getConnection();
try {
connection.addRequestHeader("username", "testu");
connection.addRequestHeader("password", "test");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpLoggingUtils.logMessage("Client Request Message", arg0.getRequest());
return true;
}
Result Snippet (This is where I expected to see the username/password headers. Since they are missing, I'm guessing this is the issue):
ABOUT TO MARSHALSENDANDRECEIVE...
2021-08-09 13:46:18.891 INFO 23112 --- [ main] com.fp.fpcustomization.HttpLoggingUtils :
----------------------------
Client Request Message
----------------------------
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Content-Length: 378
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ns3:getTicketDetails xmlns:ns3="http://externalapi.business.footprints.numarasoftware.com/"><getItemDetailsRequest><_itemDefinitionId>76894</_itemDefinitionId><_itemId>30201</_itemId></getItemDetailsRequest></ns3:getTicketDetails></SOAP-ENV:Body></SOAP-ENV:Envelope>
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.151 s <<< FAILURE! - in com.fp.fpcustomization.FpcustomizationApplicationTests
[ERROR] RequestTest Time elapsed: 0.51 s <<< ERROR!
org.springframework.ws.client.WebServiceTransportException: [401]
at com.fp.fpcustomization.FpcustomizationApplicationTests.RequestTest(FpcustomizationApplicationTests.java:29)