Total Pageviews

2019/02/12

[Spring] java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

Problem
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);
    }
    
}


No comments: