How to use parameters with HttpPost

I am using a RESTfull webservice with this methode:

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String str1, String str2){
System.out.println("value 1 = " + str1);
System.out.println("value 2 = " + str2);
}

In my Android app I want to call this method. How do I give the correct values to the parameters using org.apache.http.client.methods.HttpPost;

I have noticed that I can use the annotation @HeaderParam and simply add headers to the HttpPost object. Is this the correct way? Doing it like:

httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("str1", "a value");
httpPost.setHeader("str2", "another value");

Using the setEntity methode on httpPost won't work. It only sets the parameter str1 with the json string. When using it like:

JSONObject json = new JSONObject();
json.put("str1", "a value");
json.put("str2", "another value");
HttpEntity e = new StringEntity(json.toString());
httpPost.setEntity(e);
//server output: value 1 = {"str1":"a value","str2":"another value"} 

To set parameters to your HttpPostRequest you can use BasicNameValuePair, something like this :

    HttpClient httpclient;
    HttpPost httpPost;
    ArrayList<NameValuePair> postParameters;
    httpclient = new DefaultHttpClient();
    httpPost = new HttpPost("your login link");


    postParameters = new ArrayList<NameValuePair>();
    postParameters.add(new BasicNameValuePair("param1", "param1_value"));
    postParameters.add(new BasicNameValuePair("param2", "param2_value"));

    httpPost.setEntity(new UrlEncodedFormEntity(postParameters, "UTF-8"));

    HttpResponse response = httpclient.execute(httpPost);

You can also use this approach in case you want to pass some http parameters and send a json request:

(note: I have added in some extra code just incase it helps any other future readers)

public void postJsonWithHttpParams() throws URISyntaxException, UnsupportedEncodingException, IOException {

    //add the http parameters you wish to pass
    List<NameValuePair> postParameters = new ArrayList<>();
    postParameters.add(new BasicNameValuePair("param1", "param1_value"));
    postParameters.add(new BasicNameValuePair("param2", "param2_value"));

    //Build the server URI together with the parameters you wish to pass
    URIBuilder uriBuilder = new URIBuilder("http://google.ug");
    uriBuilder.addParameters(postParameters);

    HttpPost postRequest = new HttpPost(uriBuilder.build());
    postRequest.setHeader("Content-Type", "application/json");

    //this is your JSON string you are sending as a request
    String yourJsonString = "{\"str1\":\"a value\",\"str2\":\"another value\"} ";

    //pass the json string request in the entity
    HttpEntity entity = new ByteArrayEntity(yourJsonString.getBytes("UTF-8"));
    postRequest.setEntity(entity);

    //create a socketfactory in order to use an http connection manager
    PlainConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
    Registry<ConnectionSocketFactory> connSocketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", plainSocketFactory)
            .build();

    PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(connSocketFactoryRegistry);

    connManager.setMaxTotal(20);
    connManager.setDefaultMaxPerRoute(20);

    RequestConfig defaultRequestConfig = RequestConfig.custom()
            .setSocketTimeout(HttpClientPool.connTimeout)
            .setConnectTimeout(HttpClientPool.connTimeout)
            .setConnectionRequestTimeout(HttpClientPool.readTimeout)
            .build();

    // Build the http client.
    CloseableHttpClient httpclient = HttpClients.custom()
            .setConnectionManager(connManager)
            .setDefaultRequestConfig(defaultRequestConfig)
            .build();

    CloseableHttpResponse response = httpclient.execute(postRequest);

    //Read the response
    String responseString = "";

    int statusCode = response.getStatusLine().getStatusCode();
    String message = response.getStatusLine().getReasonPhrase();

    HttpEntity responseHttpEntity = response.getEntity();

    InputStream content = responseHttpEntity.getContent();

    BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
    String line;

    while ((line = buffer.readLine()) != null) {
        responseString += line;
    }

    //release all resources held by the responseHttpEntity
    EntityUtils.consume(responseHttpEntity);

    //close the stream
    response.close();

    // Close the connection manager.
    connManager.close();
}

Generally speaking an HTTP POST assumes the content of the body contains a series of key/value pairs that are created (most usually) by a form on the HTML side. You don't set the values using setHeader, as that won't place them in the content body.

So with your second test, the problem that you have here is that your client is not creating multiple key/value pairs, it only created one and that got mapped by default to the first argument in your method.

There are a couple of options you can use. First, you could change your method to accept only one input parameter, and then pass in a JSON string as you do in your second test. Once inside the method, you then parse the JSON string into an object that would allow access to the fields.

Another option is to define a class that represents the fields of the input types and make that the only input parameter. For example

class MyInput
{
    String str1;
    String str2;

    public MyInput() { }
      //  getters, setters
 }

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(MyInput in){
System.out.println("value 1 = " + in.getStr1());
System.out.println("value 2 = " + in.getStr2());
}

Depending on the REST framework you are using it should handle the de-serialization of the JSON for you.

The last option is to construct a POST body that looks like:

str1=value1&str2=value2

then add some additional annotations to your server method:

public void create(@QueryParam("str1") String str1, 
                  @QueryParam("str2") String str2)

@QueryParam doesn't care if the field is in a form post or in the URL (like a GET query).

If you want to continue using individual arguments on the input then the key is generate the client request to provide named query parameters, either in the URL (for a GET) or in the body of the POST.