org.vfdtech.implementations.ApiClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utilities-and-generic-tools Show documentation
Show all versions of utilities-and-generic-tools Show documentation
A utilities service with generic tools implementation. Can be
plugged into your java project
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);
}
}