B4J Question jRDC2 b4j and b4a: Client gets .EOFException

Not open for further replies.


Licensed User
jRDC2 servlet appears to be running fine. Using the tutorial example.
When calling the jRDC2 servlet from B4A or B4J UI app I am getting an EOF exception.
The error comes on this call in the BDRequestManager.bas
ser.ConvertBytesToObjectAsync(data, "ser")

Public Sub HandleJobAsync(Job As HttpJob, EventName As String)
    Dim ser As B4XSerializator
    Dim data() As Byte = Bit.InputStreamToBytes(Job.GetInputStream)
    ser.ConvertBytesToObjectAsync(data, "ser")
    Wait For (ser) ser_BytesToObject (Success As Boolean, NewObject As Object)
    If Success = False Then
        Log("Error reading response: " & LastException)
    End If
    Dim res As DBResult = NewObject
    res.Tag = Job.Tag
    CallSubDelayed2(mTarget, EventName & "_result", res)
End Sub

My Code:

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    '<<  jRDC
    Type DBResult (Tag As Object, Columns As Map, Rows As List)
    Type DBCommand (Name As String, Parameters() As Object)
    Private const rdcLink As String = ""
End Sub
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
End Sub
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
End Sub
Sub GetUsers 
    Dim req As DBRequestManager = CreateRequest
    Dim cmd As DBCommand = CreateCommand("select_all_users",Null)
    Wait For (req.ExecuteQuery(cmd, 0, Null)) JobDone(j As HttpJob)
    If j.Success Then
        req.HandleJob( j)
        Wait For (req) req_Result(res As DBResult)
        'work with result
        Log("ERROR: " & j.ErrorMessage)
    End If
End Sub
Sub CreateRequest As DBRequestManager
    Dim req As DBRequestManager
    req.Initialize(Me, rdcLink)
    Return req
End Sub
Sub CreateCommand(Name As String, Parameters() As Object) As DBCommand
    Dim cmd As DBCommand
    cmd.Name = Name
    If Parameters <> Null Then cmd.Parameters = Parameters
    Return cmd
End Sub

Here is the Logs from the B4A UI

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Error occurred on line: 73 (DBRequestManager)
java.lang.RuntimeException: java.io.EOFException
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readType(B4XSerializator.java:297)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:357)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.ReadObject(B4XSerializator.java:112)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.ConvertBytesToObject(B4XSerializator.java:82)
at b4a.example.dbrequestmanager._handlejob(dbrequestmanager.java:98)
at b4a.example.main$ResumableSub_GetUsers.resume(main.java:491)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resumeAsUserSub(DebugResumableSub.java:48)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:735)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:357)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:260)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resume(DebugResumableSub.java:43)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:245)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:137)
at anywheresoftware.b4a.BA$2.run(BA.java:365)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5438)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:77)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readByte(B4XSerializator.java:133)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:301)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readList(B4XSerializator.java:246)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:354)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readList(B4XSerializator.java:246)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:354)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readList(B4XSerializator.java:246)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:354)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readList(B4XSerializator.java:246)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:354)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readList(B4XSerializator.java:246)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:345)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readMap(B4XSerializator.java:231)
at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readType(B4XSerializator.java:275)
... 27 more
** Activity (main) Pause, UserClosed = true **
** Service (starter) Destroy (ignored)**

Here is the Log from the jRDC2 servlet. Note that I have printed part of the resulting data set to the log.

