Not able to call SOAP API in WebServiceGatewaySupport by Spring WebServiceTemplate - Need help to fix this issue

Viewed 69

I am trying to call SOAP API in Java Spring Boot using WebServiceGatewaySupport by Spring WebServiceTemplate

Config java class

public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, ClientInterceptor clientInterceptor) {
        
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        
    //SOAP URL
    webServiceTemplate.setDefaultUri("http://host/Services.asmx");
            
            
    //Auth ---It seems issue is here only????? need to check
    webServiceTemplate.setMessageSender(new Authentication());
                     
    webServiceTemplate.setMarshaller(marshaller);
    webServiceTemplate.setUnmarshaller(marshaller);
    
    webServiceTemplate.afterPropertiesSet();
    webServiceTemplate.setCheckConnectionForFault(true);
    webServiceTemplate.setInterceptors((ClientInterceptor[]) Arrays.asList(createLoggingInterceptor()).toArray());     
    return webServiceTemplate;
}

SOAP Client Call

public class TicketClient extends WebServiceGatewaySupport {
    
    public String getTicket(Ticket req) {

        System.out.println("test inside webservice support1");
        
        response = (AcquireTicketResponse) getWebServiceTemplate().marshalSendAndReceive(req);

Authentication Class

public class Authentication extends HttpUrlConnectionMessageSender { 
   
@Override protected void prepareConnection(HttpURLConnection connection) { 

String userpassword = username+":"+password+":"+domain; 
String encoded = 
Base64.getEncoder().withoutPadding().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8)); 

connection.setRequestProperty("Authorization", "Basic "+encoded); connection.setRequestProperty("Content-Type", "application/xml"); super.prepareConnection(connection);
    
}

Not using Authetication class and add the above into

ClientInterceptor

public class SoapLoggingInterceptor implements ClientInterceptor {

@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {


        String username="test";
        String password="test";
        String domain = "@test";
        String userpassword = username+":"+password+domain;
         
        String encoded = Base64.getEncoder().withoutPadding().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8));       
        messageContext.setProperty("Authorization", "Basic "+encoded);    
        messageContext.setProperty("Content-type", "XML");   

Case -1 --->When I passed (user, pwd, domain and content-type) through messagesender, content type is taking but throwed "BAD REQUEST ERROR 400"....When i comment contenttype property, then it throwed "INTERNAL SERVER ERROR 500".

Case-2...when I passed (user, pwd, domain and content-type) through ClientInterceptor , always it throwed "INTERNAL SERVER ERROR 500"......It seems Authentication properties for the service are not going to API call.............................Please suggest some options

Both the cases, Authentication is not passing to service, if i comment,Authentication code (userid/pwd/domain) in both cases also...no efforts in output



After setting the user ID/pwd

@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        String username="test";
        String password="test";
        String domain = "@test";
        String userpassword = username+":"+password+domain;
        
        byte[] userpassword = (username+":"+password).getBytes(StandardCharsets.UTF_8);        
        String encoded = Base64.getEncoder().encodeToString(userpassword);       
         
        
    ByteArrayTransportOutputStream os = new 
  ByteArrayTransportOutputStream();
    
    try {

        
        TransportContext context = TransportContextHolder.getTransportContext();    
        WebServiceConnection conn = context.getConnection();                
        ((HeadersAwareSenderWebServiceConnection) conn).addRequestHeader("Authorization", "Basic " + encoded);  
    
        

        
    } catch (IOException e) {
        throw new WebServiceIOException(e.getMessage(), e);
    }
1 Answers

First of all don't set the content type Spring WebServices will do that for you, messing around with that will only make things worse.

You should get the WebServiceConnection and cast that to a HeadersAwareSenderWebServiceConnection to add a header.

public class BasicAuthenticationInterceptor implements ClientInterceptor {

  @Override
  public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
    String username="test@test";
    String password="test";
    byte[] userpassword = (username+":"+password).getBytes(UTF_8);        
    String encoded = Base64.getEncoder().encodeToString(userpassword);       
     
    WebServiceConnection conn = TransportContext.getConnection();
    ((HeadersAwareSenderWebServiceConnection) conn).addHeader("Authorization", "Basic " + encoded);
  }
}

You also need to configure it. Assuming it is a bean don't call afterPropertiesSet (and ofcourse you are now using the ClientInterceptor remove the new Authentication() for your customized message sender.

The List<ClientInterceptor> will automatically create a list with all the interceptors so you can easily inject them.

@Bean
public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, List<ClientInterceptor> clientInterceptors) {
        
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller);       
    //SOAP URL
    webServiceTemplate.setDefaultUri("http://host/Services.asmx");
    webServiceTemplate.setCheckConnectionForFault(true);
    webServiceTemplate.setInterceptors(clientInterceptors);     
    return webServiceTemplate;
}

If this doesn't work there is something else you are doing wrong and you will need to get in touch with the server developers and get more information on the error.

Update:

Apparently you also need to provide a SOAP Action in your request, which you currently don't. For this you can specify the SoapActionCallback in the marshalSendAndReceive method. Which action to specify you can find in the WSDL you are using.

SoapActionCallback soapAction = new SoapActionCallback("SoapActionToUse");
response = (AcquireTicketResponse) getWebServiceTemplate().marshalSendAndReceive(req, soapAction);
Related