Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

180
Views
Retrofit Not Receiving Responses After the First

I am using RetroFit on android in order to send images to a REST server (developed using Python and Flask). The app sends a first image to the server which stores it and that returns that image's ID to the client. The client then takes another photo and sends it to the server, this time with the previous image ID in the endpoint URL. The server should then compute the rotation from image A to image B and return the result. Once the client has sent the second image, it should repeatedly poll the endpoint for a result until the calculations are completed server side.

The first image sends correctly, and the server stores it. The client then correctly receives the response from the server. The problem occurs when the client sends the second image. The server receives the POST correctly, but the client never seems to get a response. This is also true of the third message, the GET request that polls for a result, it is received by the server but the client never sees a response.

The code for my REST server is here

class Image(Resource):
    def post(self):
        file = request.files['uploaded_file']
        centerX = request.form['center_x']
        centerY = request.form['center_y']
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], str(id(True)) + ".jpg"))
            result = {'id' : id(), 'error' : True, 'result' : 5.5}
            return jsonify(result)
        else:
            return {'id' : -1, 'error' : False}

class Find_Transform(Resource):
    def post(self, first_id):
        result = {'id' : 1, 'error' : True, 'result' : 1.2}
        return jsonify(result)

class Find_Transform_Result(Resource):
    def get(self, first_id, second_id):
        print("Hello")
        result = {'id' : 0, 'error' : True, 'result' : 1.1}
        return jsonify(result)


api.add_resource(Image,'/image')
api.add_resource(Find_Transform,'/image/<first_id>/find-transform')
api.add_resource(Find_Transform_Result, '/image/<first_id>/find-transform/<second_id>')

if __name__ == '__main__':
    app.run(host='0.0.0.0',port='5002')

As you can see some of the endpoints are still just stubs to test the REST api.

My java Respond.class is here

public class Respond {

    private int id;
    private Boolean error;
    private float result;

    public int getMessage() {
        return id;
    }


    public void setMessage(int id) {
        this.id = id;
    }

    public Boolean getError() {
        return error;
    }

    public void setError(Boolean error) {
        this.error = error;
    }

    public void setResult(float result) {
        System.out.println("Got Result");
        this.result = result;
    }

    public float getResult() {
        return result;
    }
}

My Retrofit interface is here

public interface FileApi {

    @Multipart
    @POST("/image")
    Call<Respond> uploadCropImage(@Part MultipartBody.Part file, @Part MultipartBody.Part x, @Part MultipartBody.Part y);

    @Multipart
    @POST("/image/{first_id}/find-transform")
    Call<Respond> uploadCompareImage(@Path("first_id") int id, @Part MultipartBody.Part file);

    @GET("/image/{first-id}/find-transform/{second-id}")
    Call<Respond> getCompareResult(@Path("first-id") int firstId, @Path("second-id") int secondId);
}

The reason for the two separate file upload functions is that the first image needs to be sent alongside a user selected centre point, while the second is just an image.

Finally the sections where I build my requests are here:

 private void uploadFirstImage(byte[] imageBytes) {

        FileApi service = RetroClient.getApiService();


        RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), imageBytes);

        MultipartBody.Part fileBody =
                MultipartBody.Part.createFormData("uploaded_file", "first_image.jpg", requestFile);


        RequestBody image_center_x = RequestBody.create(MediaType.parse("multipart/form-data"), Float.toString(points[0].x));
        MultipartBody.Part xBody = MultipartBody.Part.createFormData("center_x", null, image_center_x);

        RequestBody image_center_y = RequestBody.create(MediaType.parse("multipart/form-data"), Float.toString(points[0].y));
        MultipartBody.Part yBody = MultipartBody.Part.createFormData("center_y", null, image_center_y);


        Call<Respond> resultCall = service.uploadCropImage(fileBody, xBody, yBody);

        resultCall.enqueue(new Callback<Respond>() {
            @Override
            public void onResponse(Call<Respond> call, Response<Respond> response) {

                // Response Success or Fail
                if (response.isSuccessful()) {
                    if (response.body().getError()==true){
                        System.out.println(Double.toString(response.body().getResult()));
                        session_id = response.body().getMessage();
                    }


                } else {
                    Toast.makeText(getApplicationContext(),"Failed to communicate with server",Toast.LENGTH_LONG).show();
                }


            }

            @Override
            public void onFailure(Call<Respond> call, Throwable t) {
            }
        });
    }

and here:

