Search code examples
javaspringsslwebspheresoap-client

SOAP Spring Client Request over https and through firewall


It has been a while since I wrote a SOAP client, but I am trying to write a client that connects / consumes an external SOAP service across https and through a firewall.

I have manually pulled the wsdl and schemas and used Eclipse Web Service Client feature to generate web service code. I am calling the client code through a get request at moment just to see if I can even connect to the WS. I can browse the WSDL in Chrome\IE and able to use ReadyApi to test the connection outside of Java and RAD/WebSphere.

@Bean
public Jaxb2Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();     
    marshaller.setPackagesToScan("com.complianceservice.client");
    try {
        marshaller.afterPropertiesSet();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return marshaller;
}
@Bean
public VendorClient vendorClient(Jaxb2Marshaller marshaller) {
    VendorClient client = new VendorClient ();
    client.setDefaultUri("https://webservice.vendor.com/WebServices/productServices.svc?wsdl");
    client.setMarshaller(marshaller);
    client.setUnmarshaller(marshaller);
    return client;
}

This will call the client service code...

@GetMapping(value = "/health")
public String getHealth() throws ResponseException {
    Response response = vendorComplianceService.processHealth();
    return response!= null?"Health, OK":"Problem detected";
}

@Override
public MessageResponse processHealth() throws ResponseException {
    try {
        GetDaysUntilPasswordExpiresResponse response = vendorClient.getGetDaysUntilPasswordExpires();
        if (response != null){
            MessageResponse myResponse = new MessageResponse();
        //set something
            return myResponse;
        }
    } catch (Exception e) {
        e.printStackTrace();
        throw new ResponseException(e);
    }       
    return null;
}

public GetDaysUntilPasswordExpiresResponse getGetDaysUntilPasswordExpires( ){

    GetDaysUntilPasswordExpires requestPayload = new GetDaysUntilPasswordExpires();
    requestPayload.setContext(healthClientContext());   
    log.info("Requesting expire info for :" + clientContext.getUserID());       
    GetDaysUntilPasswordExpiresResponse response = (GetDaysUntilPasswordExpiresResponse) getWebServiceTemplate()
            .marshalSendAndReceive("https://webservice.vendor.com/WebServices/IAccount/GetDaysUntilPasswordExpires", requestPayload                     
            );
    return response;
}

This will just timeout looking for a connection response from the server because our firewall is blocking it.

How do I tell this client code to use proxy settings to get through our Firewall in Java/Spring? In REST I am able to specify an httpclient that uses Proxy credential provider with an ssl connection socket factory. I am not sure how to do this with the SOAP client that uses the WebServiceTemplate to marshal, send and receive. Is this even a good idea?

Also how can I log or view the actual SOAP request to make sure I am sending proper format?

For those familiar with WebSphere, how can I ensure the remote certificates are properly installed and usable?


Solution

  • A combination of @dbreaux help to add the CA to WAS and the following solved the issue .

    In the AppConfig, I added this bean ...

    @Bean
    public WebServiceTemplate webServiceTemplate(){
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        MessageFactory msgFactory = null;
        try {
            msgFactory = MessageFactory.newInstance(SOAPConstants.DEFAULT_SOAP_PROTOCOL);
        } catch (SOAPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        SaajSoapMessageFactory newSoapMessageFactory = new SaajSoapMessageFactory(msgFactory);
        webServiceTemplate.setMessageFactory(newSoapMessageFactory);
        webServiceTemplate.setMarshaller(marshaller());
        webServiceTemplate.setUnmarshaller(marshaller());
        return webServiceTemplate; 
    }
    
    //and then wired into the client component and set system properties for https proxy
    
    public GetDaysUntilPasswordExpiresResponse getGetDaysUntilPasswordExpires(  ){
        System.getProperties().put("https.proxyHost", HTTPS_PROXY_HOST );  
        System.getProperties().put("https.proxyPort", HTTPS_PROXY_PORT);
    
        System.getProperties().put("https.proxyUser", HTTPS_PROXY_USER );  
        System.getProperties().put("https.proxyPassword", HTTPS_PROXY_PASSWORD);
        GetDaysUntilPasswordExpires requestPayload = new GetDaysUntilPasswordExpires();
        requestPayload.setContext( healthClientContext());
    
        log.info("Requesting expire info for :" + healthClientContext.getUserID()); 
        GetDaysUntilPasswordExpiresResponse response = (GetDaysUntilPasswordExpiresResponse) webServiceTemplate 
                .marshalSendAndReceive(
                        VENDOR_WS_URL+"/Account"
                        ,requestPayload 
                        ,new SoapActionCallback(VENDOR_WS_NAMESPACE_URL+"/IAccount/GetDaysUntilPasswordExpires"){
                            @Override
                            public void doWithMessage(WebServiceMessage message)
                                    throws IOException {
                                SaajSoapMessage soapMessage = (SaajSoapMessage) message;
                                soapMessage.setSoapAction(VENDOR_WS_NAMESPACE_URL+"/IAccount/GetDaysUntilPasswordExpires");   
                            }
                        }
                );
        return response;
    }