Using the Connection API

Use the Connection API to send a request to a remote resource using the connection infrastructure and obtain a response.

Overview

The Connection API is contained in the zero.core IVY dependency, and has two key classes:

  • zero.core.connection.Connection
  • zero.core.connection.Connection.Response

For an overview of the connection infrastructure and associated topics, see Calling a remote resource.

An application uses the Connection class to build and send a request to the named resource. The request is then given a reference to a Connection.Response instance, and it can then use the Connection.Response object to wait for and examine the status and contents of the response.

The Connection class provides the application with two alternative approaches when initiating a request:

  • A collection of static methods, each of which set up, initiate, and send a request in a single method call.
  • A more flexible API in which an application creates a Connection object, sets up the request, and sends it to the target resource in a series of method calls.

Using the static methods is equivalent to sending a simple request that uses the full Connection API. The way in which the application interacts with the Connection.Response object does not depend on the approach taken when sending the request.

See the API reference for zero.core for more information.

You can find information about the protocols supplied for use with the Connection API in the Protocol reference. To send e-mail messages, see Sending an e-mail using EmailConnection for more information.

Sending requests to resources

Sending requests using the static Connection API

The static methods of the Connection class provide a simple way to send REST-style requests to resources. The following list contains the four basic forms:

  • Connection.Response doGET(String resource, Map<String, List<Object>> headers)
  • Connection.Response doPUT(String resource, Map<String, List<Object>> headers, Object body)
  • Connection.Response doPOST(String resource, Map<String, List<Object>> headers, Object body)
  • Connection.Response doDELETE(String resource, Map<String, List<Object>> headers)

In addition to the basic forms, the Connection class has overloaded forms that differ in the way the request headers are supplied.

resource
The URL or destination name of the resource to be invoked.
headers
The headers to be sent with the request expressed as a Map of header names and List of associated values. If no request headers are required, the application either passes an empty Map or an null value, or else uses the overloaded methods that have no headers argument.
body
The body of the request. The supported body types depend on the protocol being used but typically include:
  • String
  • byte[]
  • InputStream
  • Reader

The following code extract shows a simple example in which doGET() is used send an HTTP request to retrieve a resource:

try {
    Connection.Response response = Connection.doGET("http://www.projectzero.org/repo");
    // work with response headers and body
} catch (Exception e) {
    // handle exceptions
}

The meaning of request headers and the object types supported for the request body depend upon the protocol that you use. See Protocol reference for more information.

See the API reference for zero.core for more information on the methods.

Sending requests using the full Connection API

The static methods of the Connection class offer a simple way to issue requests and obtain a Connection.Response object. These methods simplify the full Connection API, which might explicitly be used by applications in more advanced scenarios.

In the following example, the single doGET() call is replaced with separate statements to create a new Connection object and get the associated Connection.Response object.

    Connection conn = new Connection("http://www.projectzero.org/repo");
    Connection.Response response = conn.getResponse();

Applications using full Connection API follow the following pattern:

  1. Create a new Connection object, specifying a target resource and operation.
  2. Set up any request headers that are required.
  3. Set the request body, if required.
  4. Send the request and obtain a reference to a Connection.Response.

The Connection class provides two public constructors:

  • Connection(String resource)
  • Connection(String resource, Connection.Operation operation)

By default, the first form prepares a GET request, but the second allows the operation to be defined using the enumeration, Connection.Operation:

  • GET
  • HEAD
  • POST
  • PUT
  • DELETE

The newly created Connection object supplies a number of methods by which request headers can be set and are summarized in the following list. Each header consists of a name, of type String, and a list of associated values, of type List<Object>. The setRequestHeader() and removeRequestHeader() methods replace, or remove, all the values for the named header. However, the addRequestHeader() and addRequestHeaders() methods do not replace any existing header values. If the named headers are already set, these methods append the new values to the end of the list.

  • void setRequestHeader(String key, List<Object> values)
  • List<Object> removeRequestHeader(String key)
  • void addRequestHeader(String key, Object value)
  • void addRequestHeaders(Map<String, List<Object>> headers)

The application can only call these methods before the request body has been set. Any subsequent attempts to call one of these methods results in an IllegalStateException being thrown.

For POST and PUT operations, the request body is specified using one of two methods:

  • void setRequestBody(Object body)
  • OutputStream getRequestBodyOutputStream()

The application uses the setRequestBody() method to supply the message body in a similar way to static form of the Connection API. The supported body types depend on the protocol being used but typically include:

  • String
  • byte[]
  • InputStream
  • Reader

Alternatively, the getRequestBodyOutputStream() method allows an application to request an OutputStream in which it writes the request body. If this method is used to supply the request body, the application must flush() and close() the request body stream before the request is sent, or in other words, before calling getResponse().

