1. *** New version of B4J is available ***
    B4J v7.8
    Dismiss Notice

B4J Question DBRequestManager HandleJobAsync's and "unprocessed" Wait For's

Discussion in 'B4J Questions' started by OliverA, Aug 16, 2019.

  1. OliverA

    OliverA Expert Licensed User

    Currently DBRequestManager's HandleJobAsync code is as follows
    Code:
    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)
           
    Return
       
    End If
       
    Dim res As DBResult = NewObject
       res.Tag = Job.Tag
       CallSubDelayed2(mTarget, EventName & 
    "_result", res)
    End Sub
    A typical use for this method is shown in the example provided in the jRDC2 page ():
    Code:
    Sub GetRecord (id As Int)
       
    Dim req As DBRequestManager = CreateRequest
       
    Dim cmd As DBCommand = CreateCommand("select_animal"Array(id))
       
    Wait For (req.ExecuteQuery(cmd, 0Null)) JobDone(j As HttpJob)
       
    If j.Success Then
           req.HandleJobAsync(j, 
    "req")
           
    Wait For (req) req_Result(res As DBResult)
           
    'work with result
           req.PrintTable(res)
       
    Else
           
    Log("ERROR: " & j.ErrorMessage)
       
    End If
       j.Release
    End Sub
    The issue I encounter is that if in HandleJobAsync, Success = False, then the Wait For in GetRecord never "finishes".
    Modified GetRecord routine:
    Code:
    Sub GetRecord2 (id As Int)
       
    Log($"GetRecord2 call # ${id}: entry"$)
       
    Dim req As DBRequestManager = CreateRequest
       
    Dim cmd As DBCommand = CreateCommand("select_studentids"Array())
       
    Wait For (req.ExecuteQuery(cmd, 0Null)) JobDone(j As HttpJob)
       
    If j.Success Then
           
    Log($"GetRecord2 call # ${id}: Successful query. Retrieving data"$)
           req.HandleJobAsync(j, 
    "req")
           
    Log($"GetRecord2 call # ${id}: Before Wait For"$)
           
    Wait For (req) req_Result(res As DBResult)
           
    Log($"GetRecord2 call # ${id}: After Wait For"$)
           
    'work with result
           'req.PrintTable(res)
       Else
           
    'Log("ERROR: " & j.ErrorMessage)
           Log($"GetRecord2 call # ${id}: ERROR: ${j.ErrorMessage}"$)
       
    End If
       j.Release
       
    Log($"GetRecord2 call # ${id}: exit"$)
    End Sub
    Called with following loop
    Code:
    For i = 0 To 3
       GetRecord2(i)
    Next
    will produce the following result when everything goes ok
    and the following if Success = False in HandleJobAsync
    Notice that nothing is executed after the Wait For in GetRecord2?

    A solution may be to do a CallSubDelayed2 no matter what. In case of Success = False, return a Null value for the DBResult. This then would need checking in the calling code.
    Code:
    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)
       
    Dim res As DBResult = Null
       
    If Success = False Then
           
    Log("Error reading response: " & LastException)
       
    Else
           res = NewObject
           res.Tag = Job.Tag
       
    End If
       CallSubDelayed2(mTarget, EventName & 
    "_result", res)
       
    Return
    End Sub
    With this change, the logging (upon Success = False) produces
    Note: This break existing code, so another option may be necessary
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    What causes ser_ConvertBytesToObjectsAsync to fail? This is not something that should normally happen.
     
  3. OliverA

    OliverA Expert Licensed User

    But if it does, there is no way to programmatically catch this as is. Yes, there is a log entry, but the programmer has no clue and there is a wait for that will never execute. I guess I can just have my own mod of DBRequestManager, but I was hoping for something more universal.
    Maybe a failed hacking attempt? jRDC2 may not be well known, but it could become a target. Flipped bits that are not caught by networking checksums? Yes, I'm just guessing here. If at this point of the stage (after receiving an answer from jRDC2) if you think ser_ConvertBytesToObjectsAsync should not fail, why test for success at all in the original code? Why not just assign newObject to res and if something's gone wrong let the code bomb out? At least one could then use a try catch around HandleAsyncJobs if one is worried about failures. As the code stands right now, the only way to tell that a failure occurred is through a log entry.
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    I don't think that this is really related.

    If the data was downloaded properly (Job.Success = True) then the payload will be serialized properly. If it wasn't serialized properly then you probably made a programming mistake and you will see it during development.

    Just because the API passed this flag. I agree that not testing for it is also fine.

    There is no real issue here and I don't think that it is worth changing anything.
     
    Johan Hormaza likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice