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

com.sap.cloud.yaas.rammler.commons.RequestExecutor Maven / Gradle / Ivy

There is a newer version: 1.8.1
Show newest version
/*
 * © 2016 SAP SE or an SAP affiliate company.
 * All rights reserved.
 * Please see http://www.sap.com/corporate-en/legal/copyright/index.epx for additional trademark information and
 * notices.
 */
package com.sap.cloud.yaas.rammler.commons;

import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.function.Supplier;

import javax.ws.rs.client.Invocation;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.concurrent.FutureAdapter;


/**
 * A class capable of performing the actual execution of a request (Invocation).
 * It provides sync (execute()) and async (queue()) execution.
 */
public class RequestExecutor
{
	private static final Logger LOG = LoggerFactory.getLogger(RequestExecutor.class);

	private final CallbackHandler callbackHandler;

	/**
	 * Creates a new instance of this {@link RequestExecutor}, using the given {@link CallbackHandler}.
	 * 
	 * @param callbackHandler the callback handler to be used
	 */
	public RequestExecutor(final CallbackHandler callbackHandler)
	{
		this.callbackHandler = callbackHandler;
	}

	/**
	 * Execute the request synchronously, and return an object of type {@link Response}.
	 *
	 * @param invocation the request invocation object
	 * @return the response
	 */
	public Response execute(final Invocation invocation)
	{
		final Response response = handleCallError(() -> {
			return invocation.invoke();
		});
		callbackHandler.completed(response);
		return response;
	}

	/**
	 * Execute the request synchronously, and return an object of custom type, provided by the clazz parameter.
	 *
	 * @param invocation the request invocation object
	 * @param clazz the class object representing the type to which the response body should be converted
	 * @param  the expected type of the response body
	 * @return the response converted to given type
	 */
	public  T execute(final Invocation invocation, final Class clazz)
	{
		final Response response = handleCallError(() -> {
			return invocation.invoke();
		});

		// dont catch exceptions from the handler
		callbackHandler.completed(response);
		try
		{
			return handleUnmarshallingError((final Class c) -> {
				return response.readEntity(c);
			}, clazz);
		}
		finally
		{
			// in case of InputStream
			response.close();
		}
	}

	/**
	 * Execute the request synchronously, and return an object of custom type, provided by the gt parameter.
	 *
	 * @param invocation the request invocation object
	 * @param gt {@link GenericType} object representing the type to which the response body should be converted
	 * @param  the expected type of the response body
	 * @return the response converted to given type
	 */
	public  T execute(final Invocation invocation, final GenericType gt)
	{
		final Response response = handleCallError(() -> {
			return invocation.invoke();
		});

		// dont catch exceptions from the handler
		callbackHandler.completed(response);

		try
		{
			return handleUnmarshallingError((final GenericType c) -> {
				return response.readEntity(c);
			}, gt);
		}
		finally
		{
			// in case of InputStream
			response.close();
		}
	}

	/**
	 * Execute the request asynchronously, and return an object of type {@link Response}.
	 *
	 * @param invocation the request invocation object
	 * @return the future of response
	 */
	public Future queue(final Invocation invocation)
	{
		return invocation.submit(callbackHandler);
	}

	/**
	 * Execute the request asynchronously, and return an object of custom type, provided by the clazz parameter.
	 *
	 * @param invocation the request invocation object
	 * @param clazz the class object representing the type to which the response body should be converted
	 * @param  the expected type of the response body
	 * @return the future of the given type
	 */
	public  Future queue(final Invocation invocation, final Class clazz)
	{
		final Future result = invocation.submit(callbackHandler);
		return new FutureAdapter(result)
		{
			@Override
			protected T adapt(final Response response)
			{
				try
				{
					return handleUnmarshallingError((final Class c) -> {
						return response.readEntity(c);
					}, clazz);
				}
				finally
				{
					// in case of InputStream
					response.close();
				}
			}
		};
	}

	/**
	 * Execute the request asynchronously, and return an object of custom type, provided by the gt parameter.
	 *
	 * @param invocation the request invocation object
	 * @param gt {@link GenericType} object representing the type to which the response body should be converted
	 * @param  the expected type of the response body
	 * @return the future of the given type
	 */
	public  Future queue(final Invocation invocation, final GenericType gt)
	{
		final Future result = invocation.submit(callbackHandler);
		return new FutureAdapter(result)
		{
			@Override
			protected T adapt(final Response response)
			{
				try
				{
					return handleUnmarshallingError((final GenericType c) -> {
						return response.readEntity(c);
					}, gt);
				}
				finally
				{
					// in case of InputStream
					response.close();
				}
			}
		};
	}

	private Response handleCallError(final Supplier supplier)
	{
		try
		{
			return supplier.get();
		}
		// CHECKSTYLE IGNORE IllegalCatchCheck NEXT 1 LINES
		catch (final RuntimeException e)// NOPMD // NOSONAR
		{
			LOG.warn("Exception executing the REST call: " + e.getMessage(), e);
			return handleTheErrorOrNot(e);
		}
	}

	private  O handleUnmarshallingError(final Function function, final I clazz)
	{
		try
		{
			return function.apply(clazz);
		}
		// CHECKSTYLE IGNORE IllegalCatchCheck NEXT 1 LINES
		catch (final RuntimeException e)// NOPMD // NOSONAR
		{
			LOG.warn("Exception unmarshalling the entity: " + e.getMessage(), e);
			return handleTheErrorOrNot(e);
		}
	}

	private  T handleTheErrorOrNot(final RuntimeException e)
	{
		if (callbackHandler.handlesFailure(e))
		{
			// if the error was handled then return null
			return null;
		}
		else
		{
			// otherwise rethrow the exception
			throw e;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy