B4J Question *SOLVED* - JavaObject - "RunMethod" acting differently in Debug and Release modes.

Claudio Oliveira

Active Member
Licensed User
Longtime User
Hey guys!
I want to get the SQLiteJDBC version programatically straight from the library itself, so I wrote this tiny little piece of code to achieve that.
The whole project is just:
B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #AdditionalJar: sqlite-jdbc-3.50.1.0
#End Region

Sub Process_Globals
    
End Sub

Sub AppStart (Args() As String)
    
    Dim jo As JavaObject
    
    jo = jo.InitializeStatic("org.sqlite.SQLiteJDBCLoader")
    Log(jo.RunMethod("getVersion", Null))

End Sub

In Debug mode I get:
Waiting for debugger to connect... Program started. 3.50.1.0 Program terminated (StartMessageLoop was not called).:
Waiting for debugger to connect...
Program started.
3.50.1.0
Program terminated (StartMessageLoop was not called).
Which is correct.

But, in Release mode all I get is the word "unknown".

I'm an absolute zero in JAVA, so if somebody can put me in the right path or maybe explain why these different behaviours in debug and release modes, I'll be immensely grateful.

Thank you, guys!
 

WebQuest

Active Member
Licensed User
Longtime User
B4X:
Sub AppStart (Form1 As Form, Args() As String)
    Dim sql As SQL
    sql.InitializeSQLite(":memory:", True) ' Usa un DB temporaneo in RAM
    
    Dim md As DatabaseMetaData = sql.GetMetaData
    Log("Driver Name: " & md.DriverName)
    Log("Driver Version: " & md.DriverVersion)

    ' Versione del motore SQLite (opzionale)
    Dim rs As ResultSet = sql.ExecQuery("SELECT sqlite_version() AS versione")
    If rs.NextRow Then
        Log("SQLite Engine Version: " & rs.GetString("versione"))
    End If
    rs.Close

    sql.Close
End Sub
 
Upvote 0

Claudio Oliveira

Active Member
Licensed User
Longtime User
Hi @WebQuest!

I appreciate your answer. Thanks, pal!
You almost hit the bullseye.

This code of yours:
B4X:
    ' Versione del motore SQLite (opzionale)
    Dim rs As ResultSet = sql.ExecQuery("SELECT sqlite_version() AS versione")
    If rs.NextRow Then
        Log("SQLite Engine Version: " & rs.GetString("versione"))
    End If
    rs.Close
Works properly, and returns SQLite driver version, however it does not return the driver's revision number, that SQLiteJDBC developers use.
For example:
sqlitejdbc-3.46 has two minor versions (3.46.0 and 3.46.1).
Version 3.46.0 has one revision (3.46.0.1) and version 3.46.1 has three revisions (3.46.1.1, 3.46.1.2 and 3.46.1.3).
So, if I reference sqlitejdbc-3.46.1.2, for instance, in my #AdditionalJar statement, your code will return "3.46.1", and it's correct, but the revision number is missing, which is important to me for info and error trappig purposes.

As for this piece:
B4X:
    Dim md As DatabaseMetaData = sql.GetMetaData
    Log("Driver Name: " & md.DriverName)
    Log("Driver Version: " & md.DriverVersion)
I just couldn't get it to work. "DatabaseMetaData"?, "sql.GetMetaData"? Where do this come from?

Well, for now I'll have to keep this information hardcoded in a global variable inside the app istself.
Meanwhile, with a little luck someone will show up with an explanation on why a java function works perfectly in debug mode but not in release mode.
I suppose there must be a reason for this ...

Thank you once more @WebQuest.
Mille Grazie
 
Upvote 0

Chris2

Active Member
Licensed User
Longtime User
B4X:
Log(jo.RunMethod("getMinorVersion", Null))
works for me in Debug & Release (although it's not particularly helpful).

But both
B4X:
Log(jo.RunMethod("getMajorVersion", Null))
Log(jo.RunMethod("getVersion", Null))
work in Debug but fail in Release mode.

In Release mode "getVersion"gives me 'unknown' in the logs like you, @Claudio Oliveira, and I think "getMajorVersion" is trying to do the same but because it should be an int (I guess) it instead throws an error:
B4X:
main._appstart (java line: 45)
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
    at b4j.example.main._appstart(main.java:45)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
    at b4j.example.main.main(main.java:28)
Caused by: java.lang.NumberFormatException: For input string: "unknown"
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:668)
    at java.base/java.lang.Integer.parseInt(Integer.java:786)
    at org.sqlite.SQLiteJDBCLoader.getMajorVersion(SQLiteJDBCLoader.java:377)
    ... 13 more