The application can only call one of the methods to set the request body for an individual Connection object. Any subsequent attempts to call one of these methods results in an IllegalStateException being thrown.

After the request body is completed, the application uses the getResponse() to signal that the request be sent to the target resource and obtain a reference to the Connection.Response object.

  • Connection.Response getResponse()

The following example uses the full Connection API to prepare and send a simple e-mail message:

    Connection conn = new Connection("mailto:you@projectzero.org", Connection.Operation.POST);
    conn.addRequestHeader("Subject", "Hello!");
    conn.addRequestHeader("From", "me@projectzero.org");
    conn.setRequestBody("This is the text of the email.");
    Connection.Response resp = conn.getResponse();

The EmailConnection class provides additional support for sending an e-mail using the Connection API. The meaning of request headers, and the object types supported for the request body, depend upon the protocol that you use. See Protocol reference for more information.

See the API reference for zero.core for more information on the methods.

Working with Connection.Response

After using Connection to send a request to a resource, the application is given a reference to a Connection.Response object. For protocols that supply a response to a request, an application can use the methods supplied by Connection.Response to complete the following actions:

  • Examine any protocol-specific status code associated with the response.
  • Examine any response headers.
  • Obtain any response body.

The application is given the Connection.Response reference after the request is sent. Depending on the protocol in use, a response might not have been received from the resource at this time. If the response is still in-flight when the application eventually uses the methods of Connection.Response to examine it, the method call blocks until the requested information is available.

Working with response headers

The following methods of Connection.Response allow an application to examine the headers supplied with the response:

  • Set<String> getResponseHeaderKeys()
  • List<Object> getResponseHeader(String key)

Response header values are always represented as List objects, regardless of the protocol that has been used. The following code extract extends the doGET() example to display the first value of the response Content-Type header, if the header is present:

try {
    Connection.Response response = Connection.doGET("http://www.projectzero.org/repo");
    List<Object> contentType = resp.getResponseHeader("Content-Type");
    if (contentType != null) {
        System.out.println(contentType.get(0).toString());
    }
    // work with response body
} catch (Exception e) {
    // handle exceptions
}

Obtaining the response body

Connection.Response provides several methods by which the application obtains the response body. The basic forms are summarized in the following list:

  • String getResponseBodyAsString()
  • byte[] getResponseBodyAsBytes()
  • Reader getResponseBodyReader()
  • InputStream getResponseBodyInputStream()
  • Object getResponseBody()

The application can call only one of the preceding methods for an individual Connection.Response object. Any subsequent attempts to call one of these methods results in an IllegalStateException being thrown.

The getResponseBody() method gives access to the response body object returned by the protocol implementation or any configured connection handlers. It is intended for use in advanced applications where such specific access is required. For general scenarios, use the method that converts the body into the form most suitable for the application, which simplifies the logic and protects the application from implementation or configuration changes that might change the type of the body returned by getResponseBody().

The following extension of the doGET() example uses getResponseBodyAsString() to obtain the response body and writes it to System.out:

try {
    Connection.Response response = Connection.doGET("http://www.projectzero.org/repo");
    List<Object> contentType = response.getResponseHeader("Content-Type");
    if (contentType != null) {
        System.out.println(contentType.get(0).toString());
    }
    System.out.println(response.getResponseBodyAsString());
} catch (Exception e) {
    // handle exceptions
}

The meaning of request headers and the object types supported for the request body depend upon the protocol that you use. See Protocol reference for more information.

See the API reference for zero.core for more information on the methods.

Advanced topics

Targeting local HTTP resources

The Connection API provides a convenient method to invoke a local HTTP resource without needing to specify a full URL. This mechanism can be used when the application invokes the Connection API whilst responding to an HTTP or HTTPS request.

When specifying a resource in any call to the Connection API, the application might use the following prefixes in place of an absolute URL.

./
Relative to current resource.
../
Relative to parent resource.
~/
Relative to the application context root.

For example, consider an application that responds to a request to http://mydomain.com:8080/appRoot/level1/level2/level3. Requesting the resource ./rel1 results in the request being sent to http://mydomain.com:8080/appRoot/level1/level2/rel1.

Resource names that do not begin with the preceding prefixes are interpreted as absolute resource names. In particular, resources starting with / are not resolved relative to the current request. Calling Connection.getResource() returns the absolute URL for the Connection request, regardless of whether it is specified using an absolute name or relative prefix.

Sending an e-mail

The EmailConnection API provides a specialized interface to help send an e-mail with optional MIME attachments using the SMTP protocol. For more information, see Sending an e-mail using the EmailConnection API.

Version 1.1.0.0.21442