B4J Question Non_UI application Handler response

walterf25

Expert
Licensed User
Longtime User
Hi all, i am working on a personal project where I have a B4J Non-UI app running on a google cloud Virtual Machine, the app receives requests with a TokenID and message parameters which then are sent to the firebase messaging API, this works just fine, but i am having a hard time understanding how to send a response back to the client after the call has been made to the fcm.googleapis.com.

Below is my code:
B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    Dim start As Long = DateTime.Now
    resp.ContentType = "text/html;charset=utf-8"
    response = resp
    Dim messageto As String = req.GetParameter("messageto")
    Select messageto
        Case "Chofer"
            
        Case "Owner"
        SendMessageToOwnerDevice(req.GetParameter("fcmtoken"), req.GetParameter("data"))
        Case "Cliente"
            
    End Select

    Log($"took: ${DateTime.Now - start}ms"$)
    resp.Write("Notification Successful") ''I don't even get this response on the client side.
    StartMessageLoop 'we need this here, for the wait for   
End Sub

B4X:
Private Sub SendMessageToOwnerDevice(FCMToken As String, datamessage As String)
    Dim Job1 As HttpJob
    Job1.Initialize("SendMessageOwner", Me)
  
    DateTime.DateFormat="dd.MM.yyyy"
    Dim DatumZeit As String
    DatumZeit=DateTime.Date(DateTime.Now)
    DatumZeit=DatumZeit & " " & DateTime.Time(DateTime.Now)
  
  
    Dim m As Map = CreateMap("to": $"${FCMToken}"$)
    Dim data As Map = CreateMap("data": datamessage)
    m.Put("data", data)
    m.Put("content_available", True)
    Dim jg As JSONGenerator
    jg.Initialize(m)
    Job1.Tag=jg
    Log(jg.ToString)
    Job1.PostString("https://fcm.googleapis.com/fcm/send", jg.ToString)
    Job1.GetRequest.SetContentType("application/json;charset=UTF-8")
    Job1.GetRequest.SetHeader("Authorization", "key=" & Main.API_KEY)
End Sub

Sub JobDone(Job As HttpJob)
    If Job.Success Then
        Log("response: " & Job.GetString) '''I see this being logged and according to the logs it returns a successful response.
        response.ContentType = "application/json;charset=utf-8"   
        response.Write(Job.GetString) '''I never receive this response either on the client side
    Else
        '''response.SendError(500, Job.ErrorMessage)
        Log("failed to connect to server: " & Job.ErrorMessage)
    End If
    Job.Release
    StartMessageLoop
End Sub

Does anyone with more experience with this have any idea why that is, on the client side I get the following error:
ResponseError. Reason: java.net.SocketTimeoutException: timeout, Response:
error: java.net.SocketTimeoutException: timeout

Any suggestions guys?

Thanks,
Walter
 

alwaysbusy

Expert
Licensed User
Longtime User
The StartMessageLoop at the end of the JobDone() method should be a StopMessageLoop I should think.

This is a snippet I use to make some API call (note that I pass the resp variable instead of making it a global variable, not sure if it matters):
B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    resp.ContentType = "application/json"  
  
    Select Case req.Method
        Case "GET"
            If req.RequestURI.Length + 1 <= "/v1/admin/monitor/".Length Then
                ABMShared.SendError(resp, 404, "Invalid call")
                Return
            End If
            Dim PostType As String = req.RequestURI.SubString("/v1/admin/monitor/".Length)
            Select Case PostType
                Case "latest"
                    RunAPI(resp)
                    StartMessageLoop '<--- start the loop
                Case Else
                    ABMShared.SendError(resp, 404, "Invalid call")
                    Return
            End Select
...

Sub RunAPI(resp As ServletResponse)
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download(Main.MonitorUrl & "/monitor/latest")
    j.GetRequest.SetHeader("api_key", "eyJhbGciOiJIUzUx...")
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        'Log("Success")
        Dim body As TextReader
        body.Initialize(j.GetInputStream)
        resp.Write(body.ReadAll)
    Else
        resp.Status = j.Response.StatusCode
        resp.Write(j.Response.ErrorResponse)      
    End If
    j.Release
    StopMessageLoop '<--- stop the loop
End Sub

Alwaysbusy
 
Last edited:
Upvote 0

walterf25

Expert
Licensed User
Longtime User
The StartMessageLoop at the end of the JobDone() method should be a StopMessageLoop I should think.

This is a snippet I use to make some API call (note that I pass the resp veriable instead of making it a global variable, not sure if it matters):
B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    resp.ContentType = "application/json"  
  
    Select Case req.Method
        Case "GET"
            If req.RequestURI.Length + 1 <= "/v1/admin/monitor/".Length Then
                ABMShared.SendError(resp, 404, "Invalid call")
                Return
            End If
            Dim PostType As String = req.RequestURI.SubString("/v1/admin/monitor/".Length)
            Select Case PostType
                Case "latest"
                    RunAPI(resp)
                    StartMessageLoop '<--- start the loop
                Case Else
                    ABMShared.SendError(resp, 404, "Invalid call")
                    Return
            End Select
...

Sub RunAPI(resp As ServletResponse)
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download(Main.MonitorUrl & "/monitor/latest")
    j.GetRequest.SetHeader("api_key", "eyJhbGciOiJIUzUx...")
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        'Log("Success")
        Dim body As TextReader
        body.Initialize(j.GetInputStream)
        resp.Write(body.ReadAll)
    Else
        resp.Status = j.Response.StatusCode
        resp.Write(j.Response.ErrorResponse)      
    End If
    j.Release
    StopMessageLoop '<--- stop the loop
End Sub

Alwaysbusy
Weird, i could have sworn i had already tried that before, it is working now, thanks for hint.

Walter
 
Upvote 0
Top