Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.fineract.restwebservice; import java.net.URI; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.HashMap; import java.util.List; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.lang.StringUtils; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.crypto.codec.Base64; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; public class PlatformRestClient extends RestTemplate { protected final String basicAuthenticationCredentials; private Integer numberOfHttpRequestAttempts = 0; private final Integer numberOfHttpRequestRetries = 3; /** * PlatformRestClient public constructor * * @param basicAuthenticationCredentials */ public PlatformRestClient(final String basicAuthenticationCredentials) { super(); this.basicAuthenticationCredentials = basicAuthenticationCredentials; this.configureClient(); } /** * PlatformRestClient public constructor * * @param securityContext */ public PlatformRestClient(final SecurityContext securityContext) { super(); this.basicAuthenticationCredentials = this.createBasicAuthenticationCredentials(securityContext); } /** * Skip SSL certificate verification */ private void skipSslCertificateVerification() { final TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; try { // get the SSL context object SSLContext sslContext = SSLContext.getInstance("SSL"); // initialize the SSL context sslContext.init(null, trustManager, new SecureRandom()); // Set the default SSLSocketFactory HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); } catch (Exception e) { } } /** * Configure the REST API client class */ protected void configureClient() { this.skipSslCertificateVerification(); // reset the variable this.numberOfHttpRequestAttempts = 0; } /** * Creates a new {@link HttpEntity} object for the HTTP request * * @param entityBody * @param basicAuthenticationCredentials * @param contentMediaType * @param acceptedResponseMediaTypes * @return {@link HttpEntity} object */ public HttpEntity<String> getHttpRequestEntity(final String entityBody, final MediaType contentMediaType, final List<MediaType> acceptedResponseMediaTypes) { final HttpHeaders entityHeaders = new HttpHeaders(); entityHeaders.setContentType(contentMediaType); entityHeaders.setAccept(acceptedResponseMediaTypes); if (StringUtils.isNotEmpty(basicAuthenticationCredentials)) { entityHeaders.add("Authorization", "Basic " + this.basicAuthenticationCredentials); } return new HttpEntity<String>(entityBody, entityHeaders); } /** * Creates a new {@link HttpEntity} object for a JSON HTTP request * * @param entityBody * @return {@link HttpEntity} object */ public HttpEntity<String> getJsonHttpRequestEntity(final String entityBody) { return this.getHttpRequestEntity(entityBody, MediaType.APPLICATION_JSON, Arrays.asList(MediaType.APPLICATION_JSON)); } /** * Creates a HTTP basic authentication credentials using the spring {@link SecurityContext} authentication credentials * * @param securityContext {@link SecurityContext} object * @return basic authentication credentials */ public String createBasicAuthenticationCredentials(final SecurityContext securityContext) { String basicAuthenticationCredentials = null; if ((securityContext.getAuthentication() != null) && (securityContext.getAuthentication().getCredentials() != null)) { final String username = securityContext.getAuthentication().getName(); final String password = securityContext.getAuthentication().getCredentials().toString(); basicAuthenticationCredentials = this.createBasicAuthenticationCredentials(username, password); } return basicAuthenticationCredentials; } /** * Creates a HTTP basic authentication credentials * * @param username * @param password * @return basic authentication credentials */ public String createBasicAuthenticationCredentials(final String username, final String password) { final String concatUsernameAndPassword = username + ":" + password; final byte[] encodeConcatUsernameAndPassword = Base64.encode(concatUsernameAndPassword.getBytes()); return new String(encodeConcatUsernameAndPassword); } /** * Executes a HTTP request using the spring framework RestTemplate * * @param url the URL * @param method the HTTP method (GET, POST, etc) * @param requestEntity the entity (headers and/or body) to write to the request, may be null * @param responseType the type of the return value * @return the response as entity * @throws InterruptedException * @throws RestClientException */ public <T> ResponseEntity<T> executeHttpRequest(final URI url, final HttpMethod method, final HttpEntity<?> requestEntity, final Class<T> responseType) { final RestTemplate restTemplate = new RestTemplate(); HttpStatus statusCode = null; ResponseEntity<T> responseEntity = null; // increment the number of request attempts by 1 this.numberOfHttpRequestAttempts++; try { // execute the HTTP request responseEntity = restTemplate.exchange(url, method, requestEntity, responseType); statusCode = responseEntity.getStatusCode(); // catch all server HTTP error exceptions } catch (HttpServerErrorException exception) { statusCode = exception.getStatusCode(); // if HTTP status is 503 or 504, sleep for 5 seconds and retry if ((statusCode.equals(HttpStatus.SERVICE_UNAVAILABLE) || statusCode.equals(HttpStatus.GATEWAY_TIMEOUT)) && (this.numberOfHttpRequestAttempts < this.numberOfHttpRequestRetries)) { logger.info("Server returned an error response with status: " + statusCode + ", retrying again in 5 seconds"); logger.info("Number of attempts: " + this.numberOfHttpRequestAttempts); try { // sleep for 5 seconds and try again Thread.sleep(5000); } catch (InterruptedException interruptedException) { logger.error(interruptedException.getMessage(), interruptedException); } // execute HTTP request again this.executeHttpRequest(url, method, requestEntity, responseType); } else { // in other cases, throw back the exception throw exception; } } return responseEntity; } /** * Checks if the string is a valid JSON array * * @param string * @return true if valid, else false */ public static Boolean isJsonArray(final String string) { try { new ObjectMapper().readValue(string, new TypeReference<List<HashMap<String, Object>>>() { }); } catch (Exception exception) { return false; } return true; } /** * Checks if the string is a valid JSON object * * @param string * @return true if valid, else false */ public static Boolean isJsonObject(final String string) { try { new ObjectMapper().readValue(string, HashMap.class); } catch (Exception exception) { return false; } return true; } }