com.kixeye.relax.AsyncRestClient.java Source code

Java tutorial

Introduction

Here is the source code for com.kixeye.relax.AsyncRestClient.java

Source

package com.kixeye.relax;

/*
 * #%L
 * Relax
 * %%
 * Copyright (C) 2014 KIXEYE, Inc
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CancellationException;

import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;

import com.kixeye.relax.util.UrlUtils;

/**
 * A REST Async HTTP Client.
 * 
 * @author ebahtijaragic
 */
public class AsyncRestClient implements RestClient {
    private boolean isHttpClientReused = false;

    private CloseableHttpAsyncClient httpClient;

    private RestClientSerDe serDe;

    private String uriPrefix = "";

    /**
     * Creates an {@link AsyncRestClient}
     */
    protected AsyncRestClient() {

    }

    /**
     * Sets the uri prefix.
     * 
     * @param uriPrefix
     */
    protected void setUriPrefix(String uriPrefix) {
        if (uriPrefix == null) {
            uriPrefix = "";
        }

        this.uriPrefix = uriPrefix;
    }

    /**
     * Sets the serDe.
     * 
     * @param serDe
     */
    protected void setSerDe(RestClientSerDe serDe) {
        this.serDe = serDe;
    }

    /**
     * Sets the http client.
     * 
     * @param httpClient
     * @param isHttpClientReused
     */
    protected void setHttpClient(CloseableHttpAsyncClient httpClient, boolean isHttpClientReused) {
        this.httpClient = httpClient;
        this.isHttpClientReused = isHttpClientReused;
    }

    /**
     * Clsoes the client.
     * 
     * @return
     * @throws IOException 
     */
    public void close() throws IOException {
        if (!isHttpClientReused) {
            httpClient.close();
        }
    }

    /**
     * @see com.kixeye.relax.RestClient#get(java.lang.String, java.lang.String, java.lang.Class, java.lang.Object[])
     */
    @Override
    public <O> HttpPromise<HttpResponse<O>> get(final String path, String acceptHeader, final Class<O> responseType,
            Object... pathVariables) throws IOException {
        return get(path, acceptHeader, responseType, null, pathVariables);
    }

    /**
     * @see com.kixeye.relax.RestClient#get(java.lang.String, java.lang.Class, java.lang.Object)
     */
    @Override
    public <O> HttpPromise<HttpResponse<O>> get(final String path, String acceptHeader, final Class<O> responseType,
            Map<String, List<String>> additonalHeaders, Object... pathVariables) throws IOException {
        HttpPromise<HttpResponse<O>> promise = new HttpPromise<>();

        HttpGet request = new HttpGet(UrlUtils.expand(uriPrefix + path, pathVariables));

        if (acceptHeader != null) {
            request.setHeader("Accept", acceptHeader);
        }

        if (additonalHeaders != null && !additonalHeaders.isEmpty()) {
            for (Entry<String, List<String>> header : additonalHeaders.entrySet()) {
                for (String value : header.getValue()) {
                    request.addHeader(header.getKey(), value);
                }
            }
        }

        httpClient.execute(request, new AsyncRestClientResponseCallback<>(responseType, promise));

        return promise;
    }

    /**
     * @see com.kixeye.relax.RestClient#post(java.lang.String, java.lang.String, java.lang.String, java.lang.Object, java.lang.Class, java.lang.Object[])
     */
    @Override
    public <I, O> HttpPromise<HttpResponse<O>> post(String path, String contentTypeHeader, String acceptHeader,
            I requestObject, final Class<O> responseType, Object... pathVariables) throws IOException {
        return post(path, contentTypeHeader, acceptHeader, requestObject, responseType, null, pathVariables);
    }

    /**
     * @see com.kixeye.relax.RestClient#post(java.lang.String, java.lang.String, java.lang.String, I, java.lang.Class, java.lang.Object)
     */
    @Override
    public <I, O> HttpPromise<HttpResponse<O>> post(String path, String contentTypeHeader, String acceptHeader,
            I requestObject, final Class<O> responseType, Map<String, List<String>> additonalHeaders,
            Object... pathVariables) throws IOException {
        HttpPromise<HttpResponse<O>> promise = new HttpPromise<>();

        HttpPost request = new HttpPost(UrlUtils.expand(uriPrefix + path, pathVariables));
        if (requestObject != null) {
            request.setEntity(new ByteArrayEntity(serDe.serialize(contentTypeHeader, requestObject)));
        }

        if (contentTypeHeader != null) {
            request.setHeader("Content-Type", contentTypeHeader);
        }

        if (acceptHeader != null) {
            request.setHeader("Accept", acceptHeader);
        }

        if (additonalHeaders != null && !additonalHeaders.isEmpty()) {
            for (Entry<String, List<String>> header : additonalHeaders.entrySet()) {
                for (String value : header.getValue()) {
                    request.addHeader(header.getKey(), value);
                }
            }
        }

        httpClient.execute(request, new AsyncRestClientResponseCallback<>(responseType, promise));

        return promise;
    }

    /**
     * @see com.kixeye.relax.RestClient#put(java.lang.String, java.lang.String, java.lang.String, java.lang.Object, java.lang.Object[])
     */
    @Override
    public <I> HttpPromise<HttpResponse<Void>> put(String path, String contentTypeHeader, String acceptHeader,
            I requestObject, Object... pathVariables) throws IOException {
        return put(path, contentTypeHeader, acceptHeader, requestObject, null, pathVariables);
    }

