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

com.lonepulse.zombielink.executor.AsyncExecutionHandler Maven / Gradle / Ivy

The newest version!
package com.lonepulse.zombielink.executor;

/*
 * #%L
 * ZombieLink
 * %%
 * Copyright (C) 2013 - 2014 Lonepulse
 * %%
 * Licensed 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.
 * #L%
 */

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;

import com.lonepulse.zombielink.annotation.Async;
import com.lonepulse.zombielink.processor.Processors;
import com.lonepulse.zombielink.proxy.InvocationContext;
import com.lonepulse.zombielink.proxy.InvocationException;
import com.lonepulse.zombielink.response.AsyncHandler;

/**
 * 

This is an implementation of {@link ExecutionHandler} which manages {@link AsyncHandler}s that * may be used in asynchronous requests. It should be used with {@link RequestExecutor}s that * support asynchronous request execution (i.e. those requests annotated with @{@link Async}).

* * @version 1.1.0 *

* @since 1.3.0 *

* @author Lahiru Sahan Jayasinghe */ final class AsyncExecutionHandler implements ExecutionHandler { private static final Log LOGGER = LogFactory.getLog(AsyncRequestExecutor.class); @SuppressWarnings("unchecked") //safe cast from Object to AsyncHandler private static AsyncHandler getAsyncHandler(InvocationContext context) { AsyncHandler asyncHandler = null; List requestArgs = context.getArguments(); if(requestArgs != null) { for (Object object : requestArgs) { if(object instanceof AsyncHandler) { asyncHandler = AsyncHandler.class.cast(object); break; } } } return asyncHandler; } /** *

The given {@link HttpResponse} with a successful status code is processed using the response * processor chain ({@link Processors#RESPONSE} and if an {@link AsyncHandler} is defined, the result * of the processor chain is submitted to the onSuccess callback. If response processing * resulted in an error, execution defers to {@link #onError(InvocationContext, Exception)} instead * and the success callback of the {@link AsyncHandler} is skipped.

* *

See {@link ExecutionHandler#onSuccess(InvocationContext, HttpResponse)}

* * @param context * the {@link InvocationContext} with information on the proxy invocation *

* @param response * the resulting {@link HttpResponse} with a successful status code *

* @since 1.3.0 */ @Override public void onSuccess(InvocationContext context, HttpResponse response) { Object reponseEntity = null; try { reponseEntity = Processors.RESPONSE.run(context, response); //process, regardless of an AsyncHandler definition } catch(Exception e) { onError(context, InvocationException.newInstance(context, response, e)); return; } AsyncHandler asyncHandler = getAsyncHandler(context); if(asyncHandler != null) { try { asyncHandler.onSuccess(response, reponseEntity); } catch (Exception e) { LOGGER.error("Callback \"onSuccess\" aborted with an exception.", e); } } } /** *

The given {@link HttpResponse} with a successful status code is processed using the response * processor chain ({@link Processors#RESPONSE} and if an {@link AsyncHandler} is defined, the given * {@link HttpResponse} with a failed status code is submitted to the onFailure callback. If * response processing resulted in an error, execution defers to {@link #onError(InvocationContext, * Exception)} instead and the success callback of the {@link AsyncHandler} is skipped.

* *

See {@link ExecutionHandler#onFailure(InvocationContext, HttpResponse)}

* * @param context * the {@link InvocationContext} with information on the proxy invocation *

* @param response * the resulting {@link HttpResponse} with a failed status code *

* @since 1.3.0 */ @Override public void onFailure(InvocationContext context, HttpResponse response) { try { Processors.RESPONSE.run(context, response); //process, regardless of a failed response } catch(Exception e) { onError(context, InvocationException.newInstance(context, response, e)); return; } AsyncHandler asyncHandler = getAsyncHandler(context); if(asyncHandler != null) { try { asyncHandler.onFailure(response); } catch (Exception e) { LOGGER.error("Callback \"onFailure\" aborted with an exception.", e); } } } /** *

If an {@link AsyncHandler} is defined, any exception which resulted in an error will be * available via the onError callback.

* *

See {@link ExecutionHandler#onError(InvocationContext, Exception)}

* * @param context * the {@link InvocationContext} with information on the proxy invocation *

* @param error * the exception which resulted in a request execution failure *

* @since 1.3.0 */ @Override public void onError(InvocationContext context, Exception error) { AsyncHandler asyncHandler = getAsyncHandler(context); if(asyncHandler != null) { try { asyncHandler.onError(error instanceof InvocationException? (InvocationException)error :InvocationException.newInstance(context, error)); } catch(Exception e) { LOGGER.error("Callback \"onError\" aborted with an exception.", e); } } } }