B4J Question B4J Jackcess Problem - Works from UI but gets ExceptionInInitializerError when run as Standalone .EXE file

PJLPJLPJL

Member
Licensed User
I'd be grateful for help with this issue.
I'm using Jackcess to read a .MDB database in B4J on a Windows 10 PC (64-b20H2 with Java JDK11.0.1 and Java 8 Update 271)
The program works perfectly when run from the B4J UI (in either debug or release mode) provided I include a "#AdditionalJar: commons-logging-1.1.3" statement in Main (btw also needed when using Jackcess in B4A).
But when I build a standalone package the .EXE crashes with an error message that begins "java.lang.ExceptionInInitializerError" (full text below). The form is displayed and MsgBox "1" appears, but when it's dismissed the program then fails so it's the Access.Open statement (ie the invocation of Jackcess) that's causing the problem (MsgBox "2" doesn't appear).

My code is:
Test program which opens and reads MS Access DB on Windows 10 PC:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region

'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip

Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Public Const PLDir As String = "D:\New Folder" ' Hardcoded just for demo program
    Public const PLFile As String="COVID-19.mdb"
    Public Access As JackcessDatabase
    Public ACTable As JackcessTable
    Public ACIndex As JackcessIndex
End Sub

Public Sub Initialize
   
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    xui.MsgboxAsync("1 " & PLDir & "\" & PLFile & CRLF & File.Exists(PLDir,PLFile),"Test")
    Wait for msgbox_result
    Access.open(PLDir & "\" & PLFile)
    xui.MsgboxAsync("2 DB " & PLFile & " opened","Test")
    Wait for msgbox_result
    ACTable.Initialize(Access.GetTable("Electoral_Roll"))
    ACIndex.Initialize(ACTable.GetIndex("Android"))

End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Sub Button1_Click
    xui.MsgboxAsync("3 " & NumberFormat(ACTable.GetRowCount,1,0) & " Members","Test")
    wait for msgbox_result
    ExitApplication
End Sub

From Main module:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
    #AdditionalJar: commons-logging-1.1.3
#End Region

Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
b4xmainpage$ResumableSub_B4XPage_Created.resume (java line: -1)
java.lang.ExceptionInInitializerError
at b4j/com.healthmarketscience.jackcess.GeneralLegacyIndexCodes.getCharHandler(Unknown Source)
at b4j/com.healthmarketscience.jackcess.GeneralLegacyIndexCodes.writeNonNullIndexTextValue(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexData$GenLegTextColumnDescriptor.writeNonNullValue(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexData$ColumnDescriptor.writeValue(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexData.createEntryBytes(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexData.access$3000(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexData$EntryCursor.beforeEntry(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexCursor.findPotentialRow(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexCursor.findFirstRowByEntryImpl(Unknown Source)
at b4j/com.healthmarketscience.jackcess.IndexCursor.findFirstRowByEntry(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database$DefaultTableFinder.findRow(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database$TableFinder.findObjectId(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.readSystemCatalog(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.<init>(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.open(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.open(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.open(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.open(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.open(Unknown Source)
at b4j/com.healthmarketscience.jackcess.Database.open(Unknown Source)
at b4j/anywheresoftware.b4a.objects.JackcessDatabase.Open(Unknown Source)
at b4j/b4j.example.b4xmainpage$ResumableSub_B4XPage_Created.resume(Unknown Source)
at b4j/anywheresoftware.b4a.BA.checkAndRunWaitForEvent(Unknown Source)
at b4j/anywheresoftware.b4a.BA.raiseEvent2(Unknown Source)
at b4j/anywheresoftware.b4a.BA$1.run(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.lang.RuntimeException: failed loading index codes file com/healthmarketscience/jackcess/index_codes_genl
eg.txt
at b4j/com.healthmarketscience.jackcess.GeneralLegacyIndexCodes.loadCodes(Unknown Source)
at b4j/com.healthmarketscience.jackcess.GeneralLegacyIndexCodes$Codes.<clinit>(Unknown Source)
... 32 more
Caused by: java.io.IOException: Could not load jackcess resource com/healthmarketscience/jackcess/index_codes_genleg.txt

at b4j/com.healthmarketscience.jackcess.Database.getResourceAsStream(Unknown Source)
... 34 more

C:\Users\xxxxxxxxxxxx\Dropbox\Documents\B4J\Projects\test\B4J\Objects\temp\build\bin>pause
Press any key to continue . . .

I've attached a zip containing the program and another containing the database so you can test if you want to.

Again, huge thanks for any help you can give.
 

Attachments

  • Backup test 2021-01-14 12.18.zip
    3 KB · Views: 112
  • COVID-19.zip
    30.4 KB · Views: 114

PJLPJLPJL

Member
Licensed User
Thank you Erel. Yes, I'd already seen that thread and done some tests with ucanaccess.
I had two reasons for sticking with Jackcess: I couldn't get ucanaccess to work either (but could probably try harder); and I want the app to be portable to Android and I don't think ucanaccess works on Android (whereas Jackcess does).
If you're saying that ucanaccess is the way to go I will happily revisit my attempts.
Again, huge thanks.
 
Upvote 0

PJLPJLPJL

Member
Licensed User
Thank you Erel.
I see what your saying about the 4 text files - they're something to do with indexes for Jackcess and the error messages also contain references to failing to load index codes.
As I understand it (and I may be wrong) the "files" directory contains files (eg. icons, layouts etc.) that are available to the app as it runs.
However, where do they need to be for the standalone .EXE to find them? There is no "files" directory in the "build" directory that the .EXE ends up in. Are they bound into the .EXE or is it still looking for them? (I can't find the icon or layout files anywhere near the .EXE file either).
Forgive my ignorance of all this - I'm new to java and B4X. It's a thoroughly wonderful system and I'm very grateful for your patient help.
 
Upvote 0

PJLPJLPJL

Member
Licensed User
I'm hunting!
They are included in the .JAR file which goes to make the .EXE. Does that explain why it runs in the UI but not standalone?
 
Upvote 0

PJLPJLPJL

Member
Licensed User
Again, thank you Erel. UCanAccess is the answer.
For others navigating the (treacherous) waters of using Access on both Windows and Android, I'll mention that I succeeded using B4J (on the Windows PC) with UCanAccess v 5 (and associated dependencies) and on the Android phone with UCanAccess v 4. As I'm using B4XPages this is easy. The functional code is identical but the #AdditionalJar statements and the files in the additional libraries are different. For clarity I'll list below:
Android B4A statements:
    #AdditionalJar: jackcess-2.1.11
    #AdditionalJar: ucanaccess-4.0.4
    #AdditionalJar: commons-lang-2.6
    #AdditionalJar: commons-logging-1.1.3
    #AdditionalJar: hsqldb-2.3.1

Windows B4J Statements:
#AdditionalJar: ucanaccess-5.0.0
#AdditionalJar: commons-lang3-3.8.1
#AdditionalJar: commons-logging-1.2
#AdditionalJar: hsqldb-2.5.0
#AdditionalJar: jackcess-3.0.1-B4J

Both used the same connection string:
UCanAccess Connection String:
    SQL.Initialize("net.ucanaccess.jdbc.UcanaccessDriver", "jdbc:ucanaccess://D:pathname/file.mdb") 'change path as needed

Hope this helps others.
 
Upvote 0
Top