13

I am writing some Java code that uses Apache HttpClient version 4.2.2 to hit a RESTful 3rd party API. This API has methods that utilize HTTP GET, POST, PUT and DELETE. It's important to note that I'm using a 4.x.x version and not 3.x.x, because the API changed a lot from 3 to 4. All relevant examples I've found have been for a 3.x.x version.

All API calls require you provide the api_key as a parameter (regardles of which method you are using). This means that regardles of whether I'm making a GET, POST or otherwise, I need to provide this api_key in order for the call to authenticate server-side.

// Have to figure out a way to get this into my HttpClient call,
// regardless of whether I'm using: HttpGet, HttpPost, HttpPut
// or HttpDelete...
String api_key = "blah-whatever-my-unique-api-key";

So I'm trying to figure out how to provide HttpClient with the api_key regardless of my request method (which in turn depends on which RESTful API method I'm trying to hit). It looks like HttpGet doesn't even support the notion of parameters, and HttpPost uses something called HttpParams; but again these HttpParams only seem to exist in 3.x.x version of HttpClient.

So I ask: What is the proper, v4.2.2 way to attach/add my api_key String to all four:

  • HttpGet
  • HttpPost
  • HttpPut
  • HttpDelete

Thanks in advance.

3 Answers3

32

You can use URIBuilder class to build the request URI for all the HTTP methods. URI builder provides setParameter method to set the parameter.

URIBuilder builder = new URIBuilder();
builder.setScheme("http").setHost("www.google.com").setPath("/search")
    .setParameter("q", "httpclient")
    .setParameter("btnG", "Google Search")
    .setParameter("aq", "f")
    .setParameter("oq", "");
URI uri = builder.build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());

The output should be

http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq= 
randers
  • 5,031
  • 5
  • 37
  • 64
  • 4
    Thanks @rboorgapally (+1) - however I believe this only works for `HttpGet` (setting the parameters on the query string), and would have no effect for `HttpPost`, `HttpPut` or `HttpDelete`. Although each of these have a constructor that accepts a `URI` as an argument, I do not believe `URIBuilder` implicitly knows to convert query string parameters to, say, `HttpPost` POST variables, etc. So althought I would be passing the non-`HttpGet` methods a URI with the full query string, I do not believe they will know how to convert that query string into a data format they know how to work with. –  Dec 27 '12 at 13:10
  • I will just like to add that `setParameter` overrides the existing value. So if one wants to set a `List` variable in URI like `/search?q=1&q=2&y=3`, so here `q` is a list and it's final value will be 2 not [1,2]. To avoid this one may use `addParameter` method of the URIBuilder. Docs: http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html#addParameter%28java.lang.String,%20java.lang.String%29 – Siddharth Trikha Mar 17 '16 at 05:50
  • So is this answer applicable for non-get requests or not? – Kartik Chugh Jan 04 '21 at 20:53
6

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 and imports are from org.apache.http client libraries)

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();
}
Arthur
  • 568
  • 7
  • 17
1

An important thing here is to say explictly the apache's packages you must use, because there are different ways to implement a get request.

For example, you could use Apache Commons or HttpComponents. In this example, I will use HttpComponents (org.apache.http.*)

Request class:

package request;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import Task;

public void sendRequest(Task task) throws URISyntaxException {

    URIBuilder uriBuilder = new URIBuilder();
    uriBuilder.setScheme("http")
            .setHost("localhost")
            .setPort(8080)
            .setPath("/TesteHttpRequest/TesteDoLucas")
            .addParameter("className", task.getClassName())
            .addParameter("dateExecutionBegin", task.getDateExecutionBegin())
            .addParameter("dateExecutionEnd", task.getDateExecutionEnd())
            .addParameter("lastDateExecution", task.getDateLastExecution())
            .addParameter("numberExecutions", Integer.toString(task.getNumberExecutions()))
            .addParameter("idTask", Integer.toString(task.getIdTask()))
            .addParameter("numberExecutions" , Integer.toString(task.getNumberExecutions()));
    URI uri = uriBuilder.build();

    HttpGet getMethod = new HttpGet(uri);

    CloseableHttpClient httpclient = HttpClients.createDefault();

    CloseableHttpResponse response = null;

    try {
        response = httpclient.execute(getMethod);
    } catch (IOException e) {
        //handle this IOException properly in the future
    } catch (Exception e) {
        //handle this IOException properly in the future
    }
}

I'm using Tomcat v7.0 Server, then the class above receives a task and sends it to a specific servlet in the link http://localhost:8080/TesteHttpRequest/TesteDoLucas.

My Dynamic Web project is named TesteHttpRequest and my servlet attends by the url /TesteDoLucas

Task class:

package bean;

public class Task {

    private int idTask;
    private String taskDescription;
    private String dateExecutionBegin;
    private String dateExecutionEnd;
    private String dateLastExecution;
    private int numberExecutions;
    private String className;

    public int getIdTask() {
        return idTask;
    }

    public void setIdTask(int idTask) {
        this.idTask = idTask;
    }

    public String getTaskDescription() {
        return taskDescription;
    }

    public void setTaskDescription(String taskDescription) {
        this.taskDescription = taskDescription;
    }

    public String getDateExecutionBegin() {
        return dateExecutionBegin;
    }

    public void setDateExecutionBegin(String dateExecutionBegin) {
        this.dateExecutionBegin = dateExecutionBegin;
    }

    public String getDateExecutionEnd() {
        return dateExecutionEnd;
    }

    public void setDateExecutionEnd(String dateExecutionEnd) {
        this.dateExecutionEnd = dateExecutionEnd;
    }

    public String getDateLastExecution() {
        return dateLastExecution;
    }

    public void setDateLastExecution(String dateLastExecution) {
        this.dateLastExecution = dateLastExecution;
    }

    public int getNumberExecutions() {
        return numberExecutions;
    }

    public void setNumberExecutions(int numberExecutions) {
        this.numberExecutions = numberExecutions;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
}

Servlet class:

package servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/TesteDoLucas")
public class TesteHttpRequestServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String query = request.getQueryString();
        System.out.println(query);
     }

     protected void doPost(HttpServletRequest request, HttpServletResponse   response) throws ServletException, IOException {
        doGet(request, response);
        }
    }

The query parameters sent will be shown at console.

className=java.util.Objects%3B&dateExecutionBegin=2016%2F04%2F07+22%3A22%3A22&dateExecutionEnd=2016%2F04%2F07+06%3A06%3A06&lastDateExecution=2016%2F04%2F07+11%3A11%3A11&numberExecutions=10&idTask=1&numberExecutions=10

To fix the encoding, you can look at here: HttpServletRequest UTF-8 Encoding

Community
  • 1
  • 1
Lucas Amorim Silva
  • 567
  • 1
  • 7
  • 14
  • How different is your answer from the existing one? What value does it aggregate? You should have kept the focus on adding the parameters to the request. The `Task` class is irrelevant in the context of the question. – cassiomolin Apr 08 '16 at 20:54
  • I posted this question because I have tem same doubt days ago and every question I found answered in stackoverflow ignored the whole process of sending the request. I mean, the part of adding new parameters was right, but had to search in another topics how to complete the request (and I only found in the oficial documentation) and it took me time. It aggregates a lot in the way that you can copy and paste it and have a real funcional example of the request made with you get parameters, saving you time of searching details in the documentation. The task class is irrelevant, but helps to e.g. – Lucas Amorim Silva Apr 11 '16 at 09:34