Java + HTTPS: Unable to Find Valid Certification Path to Requested Target


When invoking a HTTPS URL from Java, for example…

final RestTemplate restTemplate = new RestTemplate();
restTemplate.execute("", HttpMethod.GET, null, ...);

…the following exception is thrown…

org.springframework.web.client.ResourceAccessException: I/O error on GET
request for ""
PKIX path building failed:
unable to find valid certification path to requested target; nested exception
PKIX path building failed:
unable to find valid certification path to requested target
	at org.springframework.web.client.RestTemplate.doExecute(
	at org.springframework.web.client.RestTemplate.execute(


One way is to simply disable the SSL validation by configuring SSLContext to trust all X.509 certificates before invoking the intended HTTPS URL.

class MyAppConfig {
    public Boolean disableSSLValidation() throws Exception {
        final SSLContext sslContext = SSLContext.getInstance("TLS");

        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
        }}, null);

        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;

        return true;

Unless you are writing test cases or implementing non-production code, this approach is highly discouraged because it doesn’t prevent the man-in-the-middle attacks.

SOLUTION 2: Import Certificate into Java Keystore – RECOMMENDED

The reason we see this exception is because the certificate used by the HTTPS URL doesn’t exist in the Java Keystore. Hence, the SSL validation fails.

To fix this, we can download the website’s certificate using a browser to be added into Java Keystore.

Access the website (in this example, I use and click on the pad lock.

Find the button that allows you to view and export the certificate as a PEM file. In this example, I named that file google.cer.

The content of the downloaded PEM file should look like this:-


Go to the Terminal.

If you have multiple versions of java, make sure you choose the correct version first:-

export JAVA_HOME="`/usr/libexec/java_home -v '1.7*'`"

Import the certificate into Java Keystore:-

sudo keytool -import -trustcacerts -file /path/to/google.cer -alias google -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit

Now, you should be able to invoke the HTTPS URL without any exception.

If for some reason you need to remove the imported certificate from Java Keystore, you can refer to that certificate using the alias and run this command:-

sudo keytool -delete -alias google -keystore $JAVA_HOME/jre/lib/security/cacerts



When accessing HTTPS links from a local application server, the modern browser throws the following error message(s):-

  • SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message. (Error code: ssl_error_weak_server_ephemeral_dh_key)
  • Server has a weak ephemeral Diffie-Hellman public key


There are multiple solutions to this problem.

SOLUTION 1: Disable browser check

One way is to completely disable this check on the browser.

For example, in Firefox, go to about:config and set security.ssl3.dhe_rsa_aes_128_sha and security.ssl3.dhe_rsa_aes_256_sha to false.

The downside is the browser is exposed to Logjam attacks.

SOLUTION 2: Use Java 8

The easiest solution is to use Java 8 because it has better cipher support.

The downside is sometimes using Java 8 is not an option if you don’t have control on the application server.

SOLUTION 3: Use Bouncy Castle

If you are using Java 6 or Java 7, you can download Bouncy Castle crypto implementation and store them in $JAVA_HOME/jre/lib/ext.

Then, register this provider in $JAVA_HOME/jre/lib/security/, for example:-

# List of providers and their preference orders (see above):
# MacOSX added as #3 ${java.home}/lib/security/sunpkcs11-macosx.cfg

The downside is if your team is doing local application development, all team members have to perform these steps on their machines too.

SOLUTION 4: Disable all weak Diffie-Hellman ciphers

Another solution is to configure the server by disabling all the weak Diffie-Hellman ciphers.

You can either enable the strong ciphers or disable the weak ciphers.

However, it is preferable (in my opinion) to disable weak ciphers so that newer (and stronger) ciphers will automatically be included when Java version is updated in the future.

Here is a working example for Jetty server:-

        <requestlog implementation="org.eclipse.jetty.server.NCSARequestLog">
            <connector implementation="">
            <connector implementation="org.eclipse.jetty.server.ssl.SslSocketConnector">

The downside is the server configuration gets a little lengthy.

HTML: Creating a Default Placeholder for Image that Fails to Load


Let’s assume our web application relies on an external system to provide the image link, for example: employee photo link of a company.

<img src="http://external/server/employeeId.jpg">

If the image link is invalid, we will get the ugly looking “x” on certain browsers.


To fix this, we can load an image placeholder from our own web application if the external image link fails to load for some reason:-

<img src="http://external/server/employeeId.jpg" onerror="this.src='http://server/app/resources/img/avatar.jpg'">