-1

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);
    }
BALA AP
  • 21
  • 3
  • What is that `Authentication` object? Why is that a `MessageSender`? How is the webservice secured? Too little information we are in need of additional details. – M. Deinum Sep 19 '22 at 07:42
  • Please don't add additional information as comments as that is totally unreadable. Please provide that information as an additional edit to your question. – M. Deinum Sep 19 '22 at 09:09
  • Your basic auth stuff looks wrong... Why are there 2 `:` there should be 1... Why is the domain added (shouldn't that be an `@`? ). Finally instead of extending the sender, I would suggest to write a `ClientInterceptor` which sets it on the transport. – M. Deinum Sep 19 '22 at 11:42
  • Thanks....I changed domain with @ user/pwd. I set in the ClientInterceptor but now i am getting : Internal Server Error [500] ......I have updated my ClientInterceptor in the question part....Please let me where I am wrong here – BALA AP Sep 19 '22 at 14:53
  • I have no idea why you are setting the content type, you shouldn't and what you are attempting to set is even wrong as well. You aren't setting the header you are setting a property those are different things! I also told you to set it on the transport **not** the message context. I've also edited your question 3 times please use proper formatting and leave the formatting that is done in place. – M. Deinum Sep 19 '22 at 16:23

1 Answers1

0

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);
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • My bad it should be `HeadersAwareSenderWebServiceConnection`, modified the question. – M. Deinum Sep 20 '22 at 05:10
  • Please suggest ......I copied the code in Questions page (last)....Please check and suggest – BALA AP Sep 20 '22 at 07:04
  • No you don't. Apparently you also need to send a `SOAPAction` which you currently aren't sending. I strongly have the feeling you have no clue on what you are doing (from a SOAP perspective and framework perspective). – M. Deinum Sep 20 '22 at 09:00
  • To provide a `SOAPAction` you need to use a different send method on the template and use the `WebServiceMessageCallback` in the form of a `SoapActionCallback` to set the proper soap action. Which to set is in your WSDL. – M. Deinum Sep 20 '22 at 09:10
  • 1
    Thanks. lot....It's working now ..Yes, Just started on SOAP and spring Framework work from other environment. Thanks for your solution and help – BALA AP Sep 20 '22 at 10:10
  • Thanks Deinum for your great support and patience. – BALA AP Sep 20 '22 at 10:33