B4J Question Working with jOkHTTPUtils2 - How to synchronous calls

Giu

Member
Licensed User
Longtime User
Hi all,

I started a little console application I wanna do with B4J.
App is simple, I have to connect to a postgres database (done) retrieve data from a table, iterate over it, and for each record I have to do a web request to retrieve a JSON to parse and take several URLs, then I have to download this images/files with that URL and fill a CSV. It's an easy task, and I started playing with pgsql connection (done) a simple select to try (done) and now I'm working with the communication with the API. I connect and retrieve data (the access_token for start) following jOkHttpUtils2 post samples. And it works, but I noticed getToken request is async, and I need to be synchronous because I can't continue with operations until I get this validation.

This is my code:

B4X:
..
..
    'ConnectToDatabase
    GetToken
    StartMessageLoop 'only required in a console app
End Sub

Sub GetToken() 'As String
    Dim j As HttpJob
    j.Initialize("", Me)
    j.PostString(baseURLToken, baseBodyToken)
    Wait For (j) JobDone(j As HttpJob) ' -- para peticiones asyncronas
    If j.Success Then
        Dim jp As JSONParser
        jp.Initialize(j.GetString)
        Dim response As Map = jp.NextObject
        token = response.Get("access_token")
        'Return response.Get("access_token")
    Else
        Log(j.Response.ErrorResponse)
    End If
    j.Release 
End Sub

As far as I undersand this code is async because the Wait, but "Wait" resumes the execution of my app, and I need to really wait until I get the token to continue processing other things.
I tried to remove Wait command and move the code after it, to a Sub called "JobDone(j as HttpJob)" and this worked, but this way all jobs done will end there and I have to control there the name of the job and so on to do one or other things, and I don't see it too much elegant. I tried calling it GetToken_JobDone as I remember to see this kind of nomenclature some years ago, and IDE don't warning about sub not being called, but debuging, is never called.

What I'm doing wrong?
 
Solution
getToken request is async,
You have to wait for getToken now.
B4X:
private sub app_start...

tokenizer ' you need to create this extra sub becasue appstart cant be a resumable sub
StartResumableSub
end sub

private sub tokenizer
 dim xrs as resumableSub = getToken
 Wait for (xrs) complete (success as boolean)
 if not(sucess) then return

 ' do more stuff after token passed

end sub

sub getToken as ResumableSub

...
return true
end sub

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
getToken request is async,
You have to wait for getToken now.
B4X:
private sub app_start...

tokenizer ' you need to create this extra sub becasue appstart cant be a resumable sub
StartResumableSub
end sub

private sub tokenizer
 dim xrs as resumableSub = getToken
 Wait for (xrs) complete (success as boolean)
 if not(sucess) then return

 ' do more stuff after token passed

end sub

sub getToken as ResumableSub

...
return true
end sub
 
Upvote 0
Solution

Giu

Member
Licensed User
Longtime User
Sorry I think I don't understand. This is keeping the wait inside GetToken? Or removing it?
Removing the wait inside GetToken I got it working creating a sub called JobDone but I don't like to have to check wich job called this sub.
 
Upvote 0

Giu

Member
Licensed User
Longtime User
I advanced on my project, and I'm so so confused. There is no way to just work as traditional way, where I call a sub/process or whathever, and just process line by line? Now I don't have clear where is my starting point. I created a StartProcess point I call before StartMessageLoop

B4X:
Sub AppStart (Args() As String)
    If Args.Length <> 1 Or (Args(0) <> "--prod" And Args(0) <> "--test") Then
        Utils.PrintCommandLineArguments
        ExitApplication
    Else
        ' SET SOME VARS
    End If

    StartProcess
    StartMessageLoop
End Sub

Sub StartProcess()
    Database.ConnectToDatabase
    OCApi.CreateToken
    Dim itemsRS As ResultSet = Database.GetItems ' <-------------------- here token is empty
    Do While itemsRS.NextRow
        OCApi.GetItemInfo(itemsRS.GetString2(0), 0)
      
    Loop
End Sub

' ********************************************* OCApi MODULE **********************************************

Sub CreateToken()
    Dim getTokenSub As ResumableSub = GetToken
    Wait for (getTokenSub) complete (getTokenComplete As Boolean)
    If getTokenComplete = False Then
        ExitApplication             
    End If

End Sub

Sub GetToken() As ResumableSub
    Dim j As HttpJob
    j.Initialize("GetToken", Me)
    j.PostString(baseURLToken, baseBodyToken)
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Dim jp As JSONParser
        jp.Initialize(j.GetString)
        Dim response As Map = jp.NextObject
        token = response.Get("access_token")
        Return True
    Else
        Log("Error trying to get token.")
        Log(j.Response.ErrorResponse)
    End If
    j.Release
    Return False
End Sub

Sub GetItemInfo(item As String, intento As Int)As ResumableSub
    Dim j As HttpJob
    j.Initialize("GetItemInfo", Me)
    j.GetRequest.SetHeader("Authorization", "Bearer " & token)
    j.GetRequest.SetContentType("application/json")
    j.PostString(baseURLProduct & item, Null)
  
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Dim jp As JSONParser
        jp.Initialize(j.GetString)
        Dim response As Map = jp.NextObject
        token = response.Get("access_token")
        Return True
    Else
        If j.Response.StatusCode = 401 Then
            If (intento < 3) Then
                intento = intento + 1
                CreateToken
                GetItemInfo(item, intento)
            End If
        End If
      
        Log("Error trying to get item info.")
        Log(j.Response.ErrorResponse)
    End If
    j.Release
    Return False
End Sub

Well, When I suppose to get the item info, I should have the token there, and is empty
 
Upvote 0
Top