private void uploadSecondImage(byte[] imageBytes) {

        FileApi service = RetroClient.getApiService();


        RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), imageBytes);

        MultipartBody.Part fileBody =
                MultipartBody.Part.createFormData("uploaded_file", "first_image.jpg", requestFile);


        Call<Respond> resultCall = service.uploadCompareImage(session_id,fileBody);

        resultCall.enqueue(new Callback<Respond>() {
            @Override
            public void onResponse(Call<Respond> call, Response<Respond> response) {

                // Response Success or Fail
                if (response.isSuccessful()) {
                    if (response.body().getError()==true){
                        System.out.println("Got Second Response");
                        resultID = response.body().getMessage();
                    }


                } else {
                    Toast.makeText(getApplicationContext(),"Failed to communicate with server",Toast.LENGTH_LONG).show();
                }


            }

            @Override
            public void onFailure(Call<Respond> call, Throwable t) {
                System.out.println("Failure");
            }
        });
    }

and finally, for the GET request

    final boolean[] resultReady = {false};
    while (!resultReady[0]) {

        FileApi service = RetroClient.getApiService();
        Call<Respond> resultCall = service.getCompareResult(session_id, resultID);
        resultCall.enqueue(new Callback<Respond>() {
            @Override
            public void onResponse(Call<Respond> call, Response<Respond> response) {

                // Response Success or Fail
                if (response.isSuccessful()) {
                    if (response.body().getError()){
                        System.out.println("Got Response");
                        resultReady[0] = true;
                        theta[0] = response.body().getResult();
                        Toast.makeText(getApplicationContext(),"Measurement Recieved",Toast.LENGTH_LONG).show();
                    }
                    else {
                        Toast.makeText(getApplicationContext(),"Error Recieved",Toast.LENGTH_LONG).show();
                    }


                } else {
                    Toast.makeText(getApplicationContext(),"Failed to communicate with server",Toast.LENGTH_LONG).show();
                }


            }

            @Override
            public void onFailure(Call<Respond> call, Throwable t) {
            }
        });



    }

I've tried putting breakpoints in the OnResponse functions, and have put debug statements in both OnResponse and OnFailure and it seems that that code is never run. What could be going wrong here?

EDIT: Okay so I've got some logging data. I've tested the server from a python console

In [1]: import requests

In [2]: requests.get("http://localhost:5002/image/1/find-transform/2")
Out[2]: <Response [200]>

In [3]: _.text
Out[3]: '{"error": true, "id": 0, "result": 1.1}'

In [4]: requests.post("http://localhost:5002/image/find-transform")
Out[4]: <Response [404]>

In [5]: requests.post("http://localhost:5002/image/1/find-transform")
Out[5]: <Response [200]>

In [6]: _.text
Out[6]: '{"error": true, "id": 1, "result": 1.2}'

I also put the http logging in the client side as suggested by a comment, which gave this logging output.

D/OkHttp: --> POST http://192.168.0.19:5002/image
    Content-Type: multipart/form-data; boundary=bc4ae771-2762-4124-8f07-d00dc925d886
D/OkHttp: Content-Length: 2044497
D/OkHttp: --bc4ae771-2762-4124-8f07-d00dc925d886
    Content-Disposition: form-data; name="uploaded_file"; filename="first_image.jpg"
    Content-Type: multipart/form-data
    Content-Length: 2043935
    (Truncated raw image data)
V/RenderScript: 0x7f77b4c000 Launching thread(s), CPUs 8
D/OkHttp: <-- 200 OK http://192.168.0.19:5002/image (410ms)
    Content-Type: application/json
    Content-Length: 39
    Server: Werkzeug/0.14.1 Python/3.6.8
    Date: Wed, 24 Jul 2019 17:00:47 GMT
D/OkHttp: {"error": true, "id": 9, "result": 5.5}
    <-- END HTTP (39-byte body)
I/System.out: 5.5
W/ImageReader_JNI: Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers
I/System.out: Resultcall
D/OkHttp: --> POST http://192.168.0.19:5002/image/9/find-transform
    Content-Type: multipart/form-data; boundary=63de36cb-0961-4802-a97f-57b98ebcd8cb
D/OkHttp: Content-Length: 1655614
D/OkHttp: --63de36cb-0961-4802-a97f-57b98ebcd8cb
    Content-Disposition: form-data; name="uploaded_file"; filename="first_image.jpg"
    Content-Type: multipart/form-data
    Content-Length: 1655386
    (Truncated raw image data)
D/OkHttp: <-- HTTP FAILED: java.net.SocketException: sendto failed: EPIPE (Broken pipe)
D/OkHttp: --> GET http://192.168.0.19:5002/image/9/find-transform/-1
    --> END GET
D/OkHttp: <-- 200 OK http://192.168.0.19:5002/image/9/find-transform/-1 (90ms)

It seems that the server is both correctly receiving the request, and sending the correct response. So something must be failing to be processed correctly client side, but I can't think what.

over 4 years ago · Santiago Trujillo
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!