Hi,
I struggle bootstrapping a working setup to achieve REST API calls with ej.library.iot:restclient:1.1.0
.
- I started from
MicroEJ/Example-IOT/ssl-rest-headless
example on Github - and also checked SSLHandshakeException during SSL connection
- & SSL — MicroEJ Documentation
but no luck so far.
I added 2 Amazon-Root-CA-1.crt
, DigiCert-Global-Root-G2.crt
resources, referenced as application resources in .list
.
The loading of these seems ok, the SSL Context configuration seems fine too, but at the end of the day I get Unknown error (-202)
when calling Resty.json("https://discovery.googleapis.com/discovery/v1/apis")
.
- Notice that it works fine with
"https://postman-echo.com/get"
. - It fails as well with other REST APIs, I tried Gravatar API for instance.
- Using the same endpoint in the provided
MicroEJ/Example-IOT/ssl-rest-headless
fails also.
I’m running the code on Simulator in eval with stm32f7508-dk:M5QNX_eval:2.2.0
.
Gradle dependencies:
dependencies {
implementation("ej.api:edc:1.3.7")
implementation("ej.library.iot:restclient:1.1.0")
implementation("ej.library.eclasspath:httpsclient:1.3.0")
microejVee("com.microej.veeport.st.stm32f7508-dk:M5QNX_eval:2.2.0")
}
Full app code to reproduce the issue:
public class Main {
public static void main(String[] args) throws GeneralSecurityException, IOException {
String[] certificates = new String[] { "Amazon-Root-CA-1.crt", "DigiCert-Global-Root-G2.crt" };
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
for (String certificateRes : certificates) {
String certificatePath = "/certificates/" + certificateRes;
System.out.println("Processing certificate: " + certificatePath);
try (InputStream inputStream = Main.class.getResourceAsStream(certificatePath)) {
Certificate certificate = certificateFactory.generateCertificate(inputStream);
System.out.println("\t- Certificate: " + certificate.getType() + " " + certificate.getPublicKey());
trustStore.setCertificateEntry(certificateRes, certificate);
}
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 && !(trustManagers[0] instanceof X509TrustManager)) {
throw new GeneralSecurityException();
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
for (TrustManager manager : trustManagers) {
System.out.println("Trust manager: " + manager.toString());
}
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, trustManagers, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
System.out.println("SSLSocketFactory: " + sslSocketFactory);
Resty httpClient = new Resty();
JSONResource works = httpClient.json("https://postman-echo.com/get");
System.out.println("JSON res working: " + works.toString());
// Exception in thread "main" @T:javax.net.ssl.SSLHandshakeException@: SSL-2.1: Unknown error (-202)
JSONResource fails = httpClient.json("https://discovery.googleapis.com/discovery/v1/apis");
System.out.println("JSON res failing: " + fails.toString());
}
}
The full exception stacktrace:
Exception in thread "main" @T:javax.net.ssl.SSLHandshakeException@: SSL-2.1: Unknown error (-202)
at java.lang.Throwable.fillInStackTrace(Throwable.java:82)
at java.lang.Throwable.<init>(Throwable.java:37)
at java.lang.Exception.<init>(Exception.java:18)
at java.io.IOException.<init>(IOException.java:18)
at javax.net.ssl.SSLException.<init>(SSLException.java:39)
at javax.net.ssl.SSLHandshakeException.<init>(SSLHandshakeException.java:38)
at com.is2t.support.net.ssl.SSLSocketSupport.initialClientHandShake(SSLSocketSupport.java:120)
at com.is2t.support.net.ssl.SSLSocketImpl.doHandShake(SSLSocketImpl.java:162)
at com.is2t.support.net.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:141)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:238)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:96)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:626)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:133)
at ej.rest.web.AbstractResource.fill(AbstractResource.java:53)
at ej.rest.web.Resty.fillResourceFromURL(Resty.java:390)
at ej.rest.web.Resty.doGET(Resty.java:338)
at ej.rest.web.Resty.json(Resty.java:187)
at ej.rest.web.Resty.json(Resty.java:175)
at net.opatry.rest.Main.main(Main.java:51)
at java.lang.MainThread.run(Thread.java:914)
at java.lang.Thread.runWrapper(Thread.java:387)