Error when trying to add an End Device from HTTP API

I have found on Stack Overflow someone complaining about Java’s JsonObjectRequest not working
(link)

I have tried to use instead an alternate method called StringRequest() and it works. Maybe that I was incorrectly using JsonObjectRequest, I don’t know.

Anyway, I put below the code that is working for me. If that can help someone else!

I suspect that my implementation of JsonObjectRequest was incorrectly sending the JSON file so the server didn’t find what it is expecting and displayed this message about device_id not matching regex. That’s the case also if you send an empty JSON file. That would be nice if the server was able to display a more explicit message when a mandatory field is not found.

    private void addEndDeviceToIdentityServer() {

        JSONObject dataObject = new JSONObject();

        // Prepare JSON data
        try {
            JSONObject idsObject = new JSONObject();
            idsObject.put("dev_eui", mDevEUI);
            idsObject.put("join_eui", mJoinEUI);
            idsObject.put("device_id", mDeviceId);

            JSONObject endDeviceObject = new JSONObject();
            endDeviceObject.put("ids", idsObject);
            endDeviceObject.put("network_server_address", TTN_SERVER);
            endDeviceObject.put("application_server_address", TTN_SERVER);
            endDeviceObject.put("join_server_address", TTN_SERVER);

            JSONArray paths = new JSONArray();
            paths.put("network_server_address");
            paths.put("application_server_address");
            paths.put("join_server_address");

            JSONObject fieldMaskObject = new JSONObject();
            fieldMaskObject.put("paths", paths);

            dataObject.put("end_device", endDeviceObject);
            dataObject.put("field_mask", fieldMaskObject);

        } catch (JSONException e) {
            e.printStackTrace();
            return;
        }

        Log.w(TAG,"addEndDeviceToIdentityServer: " + dataObject);

        mRequestQueue = Volley.newRequestQueue(this);
        mRequestQueue.getCache().clear();

        String url = TTN_URL + "/applications/" + mApplicationId + "/devices";

        StringRequest strRequest = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>()
                {
                    @Override
                    public void onResponse(String response)
                    {
                        Log.d(TAG, response);
                    }
                },
                new Response.ErrorListener()
                {
                    @Override
                    public void onErrorResponse(VolleyError error)
                    {
                        if (error == null || error.networkResponse == null) {
                            return;
                        }
                        Log.e(TAG, "onErrorResponse: " + error.getMessage());

                        String body;
                        //get status code here
                        final String statusCode = String.valueOf(error.networkResponse.statusCode);
                        //get response body and parse with appropriate encoding
                        try {
                            body = new String(error.networkResponse.data,"UTF-8");
                            Log.e(TAG, "body: " + body);
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                    }
                })
        {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                final Map<String, String> headers = new HashMap<>();
                headers.put("Centent-Type", "application/json");
                headers.put("Authorization", "Bearer " + mMyAppApiKey);
                return headers;
            }

            @Override
            public String getBodyContentType() {
                return "application/json; charset=utf-8";
            }

            @Override
            public byte[] getBody() throws AuthFailureError {
                return dataObject.toString().getBytes(StandardCharsets.UTF_8);
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                String responseString = "";
                if (response != null) {
                    responseString = String.valueOf(response.statusCode);
                    // can get more details such as response.headers
                }
                return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
            }
        };

        strRequest.setShouldCache(false);
        strRequest.setTag(TAG);
        
        mRequestQueue.add(strRequest);

    }
1 Like

Sounds like my life all over, use apparently good library, finally figure out it has ‘issues’, use something else. Sometimes rinse & repeat.

If it’s empty, absolutely - you can submit the issue on GitHub and do the fix and submit a PR :wink: