Android Question [SOLVED] Please help: WaitFor with HttpJob inside a Class Module - Thanks

Mashiane

Expert
Licensed User
Longtime User
Hi there

In my app, I had a subroutine in a static code module to execute some httpjobs, now with the wait for, I converted my code module to a class and am trying to make thus sub work with waitfor. This sub is called about 30 or so times in my app for different things... So I made an adjustment to try to make this work to no avail. The error is ...

B4X:
java.lang.Exception: Sub jobdone was not found.

B4X:
Sub ExecutePHP(frm As Object, pQuery As Map, JobName As String, phpFile As String, phpTag As String)
    Dim job As HttpJob
    Dim scommand As String
    Dim json As String
    job.Initialize(JobName, frm)
    job.Tag = phpTag
    json = Map2QueryString(pQuery)
    If Len(json) = 0 Then
        scommand = $"${Starter.phpPath}${phpFile}"$
    Else
        scommand = $"${Starter.phppath}${phpFile}?${json}"$
    End If
    Log(scommand)
    job.Download(scommand)
    Wait For(job) JobDone(job As HttpJob)
    CallSub2(frm,"JobIsDone",job)
End Sub

1. In my activities, I renamed "JobDone" to "JobIsDone" this processes the rest of the success /failure processes on the activity.
2. This is how I call this method... (modmashiane being the class name referenced from the starter service)

B4X:
dbAction.Initialize
    dbAction.Put("action=", "validateuser")
    dbAction.Put("email=", txtLoginEmail.text.trim)
    dbAction.Put("userpassword=", txtLoginPassword.Text.trim)
    Starter.modmashiane.ExecutePHP(Me,dbAction, "validateuser","users.php",txtLoginEmail.Text.trim)
3. In debug mode, the app hangs on waitfor and does not continue at all.
4. In release mode, the above error is raised.

Can someone please advise? Im trying to avoid having to copy this method from the class to each of my activities that references it.
 

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Thanks @DonManfred , hard luck though... same issue arose.

This is what I have tried so far and my app seems to be working well so far, whether this is acceptable or not I'm not sure.

I am adding WaitFor functionality to an existing app that already has Sub JobDone defined (old method)

1. I had renamed all my original JobDone methods to JobIsDone. So I renamed these back to JobDone.
2. In the class module that uses WaitFor for httpjobs, I removed the CallSub(frm,"JobIsDone", job) call from ExecutePHP

If this is true (which is so far), so basically, all i needed to do was just add the WaitFor clause and move these to a class module, initialize the class module once, and call my subs to execute like before without any major changes to my code.
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
This is the code in my class module, I initialize this in my Starter class and call ExecutePHP and other methods in my activities. Sub JobDone has not been removed from my old code, only added Wait For clause and moved all my HTTPJOB calls to the class without having to re-write the code.

B4X:
Sub Class_Globals
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize

End Sub

Sub ExecutePHP(frm As Object, pQuery As Map, JobName As String, phpFile As String, phpTag As String)
    Dim job As HttpJob
    Dim scommand As String
    Dim json As String
    job.Initialize(JobName, frm)
    job.Tag = phpTag
    json = modMashiane.Map2QueryString(pQuery)
    If modMashiane.Len(json) = 0 Then
        scommand = $"${Starter.phpPath}${phpFile}"$
    Else
        scommand = $"${Starter.phppath}${phpFile}?${json}"$
    End If
    job.Download(scommand)
    Wait For(job) JobDone(job As HttpJob)
End Sub


Sub GetNearByPlaces(frm As Object, fromLat As String, fromLng As String, radius As String, placeTypes As String, JName As String, JTag As String)
    Dim Job As HttpJob
    Job.Initialize(JName, frm)
    Job.Tag = JTag
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("https://maps.googleapis.com/maps/api/place/nearbysearch/json?")
    sb.append("location=").Append(fromLat).Append(",").Append(fromLng)
    sb.append("&radius=").Append(radius)
    sb.append("&types=").Append(placeTypes)
    sb.append("&sensor=false")
    sb.append("&key=" & modMashiane.GooglePlacesApiKey)
    Job.Download(sb.tostring)
    Wait For(Job) JobDone(Job As HttpJob)
End Sub

Sub DownloadFile(frm As Object, iLink As String, JobName As String, phpTag As String)
    Dim job As HttpJob
    job.Initialize(JobName, frm)
    job.Tag = phpTag
    job.Download(iLink)
    Wait For(job) JobDone(job As HttpJob)
End Sub

Sub UploadFilePhp(frm As Object, pQuery As Map, dir As String, fil As String, JobName As String, phpFile As String, phpTag As String)
    Dim job As HttpJob
    Dim fd As MultipartFileData
    ' initialize the job
    job.Initialize(JobName, frm)
    job.Tag = phpTag
    ' initialize the mulipart
    fd.Initialize
    fd.KeyName = "processfile"
    fd.Dir = dir
    fd.FileName = fil
    ' determine the contenttype
    If fil.EndsWith(".png") = True Then
        fd.ContentType = "image/png"
    else If fil.EndsWith(".jpg") = True Then
        fd.ContentType = "image/jpeg"
    else If fil.EndsWith(".jpeg") = True Then
        fd.ContentType = "image/jpeg"
    else If fil.EndsWith(".json") = True Then
        fd.ContentType = "application/json"
    else if fil.EndsWith(".pdf") = True Then
        fd.ContentType = "application/pdf"
    End If
    ' execute the script to upload the file
    job.PostMultipart(Starter.phpPath & phpFile, pQuery, Array(fd))
    Wait For(job) JobDone(job As HttpJob)
End Sub
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
FileUpload.php - save to php file and save on server...

B4X:
<?php
if (isset($_REQUEST['action'])){$action=trim($_REQUEST['action']);} else {$action="";}
if (isset($_REQUEST['filepath'])){$filepath=trim($_REQUEST['filepath']);} else {$filepath="";}

switch ($action)
{
    case "upload":
        $filepath = $filepath . basename( $_FILES['processfile']['name']);
        if(move_uploaded_file($_FILES['processfile']['tmp_name'], $filepath)) {
                echo "success";
            } else{
                echo "fail";
            }
}
?>

To call from activity... where filepath is the folder to save to on the server

B4X:
dbAction.Initialize
                dbAction.Put("action", "upload")
                dbAction.Put("filepath", "")
                Starter.httpjobs.UploadFilePhp(Me,dbAction,File.Combine(Starter.masterpath,"tgif"), uFile, _
                "upload1", "uploadfile.php", "upload1")

Sub JobDone.... job.GetString will return "success" or "fail" and you can trap these and do something else...
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
B4X:
job.Initialize(JobName, frm)
I think this needs to be
B4X:
job.Initialize("",Me)
See @Erel's post on this subject. As per that post, the name is not needed anymore. Instead of "Me" you are using "frm" and therefore (i'm guessing here) the jobdone processing is done by "frm" and not the class that is implementing the wait for. Therefore the
B4X:
CallSub2(frm,"JobIsDone",job)
never executes. And since you used "frm" instead of "Me", Java is looking for a jobdone method in the "frm" module, can't find it and throws your error (when you had that method renamed to jobisdone).
 
Upvote 0
Top