All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.vfdtech.implementations.ApiClient Maven / Gradle / Ivy

Go to download

A utilities service with generic tools implementation. Can be plugged into your java project

There is a newer version: 0.3.5
Show newest version
package org.vfdtech.implementations;

import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vfdtech.models.ResponseWrapper;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;


@SuppressWarnings("unused")
public class ApiClient {
    private Logger log = LoggerFactory.getLogger(ApiClient.class);
    private OkHttpClient client;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public ApiClient() {
        client = create();
    }

    public ApiClient(final Logger log) {
        this.log = log;
        client = create();
    }

    public ApiClient(final boolean trustAllCerts) {
        try {
            client = trustAllCerts ? createAndTrustAllCerts() : create();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            throw new RuntimeException(e);
        }
    }

    public static Headers makeHeaders(Map headerValues) {
        return Headers.of(headerValues);
    }

    public static Headers.Builder makeJsonContentHeaders() {
        Headers.Builder headers = new Headers.Builder();
        return headers.add("Content-Type", "application/json");
    }

    public static Headers.Builder basicAuthedHeader(
            String username, String password) {
        Headers.Builder headerBuilder = new Headers.Builder();
        String basicAuthed = Credentials.basic(username, password);
        return headerBuilder.add("Authorization", basicAuthed);
    }

    public static Headers.Builder bearerAuthedHeader(
            Supplier tokenSupplier) {
        Headers.Builder headerBuilder = new Headers.Builder();
        return headerBuilder.add("Authorization", tokenSupplier.get());
    }

    public OkHttpClient create() {
        ConnectionPool connectionPool =
                new ConnectionPool(10, 60, TimeUnit.MILLISECONDS);
        return new OkHttpClient.Builder().followRedirects(false)
                .protocols(Collections.singletonList(Protocol.HTTP_1_1))
                .retryOnConnectionFailure(true)
                .connectTimeout(Duration.ofMinutes(2))
                .readTimeout(Duration.ofMinutes(2))
                .connectionPool(connectionPool)
                .build();
    }

    public OkHttpClient createAndTrustAllCerts() throws NoSuchAlgorithmException, KeyManagementException {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        //empty method
                    }

