B4J Question [SOLVED] Using a client certificate with MQTT as a standalone executable

Ralph Parkhurst

Member
Licensed User
Longtime User
By following this B4J Code Snippet and sample project how-to-connect-to-a-mqtt-broker-that-requires-a-client-certificate I have been able to successfully connect to my MQTT broker when run B4J in Debug or Release compilation modes. The code snippet works very well and I only needed to add my three certificate details and the MQTT broker URL to make it work.

However despite many attempts, I am unable to get it to connect when I use the built-in packager to build a standalone executable.

If have tried adding:

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
    #AdditionalJar: bcprov-jdk15on-170
    #AdditionalJar: bcpkix-jdk15on-170
    #PackagerProperty: AdditionalModuleInfoString = provides org.eclipse.paho.client.mqttv3.spi.NetworkModuleFactory with org.eclipse.paho.client.mqttv3.internal.TCPNetworkModuleFactory, org.eclipse.paho.client.mqttv3.internal.SSLNetworkModuleFactory,  org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketNetworkModuleFactory, org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketSecureNetworkModuleFactory;
    #PackagerProperty: VMArgs = --add-opens b4j/org.bouncycastle.jcajce.provider.asymmetric.rsa=java.base
#End Region

However when I build try to build and a standalone executable, the sample project crashes. When I run Run_debug.bat, I see the following debug information:

Debug output when running standalone exe:
C:\B4J_Projects\SocketFactory\Objects\temp\build\bin>java.exe @release_java_modules.txt --add-opens b4j/org.bouncycastle.jcajce.provider.asymmetric.rsa=java.base -m b4j/b4j.example.main
java.security.cert.CertificateException: X.509 not found
        at java.base/java.security.cert.CertificateFactory.getInstance(Unknown Source)
        at b4j/org.bouncycastle.cert.jcajce.NamedCertHelper.createCertificateFactory(Unknown Source)
        at b4j/org.bouncycastle.cert.jcajce.CertHelper.getCertificateFactory(Unknown Source)
        at b4j/org.bouncycastle.cert.jcajce.JcaX509CertificateConverter.getCertificate(Unknown Source)
        at b4j/b4j.example.main$SslUtil.getSocketFactory(Unknown Source)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at b4j/anywheresoftware.b4j.object.JavaObject.RunMethod(Unknown Source)
        at b4j/b4j.example.main._appstart(Unknown Source)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at b4j/anywheresoftware.b4a.BA.raiseEvent2(Unknown Source)
        at b4j/anywheresoftware.b4a.BA.raiseEvent(Unknown Source)
        at b4j/b4j.example.main.start(Unknown Source)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(Unknown Source)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(Unknown Source)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: X.509, provider: BC, class: org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory)
        at java.base/java.security.Provider$Service.newInstance(Unknown Source)
        at java.base/sun.security.jca.GetInstance.getInstance(Unknown Source)
        at java.base/sun.security.jca.GetInstance.getInstance(Unknown Source)
        ... 27 more
Caused by: java.lang.IllegalAccessException: class java.security.Provider (in module java.base) cannot access class org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory (in module b4j) because module b4j does not export org.bouncycastle.jcajce.provider.asymmetric.x509 to module java.base
        at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Unknown Source)
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
        at java.base/java.security.Provider.newInstanceUtil(Unknown Source)
        ... 30 more

I suspect there may be a #PackageProperty I am missing, but I really am not sure what to do from here.

I am using:
B4J version 9.3
Java 11.0.1
 

Ralph Parkhurst

Member
Licensed User
Longtime User
I managed to solve this by using some guesswork.

For anyone else with the same issue, I was able to create a working standalone executable by adding:

B4X:
#PackagerProperty: VMArgs = --add-opens b4j/org.bouncycastle.jcajce.provider.asymmetric.x509=java.base
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…