EDIT: although jo.RunMethod("getMinorVersion", Null) appears to work, it actually always seems to return 0, not the correct integer version number.
 
Last edited:
Upvote 0

teddybear

Well-Known Member
Licensed User
Well, for now I'll have to keep this information hardcoded in a global variable inside the app istself.
Meanwhile, with a little luck someone will show up with an explanation on why a java function works perfectly in debug mode but not in release mode.
I suppose there must be a reason for this ...
In release mode, the getVersion method will not work, that's because the version info is merged into your app.
Using the library you can get version info
B4X:
#Region Project Attributes
    #AdditionalJar: sqlite-jdbc-3.50.1.0
#End Region

Sub Process_Globals
  
End Sub

Sub AppStart (Args() As String)

    Dim sv As sqliteVersion
    Log(sv.GetVersion)

End Sub
 

Attachments

  • sqliteVersion.jar
    2.4 KB · Views: 12
  • sqliteVersion.xml
    1.1 KB · Views: 12
Last edited:
Upvote 0

Claudio Oliveira

Active Member
Licensed User
Longtime User
Thanks for your reply, @teddybear!
Well, that makes sense to me...
I'm not home right now. Out for the weekend. No computers! ;)
But I'll be back on sunday and will give it a try.
Thanks a lot!
 
Upvote 0

Chris2

Active Member
Licensed User
Longtime User
that's because the version info is merged into your app
Without wanting to hijak this thread but to aid my understanding, can you explain this further please?
Why does it matter if the additional jar methods are merged into the app in release mode? How are AdditionalJars treated differently than jar libraries?
 
Upvote 0

Claudio Oliveira

Active Member
Licensed User
Longtime User
In release mode, the getVersion method will not work, that's because the version info is merged into your app.
Using the library you can get version info
B4X:
#Region Project Attributes
    #AdditionalJar: sqlite-jdbc-3.50.1.0
#End Region

Sub Process_Globals
  
End Sub

Sub AppStart (Args() As String)

    Dim sv As sqliteVersion
    Log(sv.GetVersion)

End Sub
hI @teddybear!

I've got this error, in Release and Debug modes:

1751289711253.png
 
Upvote 0

Claudio Oliveira

Active Member
Licensed User
Longtime User
Here we go again...
I've built a standalone package and guess what?
@teddybear is right: It doesn't work.
Running from IDE in Release mode it works, but this message shows up:
"The following libraries should be distributed in the libs folder: JavaObject.jar jCore.jar sqlite-jdbc-3.50.2.0.jar"

1751293245835.png

InnoSetup added them correctly to the lib folder, but the error remains... 😖
 
Upvote 0

teddybear

Well-Known Member
Licensed User
Last edited:
Upvote 0

Claudio Oliveira

Active Member
Licensed User
Longtime User
YEAAAAAHHH!!!!!!!!
Worked perfectly! Running from IDE in release and debug modes, no matter what #MergeLibraries option I set, either true or false.
And the standalone package generated EXE worked perfectly as well.
You nailed it! 😃
Thanks a lot, dude!!!
Coffe paid. You deserved it!
Thank you too, @WebQuest, @Chris2 and @Daestrum for your patience and good will in trying to help me.
You guys are awsome!
 
Upvote 0

teddybear

Well-Known Member
Licensed User
1.Why does it matter if the additional jar methods are merged into the app in release mode? 2.How are AdditionalJars treated differently than jar libraries?
A1 :It will simplify your app release process.
A2: They are no difference, AdditionalJars explicitly declares which jar your app depends on
 
Upvote 0

Chris2

Active Member
Licensed User
Longtime User
A1 :It will simplify your app release process.
Thanks for your answer, but you mis-understand my question. Let me rephrase it...
In release mode, the getVersion method will not work, that's because the version info is merged into your app.
When you say 'the version info is merged into your app', I understand this as being that the methods in the sqlite-jdbc jar become part of your app's jar, is that correct? So they still exist, right?
So why does that make the getVersion method return "unknown"?
 
Upvote 0

Chris2

Active Member
Licensed User
Longtime User
I think the process of writing my post above has made me understand :).

Within he sqlite-jdbc jar (which is of course just a zip file), there's a properties file (sqlite-jdbc.properties) which contains:
B4X:
name=SQLite JDBC
version=3.50.1.0
So, I guess that with MergeLibraries: True although the methods in the sqlite jar are merged into your app these properties are not, and hence the version info becomes unavailable. Is that explanation correct?
 
Upvote 0
Top