When I try to call web service via WebServiceTemplate, which provided by Spring framework. It throw the following exception:
java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty; nested exception is javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:561) at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390) at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:378)
The code snippet is as following:
package demo.service.client; import javax.net.ssl.TrustManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.ws.client.core.WebServiceTemplate; import demo.dto.status; import demo.dto.mapper.StatusMapper; import demo.ws.bind.status.SendStatusRequest; import demo.ws.bind.status.SendStatusResponse; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class StatusClient { @Autowired private WebServiceTemplate wsTemplate; @Value("${webservices.host}") private String host; @Value("${webservices.url.status}") private String url; @Autowired private StatusMapper mapper; public SendStatusResponse sendData(Status entity) { SendStatusRequest request = new SendStatusRequest(); request.setStatusDto(mapper.toDto(entity)); return (SendStatusResponse) wsTemplate.marshalSendAndReceive(host + url, request); } }
How-To
Owing to the web service url is https, so you need to disable SSL certificate checking.
You need create an UnTrustworthyTrustManager:
package demo.service.client; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; public class UnTrustworthyTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // TODO Auto-generated method stub } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // TODO Auto-generated method stub } @Override public X509Certificate[] getAcceptedIssuers() { // TODO Auto-generated method stub return null; } }
And set UnTrustworthyTrustManager into MessageSender
package demo.service.client; import javax.net.ssl.TrustManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.transport.http.HttpsUrlConnectionMessageSender; import demo.dto.status; import demo.dto.mapper.StatusMapper; import demo.ws.bind.status.SendStatusRequest; import demo.ws.bind.status.SendStatusResponse; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class StatusClient { @Autowired private WebServiceTemplate wsTemplate; @Value("${webservices.host}") private String host; @Value("${webservices.url.status}") private String url; @Autowired private StatusMapper mapper; public SendStatusResponse sendData(Status entity) { HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender(); sender.setTrustManagers(new TrustManager[] { new UnTrustworthyTrustManager() }); wsTemplate.setMessageSender(sender); SendStatusRequest request = new SendStatusRequest(); request.setStatusDto(mapper.toDto(entity)); return (SendStatusResponse) wsTemplate.marshalSendAndReceive(host + url, request); } }