    /**
     * @see com.kixeye.relax.RestClient#put(java.lang.String, java.lang.String, java.lang.String, I, java.lang.Object)
     */
    @Override
    public <I> HttpPromise<HttpResponse<Void>> put(String path, String contentTypeHeader, String acceptHeader,
            I requestObject, Map<String, List<String>> additonalHeaders, Object... pathVariables)
            throws IOException {
        HttpPromise<HttpResponse<Void>> promise = new HttpPromise<>();

        HttpPost request = new HttpPost(UrlUtils.expand(uriPrefix + path, pathVariables));
        if (requestObject != null) {
            request.setEntity(new ByteArrayEntity(serDe.serialize(contentTypeHeader, requestObject)));
        }

        if (contentTypeHeader != null) {
            request.setHeader("Content-Type", contentTypeHeader);
        }

        if (acceptHeader != null) {
            request.setHeader("Accept", acceptHeader);
        }

        if (additonalHeaders != null && !additonalHeaders.isEmpty()) {
            for (Entry<String, List<String>> header : additonalHeaders.entrySet()) {
                for (String value : header.getValue()) {
                    request.addHeader(header.getKey(), value);
                }
            }
        }

        httpClient.execute(request, new AsyncRestClientResponseCallback<>(null, promise));

        return promise;
    }

    /**
     * @see com.kixeye.relax.RestClient#patch(java.lang.String, java.lang.String, java.lang.String, java.lang.Object, java.lang.Object[])
     */
    @Override
    public <I> HttpPromise<HttpResponse<Void>> patch(String path, String contentTypeHeader, String acceptHeader,
            I requestObject, Object... pathVariables) throws IOException {
        return patch(path, contentTypeHeader, acceptHeader, requestObject, null, pathVariables);
    }

    /**
     * @see com.kixeye.relax.RestClient#patch(java.lang.String, java.lang.String, java.lang.String, I, java.lang.Object)
     */
    @Override
    public <I> HttpPromise<HttpResponse<Void>> patch(String path, String contentTypeHeader, String acceptHeader,
            I requestObject, Map<String, List<String>> additonalHeaders, Object... pathVariables)
            throws IOException {
        HttpPromise<HttpResponse<Void>> promise = new HttpPromise<>();

        HttpPatch request = new HttpPatch(UrlUtils.expand(uriPrefix + path, pathVariables));
        if (requestObject != null) {
            request.setEntity(new ByteArrayEntity(serDe.serialize(contentTypeHeader, requestObject)));
        }

        if (contentTypeHeader != null) {
            request.setHeader("Content-Type", contentTypeHeader);
        }

        if (acceptHeader != null) {
            request.setHeader("Accept", acceptHeader);
        }

        if (additonalHeaders != null && !additonalHeaders.isEmpty()) {
            for (Entry<String, List<String>> header : additonalHeaders.entrySet()) {
                for (String value : header.getValue()) {
                    request.addHeader(header.getKey(), value);
                }
            }
        }

        httpClient.execute(request, new AsyncRestClientResponseCallback<>(null, promise));

        return promise;
    }

    /**
     * @see com.kixeye.relax.RestClient#delete(java.lang.String, java.lang.Object[])
     */
    @Override
    public <I> HttpPromise<HttpResponse<Void>> delete(String path, Object... pathVariables) throws IOException {
        return delete(path, null, pathVariables);
    }

    /**
     * @see com.kixeye.relax.RestClient#delete(java.lang.String, java.util.Map, java.lang.Object[])
     */
    @Override
    public <I> HttpPromise<HttpResponse<Void>> delete(String path, Map<String, List<String>> additonalHeaders,
            Object... pathVariables) throws IOException {
        HttpPromise<HttpResponse<Void>> promise = new HttpPromise<>();

        HttpDelete request = new HttpDelete(UrlUtils.expand(uriPrefix + path, pathVariables));

        if (additonalHeaders != null && !additonalHeaders.isEmpty()) {
            for (Entry<String, List<String>> header : additonalHeaders.entrySet()) {
                for (String value : header.getValue()) {
                    request.addHeader(header.getKey(), value);
                }
            }
        }

        httpClient.execute(request, new AsyncRestClientResponseCallback<>(null, promise));

        return promise;
    }

    /**
     * Returns true if we're active.
     * 
     * @return
     */
    public boolean isActive() {
        return httpClient.isRunning();
    }

    /**
     * A response callback that forwards the response to the promise.
     * 
     * @author ebahtijaragic
     */
    private class AsyncRestClientResponseCallback<R> implements FutureCallback<org.apache.http.HttpResponse> {
        private final Class<R> responseType;

        private HttpPromise<HttpResponse<R>> promise;

        /**
         * @param responseType
         * @param HttpPromise<HttpResponse<T>> promise
         */
        protected AsyncRestClientResponseCallback(Class<R> responseType, HttpPromise<HttpResponse<R>> promise) {
            this.responseType = responseType;
            this.promise = promise;
        }

        public void failed(Exception ex) {
            promise.setError(ex);
        }

        public void completed(org.apache.http.HttpResponse result) {
            try {
                promise.set(new HttpResponse<>(result, serDe, responseType));
            } catch (Exception e) {
                failed(e);
            }
        }

        public void cancelled() {
            promise.setError(new CancellationException());
        }
    }
}