Waiting for debugger to connect...
Program started.
2018-10-03 10:23:33.562:INFO::main: Logging initialized @567ms to org.eclipse.jetty.util.log.StdErrLog
Oct 03, 2018 10:23:33 AM com.mchange.v2.log.MLog
INFO: MLog clients using java 1.4+ standard logging.
Oct 03, 2018 10:23:33 AM com.mchange.v2.c3p0.C3P0Registry
INFO: Initializing c3p0- [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
2018-10-03 10:23:33.991:INFO:eek:ejs.Server:main: jetty-9.4.z-SNAPSHOT
2018-10-03 10:23:34.033:INFO:eek:ejs.session:main: DefaultSessionIdManager workerName=node0
2018-10-03 10:23:34.033:INFO:eek:ejs.session:main: No SessionScavenger set, using defaults
2018-10-03 10:23:34.036:INFO:eek:ejs.session:main: Scavenging every 660000ms
2018-10-03 10:23:34.041:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@6895a785{/,file:///C:/DataVault/B4X/B4J/jRDC/Objects/www,AVAILABLE}
2018-10-03 10:23:34.052:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened C:\DataVault\B4X\B4J\jRDC\Objects\logs\b4j-2018_10_03.request.log
2018-10-03 10:23:34.067:INFO:eek:ejs.AbstractConnector:main: Started ServerConnector@1d362d33{HTTP/1.1,[http/1.1]}{}
2018-10-03 10:23:34.068:INFO:eek:ejs.Server:main: Started @1074ms
Emulated network latency: 100ms
jRDC is running (version = 2.21)
Oct 03, 2018 10:23:48 AM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 20000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge13o9yg6gtv11i5v7f6|7a46a697, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge13o9yg6gtv11i5v7f6|7a46a697, idleConnectionTestPeriod -> 600, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, ma...
Oct 03, 2018 10:23:49 AM com.mchange.v2.c3p0.stmt.GooGooStatementCache
INFO: Multiply-cached PreparedStatement: SELECT * FROM tblContacts
Wade Pa
Wade PA
Kevin FL
Kathy FL

Command: query: select_all_users, took: 292ms, client=


Licensed User
Okay, It does not seem to make a difference with release mode. On the server side or on the client side. It has something to do with the '*' wild card. When I replace it with designated columns it works.

sql.TEST_QRY=SELECT UserName, State, Zip FROM `tblContacts`

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Tag: null, Columns: 3, Rows: 4
UserName State Zip
Wade Pa 4444
Wade PA 44444
Kevin FL 55252
Kathy FL 22525
Upvote 0


Licensed User
It's not just the '*'. I can use the wildcard in other queries that work.
For Example;In a different database on the same MariaDB server.

sql.TEST_QRY=SELECT * FROM `tblCounty`

This works.
Upvote 0


Licensed User
Longtime User
INFO: Multiply-cached PreparedStatement
This seems to be the hint that you need to investigate.
What code changes did you make to jRDC2 to print out the result? Did you notice that even you have SELECT *, only two columns are shown (in the jRDC log), even though later you show a working query that pulls more than two columns?
Upvote 0


Well-Known Member
Licensed User
Longtime User

I know this is an old thread, I have got the same info error this morning, quick google and found this:

private void assimilateNewCheckedOutStatement( StatementCacheKey key, 
                    Connection pConn,
Object ps )
        stmtToKey.put( ps, key );
        HashSet ks = keySet( key );
        if (ks == null)
            keyToKeyRec.put( key, new KeyRec() );
            //System.err.println("-------> Multiply prepared statement! " + key.stmtText );
            if (logger.isLoggable(MLevel.INFO))
                logger.info("Multiply-cached PreparedStatement: " + key.stmtText );
            if (Debug.DEBUG && logger.isLoggable(MLevel.FINE))
                logger.fine("(The same statement has already been prepared by this Connection, " +
                                "and that other instance has not yet been closed, so the statement pool " +
                                "has to prepare a second PreparedStatement object rather than reusing " +
                                "the previously-cached Statement. The new Statement will be cached, in case " +
                "you frequently need multiple copies of this Statement.)");
        keySet( key ).add( ps );
        cxnStmtMgr.addStatementForConnection( ps, pConn );

        if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX)
//          System.err.println("cxnStmtMgr.statementSet( " + pConn + " ).size(): " + 
//          cxnStmtMgr.statementSet( pConn ).size());
            if (logger.isLoggable(MLevel.FINEST))
                logger.finest("cxnStmtMgr.statementSet( " + pConn + " ).size(): " + 
                                cxnStmtMgr.statementSet( pConn ).size());

        checkedOut.add( ps );

Have not fixed it yet, but my understanding from reading the logger.fine, that what we,I, am doing is inefficient. I am call a func in a class from a worker thread in a b4j server app.

Sub get_event(pEvent As CM_EVENT, pSql As SQL) As CM_EVENT

    Dim rs As ResultSet
    Dim res As CM_EVENT
    Dim sDate As String, sSql As String
    sSql = $"SELECT * FROM [IS_CRITICALMSG].[dbo].[cm_events]
                        WHERE cm_svr_id = '${pEvent.cm_svr_id}' AND
                            public_id = '${pEvent.public_id}' AND
                            event_type = ${pEvent.event_type}"$
    rs = pSql.ExecQuery(sSql)
    If rs.NextRow Then
        Log("cls_events::get_event->event found")
        sDate = rs.GetString("event_expiry")
        res.cm_svr_id = rs.getstring("cm_svr_id")
        res.public_id = rs.getstring("public_id")
        res.event_type = rs.GetInt("event_type")
        res.event_expiry = convert_date_to_long(sDate)
        res.valid = True
        Log("cls_events::get_event->event not found")
    End If
    Return res
End Sub

Upvote 0
Not open for further replies.