Skip to content

SAP/cloud-rest-api-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

REST API Client Library

REUSE status

Java HTTP client library for HTTP handling, when building clients for RESTful APIs.

Prerequisities and Dependencies

Installation

Build the library using the following maven command.

mvn clean install

Executing Unit Tests

The unit tests of the library can be executed with the following Maven command

mvn clean install -Punit-tests

Usage

Add the following dependency to your maven pom.xml file.

<dependency>
    <groupId>com.sap.cloud.client</groupId>
    <artifactId>rest-api-client</artifactId>
    <version>${latest.version}</version>
</dependency>

Creating a RestApiClient

To create a Rest API Client, you need to extend the RestApiClient class and construct it by passing a RestApiClientConfig to it.

public class DefaultRestApiClient extends RestApiClient {

    private static final String API_PATH = "/api";

    public DefaultRestApiClient(RestApiClientConfig restApiClientConfig) {
        super(restApiClientConfig);
    }

    @Override
    protected String getApiPath() {
        return API_PATH;
    }
}

Using a Custom HttpClientProvider

An HttpClientProvider is an interface with one method HttpClient createHttpClient(). The HttpClient returned by this method is used for executing requests in RestApiClient. By default, an HttpClientProviderFactory creates default HttpClientProvider implementations depending on the AuthenticationType found in restApiClientConfig.

RestApiClient has a constructor where a custom implementation can be provided, to override the default http clients used.

    public DefaultRestApiClient(RestApiClientConfig restApiClientConfig, HttpClientProvider httpClientProvider) {
        super(restApiClientConfig, httpClientProvider);
    }

Creating a RestApiClientConfig

RestApiClientConfig has a host and an object of type Authentication. You can construct it using RestApiClientConfigBuilder.getBuilder() to get an instance of the RestApiClientConfigBuilder. Supported authentication types are ClientCertAuthentication, BasicAuthentication, OAuthAuthentication and NoAuthentication. It also supports configuring a proxy that will be used in the RestApiClient.

No Authentication

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host(<host>)
    .authentication(new NoAuthentication())
    .build();

You can also use the utility method for No Authentication.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host(<host>)
    .noAuthentication()
    .build();

You could also skip the noAuthentication() method. RestApiClientConfigBuilder constructs configurations with no authentication by default.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
                .host(<host>)
                .build();

Basic Authentication

To use basic authentication, you have to provide a username and password.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host(<host>)
    .authentication(new BasicAuthentication(<username>, <password>))
    .build();

You can also use the utility method for Basic Authentication.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host(<host>)
    .basicAuthentication(<username>, <password>)
    .build();

Client Certificate Authentication

To use the client certificate authentication, you have to provide a KeystoreConfig. You can construct it using KeystoreConfigBuilder.getBuilder() to get an instance of the KeystoreConfigBuilder.

KeyStore keystore;  // initialize with your keystore

KeystoreConfig keystoreConfig = KeystoreConfigBuilder.getBuilder()
    .keystore(keystore)
    .keystorePassword("<password>")
    .keyAlias("<key alias>")
    .build();

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host(<host>)
    .authentication(new ClientCertAuthentication(keystoreConfig))
    .build();

You can also use the utility method for Client Certificate Authentication.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host(<host>)
    .clientCertAuthentication(keystoreConfig)
    .build();

Note: By default, the SSLHttpClientProvider returned from HttpClientProviderFactory creates an http client with connection timeout of 30 seconds (30000 milliseconds). To configure the timeout, create an SSLHttpClientProvider with a custom timeout (in milliseconds) and pass it to the RestApiClient constructor.

KeystoreConfig keystoreConfig; // initialize as above
RestApiClientConfig config; // initialize as above

ClientCertAuthentication authentication = new ClientCertAuthentication(keystoreConfig);
SSLHttpClientProvider clientProvider = new SSLHttpClientProvider(authentication, <timeoutInMillis>);

RestApiClient restApiClient = new DefaultRestApiClient(config, clientProvider);

OAuth Authentication

To use OAuth authentication you have to provide an OAuthServerConfig. It is used for requesting access tokens. You can construct it using OAuthServerConfigBuilder.getBuilder() to get an instance of the OAuthServerConfigBuilder

OAuthServerConfig oAuthServerConfig = OAuthServerConfigBuilder.getBuilder()
    .oAuthServerHost(<OAuth server host>) // e.g https://authentication.sap.hana.ondemand.com
    .clientID(<client ID>)
    .clientSecret("<client secret>".toCharArray())
    .build();
                
RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host("<host>")
    .authentication(new OAuthAuthentication(oAuthServerConfig))
    .build();

You can also use the utility method for OAuth Authentication.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host("<host>")
    .oauthAuthentication(oAuthServerConfig)
    .build();

Note: By default, the OAuthServerConfigBuilder creates a configuration with an API path /oauth/token. If the path of the server is different, you can set it explicitly with the oAuthServerApiPath("<OAuth server API path>") method. For example, the access token endpoint for Neo currently has an API path of /oauth2/api/v1/token.