                    @Override
                    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        //empty method
                    }

                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[]{};
                    }
                }
        };
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        OkHttpClient.Builder newBuilder = new OkHttpClient.Builder();
        newBuilder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]);
        newBuilder.hostnameVerifier((hostname, session) -> true);

        ConnectionPool connectionPool =
                new ConnectionPool(10, 60, TimeUnit.MILLISECONDS);
        return newBuilder.followRedirects(false)
                .protocols(Collections.singletonList(Protocol.HTTP_1_1))
                .retryOnConnectionFailure(true)
                .connectTimeout(Duration.ofMinutes(2))
                .readTimeout(Duration.ofMinutes(2))
                .connectionPool(connectionPool)
                .build();
    }

    /**
     * @param httpMethod : String (GET,POST,PUT ...)
     * @param url        : URL to call
     * @param args       : This should be in this order - arg[0] = requestBody: String,
     *                   arg[1] = requestHeaders: okhttp3.Headers
     * @return ResponseWrapper
     */
    public ResponseWrapper restExchange(String httpMethod, String url, Object... args) {
        // Ensure client is initialized
        client = client != null ? client : create();

        // Validate httpMethod
        if (!isValidHttpMethod(httpMethod)) {
            throw new IllegalArgumentException("Invalid HTTP method: " + httpMethod);
        }

        // Separate request object creation logic
        Request request = buildRequest(httpMethod, url, args);

        try (Response response = client.newCall(request).execute()) {
            return handleResponse(response);
        } catch (IOException e) {
            log.error("Error occurred during REST exchange:", e);
            return buildErrorResponse(e);
        }
    }

    // Helper methods for cleaner separation of concerns
    private boolean isValidHttpMethod(String httpMethod) {
        return Arrays.asList("POST", "PUT", "GET", "PATCH").contains(httpMethod);
    }

    private Request buildRequest(String httpMethod, String url, Object... args) {
        log.info("::: URL TO CALL :::{}", url);
        MediaType mediaType = getMediaTypeFromArgs(args);
        RequestBody body = createRequestBody(args);
        Headers headers = getHeadersFromArgs(args);

        Request.Builder builder = new Request.Builder()
                .url(url);
        if (headers != null) {
            builder.headers(headers);
        }

        switch (httpMethod.toUpperCase()) {
            case "POST":
                builder.post(body);
                break;
            case "PUT":
                builder.put(body);
                break;
            case "GET":
                builder.get();
                break;
            case "PATCH":
                builder.patch(body);
                break;
            default:
                throw new IllegalStateException("Unexpected HTTP method: " + httpMethod);
        }

        return builder.build();
    }

    private ResponseWrapper handleResponse(Response response) {
        try {
            log.info("::: STATUS CODE FROM SERVICE :::{}", response.code());
            ResponseBody responseBody = response.body();
            String responseString = responseBody.string();
            log.info("::: RESPONSE FROM SERVICE:::{}", responseString);

            return ResponseWrapper.builder()
                    .statusCode(response.code())
                    .responseEntity(Pair.of(response.message(), responseString))
                    .build();
        } catch (Exception e) {
            log.info("========= ERROR OCCURRED ======== \n ERROR", e);
            return ResponseWrapper.builder().statusCode(500)
                    .responseEntity(Pair.of(e.getMessage(), null)).build();
        }
    }

    private ResponseWrapper buildErrorResponse(Exception e) {
        log.error("Error occurred during REST exchange:", e);
        return ResponseWrapper.builder().statusCode(500)
                .responseEntity(Pair.of(e.getMessage(), null)).build();
    }

    // Utility methods for optional parameters and media type handling
    private MediaType getMediaTypeFromArgs(Object... args) {
        return args.length > 2 ? (MediaType) args[2] : MediaType.parse("application/json; charset=utf-8");
    }

    private RequestBody createRequestBody(Object... args) {
        String requestBody = args.length > 0 ? String.valueOf(args[0]) : "";
        if (!requestBody.equalsIgnoreCase("")) {
            log.info("::: REQUEST TO SEND :::{}", requestBody);
        }
        return RequestBody.create(requestBody.getBytes(), getMediaTypeFromArgs(args));
    }

    private Headers getHeadersFromArgs(Object... args) {
        return args.length > 1 ? (Headers) args[1] : null;
    }

    public ResponseWrapper restExchange(String url, RequestBody requestBody, Headers headers) {
        log.info("::: URL TO CALL :::{}", url);
        if (client == null) {
            client = create();
        }
        Request.Builder request = new Request.Builder()
                .url(url).post(requestBody);

        if (Objects.nonNull(headers)) {
            request.headers(headers);
        }

        try (Response response = client.newCall(Objects.requireNonNull(request.build())).execute()) {
            ResponseBody responseBody = response.body();
            String responseString;
            responseString = responseBody.string();
            log.info("::: RESPONSE FROM SERVICE:::{}", responseString);

            return ResponseWrapper.builder()
                    .statusCode(response.code())
                    .responseEntity(Pair.of(response.message(), responseString))
                    .build();
        } catch (Exception e) {
            log.error("Exception", e);
            return ResponseWrapper.builder().statusCode(500)
                    .responseEntity(Pair.of(e.getMessage(), null)).build();
        }
    }

    public enum HttpMethod {
        POST, GET, PUT, DELETE, PATCH;
    }

    public  T call(String url, String method, HashMap body, Class returnClass, @Nullable Headers headers) throws IOException {
        OkHttpClient client = new OkHttpClient();
        RequestBody reqBody = null;
        if (body != null) {
            String stringnifiedBody = objectMapper.writeValueAsString(body);
            log.info("BODY ::: " + stringnifiedBody);
             reqBody = RequestBody.create(MediaType.parse("application/json"), stringnifiedBody);
        }


        Request req = new Request.Builder()
                .url(url)
                .headers(headers != null ? headers : Headers.of())
                .method(method, reqBody)
                .build();

        Response res = client.newCall(req).execute();
        if (!res.isSuccessful()) {
            return null;
        }
        String responseBody = res.body().string();
        log.info("RES ::: " + responseBody);
        return objectMapper.readValue(responseBody, returnClass);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy