2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.sdc.utils;
23 import static java.util.Arrays.asList;
24 import static org.onap.sdc.logger.FacadeLogUtils.serviceNameFromMDC;
26 import java.util.Optional;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.Future;
31 import java.util.concurrent.RejectedExecutionException;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.TimeoutException;
34 import java.util.function.Predicate;
36 import org.apache.commons.lang3.NotImplementedException;
37 import org.apache.commons.lang3.math.NumberUtils;
38 import org.apache.commons.lang3.time.StopWatch;
39 import org.openecomp.sdc.common.log.elements.ErrorLogOptionalData;
40 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
41 import org.openecomp.sdc.common.log.wrappers.Logger;
44 * Utility class for functional code
49 public final class FunctionalCodeUtils {
50 static final Logger LOG = Logger.getLogger(FunctionalCodeUtils.class);
54 private FunctionalCodeUtils() {
55 throw new UnsupportedOperationException("Do not instantiate utility class");
59 * Wraps the execution of the Runnable with try catch.<br>
60 * In case exception occurred returns Optional containing the
61 * resultOnException.<br>
62 * Otherwise returns an Empty optional.
65 * @param resultOnException
69 public static <T, E extends Exception> Optional<T> wrapWithTryCatch(RunnableThrows<E> runnable,
70 T resultOnException, String serviceName) {
71 Optional<T> optionalError;
74 optionalError = Optional.empty();
75 } catch (Exception e) {
76 logException(e, serviceName);
77 optionalError = Optional.of(resultOnException);
83 * Wraps the execution of the Runnable with try catch.<br>
84 * In case exception occurred logs the Exception.<br>
85 * resultOnException.<br>
86 * Otherwise returns an Empty optional.
89 * @param resultOnException
92 public static <E extends Exception> void wrapWithTryCatch(RunnableThrows<E> runnable, String serviceName) {
93 wrapWithTryCatch(runnable, serviceName);
97 * Functional Interface Similar to Runnable except that throws Exception
104 public interface RunnableThrows<E extends Exception> {
106 * Similar to run of Runnable except that throws Exception
114 private static void logException(Exception e, String serviceName) {
115 LOG.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, serviceName, new ErrorLogOptionalData(),"Error was caught : {}", e.getMessage());
116 LOG.debug("Error was caught ", e);
120 * Finds a value in an enum array by predicate
126 public static <T extends Enum<T>> T findByPredicate(Predicate<T> predicate, T[] values) {
128 final Optional<T> optionalFound = asList(values).stream()
131 return optionalFound.orElseThrow(() -> new NotImplementedException(
132 String.format("Enum: %s Not Found for predicate: %s ", values.getClass()
133 .getName(), predicate.toString())));
137 * Runs the given method.<br>
138 * In case the method passes without any Assertion Errors finishes.<br>
139 * In case there is an assertion error keeps running the method every retryIntervalMS.<br> until there is no Errors or maxWaitTimeMs has passed. <br>
140 * If there are still Assertion Errors in the last Run they are returned to the user.<br>
143 * @param maxWaitTimeMs
144 * @param retryIntervalMS
146 public static void retryMethodOnAssertionError(Runnable methodToRun, long maxWaitTimeMs, long retryIntervalMS, String serviceName) {
147 if (maxWaitTimeMs <= 0) {
148 throw new UnsupportedOperationException("Number maxWaitTimeMs be greater than 0");
150 StopWatch watch = new StopWatch();
152 boolean isLastTry = watch.getTime() + retryIntervalMS > maxWaitTimeMs;
153 boolean isSuccessfull = false;
155 while (!isLastTry && !isSuccessfull) {
158 isSuccessfull = true;
159 } catch (AssertionError e) {
160 wrapWithTryCatch(() -> Thread.sleep(retryIntervalMS), serviceName);
161 //Dummy Code to prevent sonar Issue
162 boolean flag = false;
164 LOG.debug(e.getMessage(), e);
167 isLastTry = watch.getTime() + retryIntervalMS > maxWaitTimeMs;
176 * @author mshitrit Supplier that throws an exception
180 public interface SupplierThrows<R, E extends Exception> {
182 * Same get method, but throws an exception
192 * Runs a method that declares throwing an Exception and has a return value.
194 * In case Exception Occurred replaces it with RunTimeException. <br>
195 * This is useful for two cases:<br>
196 * 1.using methods that throws exceptions in streams.<br>
197 * 2.replacing declared exception with undeclared exception (Runtime).<br>
198 * See below Use Case:<br>
199 * Instead of: intList.stream().map(e -> fooThrowsAndReturnsBoolean(e)); -
200 * does not compile !<br>
201 * Use This : intList.stream().map(e -> swallowException( () ->
202 * fooThrowsAndReturnsBoolean(e))); - compiles !<br>
207 public static <R, E extends Exception> R replaceWithUncheckedException(SupplierThrows<R, E> methodToRun) {
209 return methodToRun.get();
210 } catch (Exception e) {
211 throw new RuntimeException(e);
216 * Runs a method that declares throwing an Exception without return value.
218 * In case Exception Occurred replaces it with RunTimeException. <br>
219 * This is useful for two cases:<br>
220 * 1.using methods that throws exceptions in streams.<br>
221 * 2.replacing declared exception with undeclared exception (Runtime).<br>
222 * See below Use Case:<br>
226 public static <E extends Exception> void replaceWithUncheckedException(RunnableThrows<E> methodToRun) {
228 SupplierThrows<Boolean, E> runnableWrapper = () -> {
232 replaceWithUncheckedException(runnableWrapper);
237 * This method runs the given method.<br>
238 * In case given method finished running within timeoutInMs limit it returns true.<br>
239 * In case given method did not finish running within timeoutInMs limit it returns false.<br>
247 public static boolean runMethodWithTimeOut(Runnable runnable, long timeoutInMs, String serviceName) {
248 boolean isFinishedWithingTimeOut;
249 if (timeoutInMs <= NumberUtils.LONG_ZERO) {
250 isFinishedWithingTimeOut = false;
252 ExecutorService pool = Executors.newSingleThreadExecutor();
253 Future<Boolean> future = pool.submit(runnable, Boolean.TRUE);
256 isFinishedWithingTimeOut = future.get(timeoutInMs, TimeUnit.MILLISECONDS);
258 } catch (NullPointerException | RejectedExecutionException | InterruptedException | ExecutionException | TimeoutException e) {
259 isFinishedWithingTimeOut = false;
260 LOG.debug("method run was canceled because it has passed its time limit of {} MS ", timeoutInMs, e);
264 isFinishedWithingTimeOut = false;
265 logException(e, serviceName);
270 return isFinishedWithingTimeOut;