Note: By default, the OAuthServerConfigBuilder creates a configuration with an OAuth Header key Authorization. If the header key you want to set the Bearer header on is different, you can set it explicitly with the oAuthHeaderKey("<OAuth Header key>") method.

Configuring a Proxy

To set up a proxy for the RestApiClient, pass a Proxy object to the RestApiClientConfig. The Proxy object consists of hostname, port and scheme.

Proxy proxy = new Proxy("<hostname>", 8888, "https"); //Represents a proxy with host https://<hostname>:8888

If the scheme is not provided, it is http by default.

Proxy proxy = new Proxy("<hostname>", 8888); //Represents a proxy with host http://<hostname>:8888

Then attach the created Proxy to the RestApiClientConfigBuilder. When building the configuration, the builder will create an HttpRoutePlanner, using the Proxy object. This route planner will be set to the HttpClient that is internally used in the RestApiClient.

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host("<host>")
    .proxy(proxy)
    .build();

The RestApiClientConfigBuilder also supports directly passing an HttpRoutePlanner to the proxy method.

HttpHost httpHost = new HttpHost("<hostname>", 8888, "http");
HttpRoutePlanner httpRoutePlanner = new DefaultProxyRoutePlanner(httpHost);

RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder()
    .host("<host>")
    .proxy(httpRoutePlanner)
    .build();

Using the RestApiClient

To execute a request with RestApiClient you have to build a Request object and call the Response<String> execute(Request<RequestType> request) method.

Request is a generic class that consists of an HttpUriRequest and an entity representing the request body. It can be constructed using the provided RequestBuilder. Passing a URI is obligatory. It support deserialization of objects to JSON using the Jackson library. It also supports multipart requests.

Initialize the builder with one of its static methods.

Request<TestEntity> request = RequestBuilder
                .getRequest()
                .uri(<uri>)
                .addParameter(<queryParamName>, <queryParamValue>)
                .addHeader(<headerName>, <headerValue>)
                .build();
                
client.execute(testEntityRequest);

To use the deserialization , pass a Class object of the type you will deserialize and pass an object of this type to the entity(T entity) method.

TestEntity testEntity = new TestEntity();
Request<TestEntity> testEntityRequest = RequestBuilder
                .postRequest(TestEntity.class)
                .uri(<uri>)
                .entity(testEntity)
                .build();
                
client.execute(testEntityRequest);

To build a multipart request, add entity parts with the multipartEntity(String name, T entity) method and build the Request with buildMultipart() instead of build(). The created Request object is of type MultipartEntity - a generic model holding all entity parts and their names.

TestEntity testEntityPartOne = new TestEntity();
TestEntity testEntityPartTwo = new TestEntity();
Request<MultipartEntity<TestEntity>> testEntityMultipartRequest = RequestBuilder
                .postRequest(TestEntity.class)
                .multipartEntity(<part-one-name>, testEntityPartOne)
                .multipartEntity(<part-two-name>, testEntityPartTwo)
                .uri(<uri>)
                .buildMultipart();
                        
client.execute(testEntityMultipartRequest);                        

If the RequestBuilder is not suitable to your use case (e.g. lacks functionality), you can directly build an HttpUriRequest and construct the Request object with it using the constructor. Use org.apache.http.client.methods.RequestBuilder documentation for reference.

Note that this approach is not recommended as it leaves the opportunity that the developer does not pass the request entity (if any) to the Request object and miss on the logging that it provides. The following example won't log the request object in case of any errors.

HttpUriRequest httpUriRequest = RequestBuilder.get(<uri>).build();
Request<String> request = new Request<>(httpUriRequest);
client.execute(request);

RestApiClient works with a StatusCodeHandler and can accept a custom implementation. The library provides a default implementation (DefaultStatusCodeHandler), which is used if a handler is not explicitly provided. It is handling 401 response code by throwing an UnauthorizedException and all other status codes larger than 300 by throwing the generic ResponseException. The exceptions provide an HttpExchangeContext object that holds both the Request and Response objects of the request execution.

client.execute(request, customStatusCodeHandler);

RestApiClient works with a org.apache.http.client.ResponseHandler to parse the response body and can accept a custom implementation. If no custom implementation is provided, it uses the DefaultResponseHandler, which returns the response body as a string. The library provides two utility response handlers that use the Jackson library to deserialize a response into whatever type is provided to them as a generic:

  • JacksonJsonResponseHandler deserializes JSON responses.
  • PropertiesResponseHandler deserializes properties responses in the format of property=value.
client.execute(request, customResponseHandler);

You can also provide both a response and a status code handler.

client.execute(request, customResponseHandler, customStatusCodeHandler);

Note: The following exceptions are thrown by the interface methods:

  • ConnectionException in case of an IOException.
  • ResponseException if an error HTTP status code is received.
  • UnauthorizedException in case of a 401 Unauthorized response code, if using the default status code handler.
  • RestApiClientException is the common exception for all of the above.

Contribution

We welcome any exchange and collaboration with individuals and organizations interested in the use, support and extension of the library.

License

Copyright © 2017-2020 SAP SE or an SAP affiliate company. All rights reserved. This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the LICENSE file.

About

Java HTTP client library for HTTP handling, when building clients for RESTful APIs.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages