org.springframework.core.task.AsyncTaskExecutor

Here are the examples of the java api org.springframework.core.task.AsyncTaskExecutor taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

85 Examples 7

19 View Source File : EntityManagerFactoryBuilder.java
License : Apache License 2.0
Project Creator : yuanmabiji

/**
 * Configure the bootstrap executor to be used by the
 * {@link LocalContainerEnreplacedyManagerFactoryBean}.
 * @param bootstrapExecutor the executor
 * @since 2.1.0
 */
public void setBootstrapExecutor(AsyncTaskExecutor bootstrapExecutor) {
    this.bootstrapExecutor = bootstrapExecutor;
}

19 View Source File : RequestMappingHandlerAdapter.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Set the default {@link AsyncTaskExecutor} to use when a controller method
 * return a {@link Callable}. Controller methods can override this default on
 * a per-request basis by returning an {@link WebAsyncTask}.
 * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used.
 * It's recommended to change that default in production as the simple executor
 * does not re-use threads.
 */
public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

19 View Source File : AsyncSupportConfigurer.java
License : MIT License
Project Creator : Vip-Augus

/**
 * The provided task executor is used to:
 * <ol>
 * <li>Handle {@link Callable} controller method return values.
 * <li>Perform blocking writes when streaming to the response
 * through a reactive (e.g. Reactor, RxJava) controller method return value.
 * </ol>
 * <p>By default only a {@link SimpleAsyncTaskExecutor} is used. However when
 * using the above two use cases, it's recommended to configure an executor
 * backed by a thread pool such as {@link ThreadPoolTaskExecutor}.
 * @param taskExecutor the task executor instance to use by default
 */
public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
    return this;
}

19 View Source File : WebAsyncManagerTimeoutTests.java
License : MIT License
Project Creator : Vip-Augus

@Before
public void setup() {
    this.servletRequest = new MockHttpServletRequest("GET", "/test");
    this.servletRequest.setAsyncSupported(true);
    this.servletResponse = new MockHttpServletResponse();
    this.asyncWebRequest = new StandardServletAsyncWebRequest(servletRequest, servletResponse);
    AsyncTaskExecutor executor = mock(AsyncTaskExecutor.clreplaced);
    this.asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
    this.asyncManager.setTaskExecutor(executor);
    this.asyncManager.setAsyncWebRequest(this.asyncWebRequest);
}

19 View Source File : WebAsyncTask.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Holder for a {@link Callable}, a timeout value, and a task executor.
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @since 3.2
 * @param <V> the value type
 */
public clreplaced WebAsyncTask<V> implements BeanFactoryAware {

    private final Callable<V> callable;

    private Long timeout;

    private AsyncTaskExecutor executor;

    private String executorName;

    private BeanFactory beanFactory;

    private Callable<V> timeoutCallback;

    private Callable<V> errorCallback;

    private Runnable completionCallback;

    /**
     * Create a {@code WebAsyncTask} wrapping the given {@link Callable}.
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(Callable<V> callable) {
        replacedert.notNull(callable, "Callable must not be null");
        this.callable = callable;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value and a {@link Callable}.
     * @param timeout a timeout value in milliseconds
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(long timeout, Callable<V> callable) {
        this(callable);
        this.timeout = timeout;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value, an executor name, and a {@link Callable}.
     * @param timeout timeout value in milliseconds; ignored if {@code null}
     * @param executorName the name of an executor bean to use
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(@Nullable Long timeout, String executorName, Callable<V> callable) {
        this(callable);
        replacedert.notNull(executorName, "Executor name must not be null");
        this.executorName = executorName;
        this.timeout = timeout;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value, an executor instance, and a Callable.
     * @param timeout timeout value in milliseconds; ignored if {@code null}
     * @param executor the executor to use
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(@Nullable Long timeout, AsyncTaskExecutor executor, Callable<V> callable) {
        this(callable);
        replacedert.notNull(executor, "Executor must not be null");
        this.executor = executor;
        this.timeout = timeout;
    }

    /**
     * Return the {@link Callable} to use for concurrent handling (never {@code null}).
     */
    public Callable<?> getCallable() {
        return this.callable;
    }

    /**
     * Return the timeout value in milliseconds, or {@code null} if no timeout is set.
     */
    @Nullable
    public Long getTimeout() {
        return this.timeout;
    }

    /**
     * A {@link BeanFactory} to use for resolving an executor name.
     * <p>This factory reference will automatically be set when
     * {@code WebAsyncTask} is used within a Spring MVC controller.
     */
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    /**
     * Return the AsyncTaskExecutor to use for concurrent handling,
     * or {@code null} if none specified.
     */
    @Nullable
    public AsyncTaskExecutor getExecutor() {
        if (this.executor != null) {
            return this.executor;
        } else if (this.executorName != null) {
            replacedert.state(this.beanFactory != null, "BeanFactory is required to look up an executor bean by name");
            return this.beanFactory.getBean(this.executorName, AsyncTaskExecutor.clreplaced);
        } else {
            return null;
        }
    }

    /**
     * Register code to invoke when the async request times out.
     * <p>This method is called from a container thread when an async request times
     * out before the {@code Callable} has completed. The callback is executed in
     * the same thread and therefore should return without blocking. It may return
     * an alternative value to use, including an {@link Exception} or return
     * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}.
     */
    public void onTimeout(Callable<V> callback) {
        this.timeoutCallback = callback;
    }

    /**
     * Register code to invoke for an error during async request processing.
     * <p>This method is called from a container thread when an error occurred
     * while processing an async request before the {@code Callable} has
     * completed. The callback is executed in the same thread and therefore
     * should return without blocking. It may return an alternative value to
     * use, including an {@link Exception} or return
     * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}.
     * @since 5.0
     */
    public void onError(Callable<V> callback) {
        this.errorCallback = callback;
    }

    /**
     * Register code to invoke when the async request completes.
     * <p>This method is called from a container thread when an async request
     * completed for any reason, including timeout and network error.
     */
    public void onCompletion(Runnable callback) {
        this.completionCallback = callback;
    }

    CallableProcessingInterceptor getInterceptor() {
        return new CallableProcessingInterceptor() {

            @Override
            public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
                return (timeoutCallback != null ? timeoutCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
            }

            @Override
            public <T> Object handleError(NativeWebRequest request, Callable<T> task, Throwable t) throws Exception {
                return (errorCallback != null ? errorCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
            }

            @Override
            public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
                if (completionCallback != null) {
                    completionCallback.run();
                }
            }
        };
    }
}

19 View Source File : WebAsyncManager.java
License : MIT License
Project Creator : Vip-Augus

/**
 * The central clreplaced for managing asynchronous request processing, mainly intended
 * as an SPI and not typically used directly by application clreplacedes.
 *
 * <p>An async scenario starts with request processing as usual in a thread (T1).
 * Concurrent request handling can be initiated by calling
 * {@link #startCallableProcessing(Callable, Object...) startCallableProcessing} or
 * {@link #startDeferredResultProcessing(DeferredResult, Object...) startDeferredResultProcessing},
 * both of which produce a result in a separate thread (T2). The result is saved
 * and the request dispatched to the container, to resume processing with the saved
 * result in a third thread (T3). Within the dispatched thread (T3), the saved
 * result can be accessed via {@link #getConcurrentResult()} or its presence
 * detected via {@link #hasConcurrentResult()}.
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @since 3.2
 * @see org.springframework.web.context.request.AsyncWebRequestInterceptor
 * @see org.springframework.web.servlet.AsyncHandlerInterceptor
 * @see org.springframework.web.filter.OncePerRequestFilter#shouldNotFilterAsyncDispatch
 * @see org.springframework.web.filter.OncePerRequestFilter#isAsyncDispatch
 */
public final clreplaced WebAsyncManager {

    private static final Object RESULT_NONE = new Object();

    private static final AsyncTaskExecutor DEFAULT_TASK_EXECUTOR = new SimpleAsyncTaskExecutor(WebAsyncManager.clreplaced.getSimpleName());

    private static final Log logger = LogFactory.getLog(WebAsyncManager.clreplaced);

    private static final CallableProcessingInterceptor timeoutCallableInterceptor = new TimeoutCallableProcessingInterceptor();

    private static final DeferredResultProcessingInterceptor timeoutDeferredResultInterceptor = new TimeoutDeferredResultProcessingInterceptor();

    private static Boolean taskExecutorWarning = true;

    private AsyncWebRequest asyncWebRequest;

    private AsyncTaskExecutor taskExecutor = DEFAULT_TASK_EXECUTOR;

    private volatile Object concurrentResult = RESULT_NONE;

    private volatile Object[] concurrentResultContext;

    private final Map<Object, CallableProcessingInterceptor> callableInterceptors = new LinkedHashMap<>();

    private final Map<Object, DeferredResultProcessingInterceptor> deferredResultInterceptors = new LinkedHashMap<>();

    /**
     * Package-private constructor.
     * @see WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
     * @see WebAsyncUtils#getAsyncManager(org.springframework.web.context.request.WebRequest)
     */
    WebAsyncManager() {
    }

    /**
     * Configure the {@link AsyncWebRequest} to use. This property may be set
     * more than once during a single request to accurately reflect the current
     * state of the request (e.g. following a forward, request/response
     * wrapping, etc). However, it should not be set while concurrent handling
     * is in progress, i.e. while {@link #isConcurrentHandlingStarted()} is
     * {@code true}.
     * @param asyncWebRequest the web request to use
     */
    public void setAsyncWebRequest(AsyncWebRequest asyncWebRequest) {
        replacedert.notNull(asyncWebRequest, "AsyncWebRequest must not be null");
        this.asyncWebRequest = asyncWebRequest;
        this.asyncWebRequest.addCompletionHandler(() -> asyncWebRequest.removeAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST));
    }

    /**
     * Configure an AsyncTaskExecutor for use with concurrent processing via
     * {@link #startCallableProcessing(Callable, Object...)}.
     * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used.
     */
    public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Whether the selected handler for the current request chose to handle the
     * request asynchronously. A return value of "true" indicates concurrent
     * handling is under way and the response will remain open. A return value
     * of "false" means concurrent handling was either not started or possibly
     * that it has completed and the request was dispatched for further
     * processing of the concurrent result.
     */
    public boolean isConcurrentHandlingStarted() {
        return (this.asyncWebRequest != null && this.asyncWebRequest.isAsyncStarted());
    }

    /**
     * Whether a result value exists as a result of concurrent handling.
     */
    public boolean hasConcurrentResult() {
        return (this.concurrentResult != RESULT_NONE);
    }

    /**
     * Provides access to the result from concurrent handling.
     * @return an Object, possibly an {@code Exception} or {@code Throwable} if
     * concurrent handling raised one.
     * @see #clearConcurrentResult()
     */
    public Object getConcurrentResult() {
        return this.concurrentResult;
    }

    /**
     * Provides access to additional processing context saved at the start of
     * concurrent handling.
     * @see #clearConcurrentResult()
     */
    public Object[] getConcurrentResultContext() {
        return this.concurrentResultContext;
    }

    /**
     * Get the {@link CallableProcessingInterceptor} registered under the given key.
     * @param key the key
     * @return the interceptor registered under that key, or {@code null} if none
     */
    @Nullable
    public CallableProcessingInterceptor getCallableInterceptor(Object key) {
        return this.callableInterceptors.get(key);
    }

    /**
     * Get the {@link DeferredResultProcessingInterceptor} registered under the given key.
     * @param key the key
     * @return the interceptor registered under that key, or {@code null} if none
     */
    @Nullable
    public DeferredResultProcessingInterceptor getDeferredResultInterceptor(Object key) {
        return this.deferredResultInterceptors.get(key);
    }

    /**
     * Register a {@link CallableProcessingInterceptor} under the given key.
     * @param key the key
     * @param interceptor the interceptor to register
     */
    public void registerCallableInterceptor(Object key, CallableProcessingInterceptor interceptor) {
        replacedert.notNull(key, "Key is required");
        replacedert.notNull(interceptor, "CallableProcessingInterceptor  is required");
        this.callableInterceptors.put(key, interceptor);
    }

    /**
     * Register a {@link CallableProcessingInterceptor} without a key.
     * The key is derived from the clreplaced name and hashcode.
     * @param interceptors one or more interceptors to register
     */
    public void registerCallableInterceptors(CallableProcessingInterceptor... interceptors) {
        replacedert.notNull(interceptors, "A CallableProcessingInterceptor is required");
        for (CallableProcessingInterceptor interceptor : interceptors) {
            String key = interceptor.getClreplaced().getName() + ":" + interceptor.hashCode();
            this.callableInterceptors.put(key, interceptor);
        }
    }

    /**
     * Register a {@link DeferredResultProcessingInterceptor} under the given key.
     * @param key the key
     * @param interceptor the interceptor to register
     */
    public void registerDeferredResultInterceptor(Object key, DeferredResultProcessingInterceptor interceptor) {
        replacedert.notNull(key, "Key is required");
        replacedert.notNull(interceptor, "DeferredResultProcessingInterceptor is required");
        this.deferredResultInterceptors.put(key, interceptor);
    }

    /**
     * Register one or more {@link DeferredResultProcessingInterceptor DeferredResultProcessingInterceptors} without a specified key.
     * The default key is derived from the interceptor clreplaced name and hash code.
     * @param interceptors one or more interceptors to register
     */
    public void registerDeferredResultInterceptors(DeferredResultProcessingInterceptor... interceptors) {
        replacedert.notNull(interceptors, "A DeferredResultProcessingInterceptor is required");
        for (DeferredResultProcessingInterceptor interceptor : interceptors) {
            String key = interceptor.getClreplaced().getName() + ":" + interceptor.hashCode();
            this.deferredResultInterceptors.put(key, interceptor);
        }
    }

    /**
     * Clear {@linkplain #getConcurrentResult() concurrentResult} and
     * {@linkplain #getConcurrentResultContext() concurrentResultContext}.
     */
    public void clearConcurrentResult() {
        synchronized (WebAsyncManager.this) {
            this.concurrentResult = RESULT_NONE;
            this.concurrentResultContext = null;
        }
    }

    /**
     * Start concurrent request processing and execute the given task with an
     * {@link #setTaskExecutor(AsyncTaskExecutor) AsyncTaskExecutor}. The result
     * from the task execution is saved and the request dispatched in order to
     * resume processing of that result. If the task raises an Exception then
     * the saved result will be the raised Exception.
     * @param callable a unit of work to be executed asynchronously
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     * @see #getConcurrentResult()
     * @see #getConcurrentResultContext()
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void startCallableProcessing(Callable<?> callable, Object... processingContext) throws Exception {
        replacedert.notNull(callable, "Callable must not be null");
        startCallableProcessing(new WebAsyncTask(callable), processingContext);
    }

    /**
     * Use the given {@link WebAsyncTask} to configure the task executor as well as
     * the timeout value of the {@code AsyncWebRequest} before delegating to
     * {@link #startCallableProcessing(Callable, Object...)}.
     * @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     */
    public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
        replacedert.notNull(webAsyncTask, "WebAsyncTask must not be null");
        replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
        Long timeout = webAsyncTask.getTimeout();
        if (timeout != null) {
            this.asyncWebRequest.setTimeout(timeout);
        }
        AsyncTaskExecutor executor = webAsyncTask.getExecutor();
        if (executor != null) {
            this.taskExecutor = executor;
        } else {
            logExecutorWarning();
        }
        List<CallableProcessingInterceptor> interceptors = new ArrayList<>();
        interceptors.add(webAsyncTask.getInterceptor());
        interceptors.addAll(this.callableInterceptors.values());
        interceptors.add(timeoutCallableInterceptor);
        final Callable<?> callable = webAsyncTask.getCallable();
        final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);
        this.asyncWebRequest.addTimeoutHandler(() -> {
            logger.debug("Async request timeout for " + formatRequestUri());
            Object result = interceptorChain.triggerAfterTimeout(this.asyncWebRequest, callable);
            if (result != CallableProcessingInterceptor.RESULT_NONE) {
                setConcurrentResultAndDispatch(result);
            }
        });
        this.asyncWebRequest.addErrorHandler(ex -> {
            logger.debug("Async request error for " + formatRequestUri() + ": " + ex);
            Object result = interceptorChain.triggerAfterError(this.asyncWebRequest, callable, ex);
            result = (result != CallableProcessingInterceptor.RESULT_NONE ? result : ex);
            setConcurrentResultAndDispatch(result);
        });
        this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, callable));
        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
        startAsyncProcessing(processingContext);
        try {
            Future<?> future = this.taskExecutor.submit(() -> {
                Object result = null;
                try {
                    interceptorChain.applyPreProcess(this.asyncWebRequest, callable);
                    result = callable.call();
                } catch (Throwable ex) {
                    result = ex;
                } finally {
                    result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, result);
                }
                setConcurrentResultAndDispatch(result);
            });
            interceptorChain.setTaskFuture(future);
        } catch (RejectedExecutionException ex) {
            Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
            setConcurrentResultAndDispatch(result);
            throw ex;
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void logExecutorWarning() {
        if (taskExecutorWarning && logger.isWarnEnabled()) {
            synchronized (DEFAULT_TASK_EXECUTOR) {
                AsyncTaskExecutor executor = this.taskExecutor;
                if (taskExecutorWarning && (executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor)) {
                    String executorTypeName = executor.getClreplaced().getSimpleName();
                    logger.warn("\n!!!\n" + "An Executor is required to handle java.util.concurrent.Callable return values.\n" + "Please, configure a TaskExecutor in the MVC config under \"async support\".\n" + "The " + executorTypeName + " currently in use is not suitable under load.\n" + "-------------------------------\n" + "Request URI: '" + formatRequestUri() + "'\n" + "!!!");
                    taskExecutorWarning = false;
                }
            }
        }
    }

    private String formatRequestUri() {
        HttpServletRequest request = this.asyncWebRequest.getNativeRequest(HttpServletRequest.clreplaced);
        return request != null ? request.getRequestURI() : "servlet container";
    }

    private void setConcurrentResultAndDispatch(Object result) {
        synchronized (WebAsyncManager.this) {
            if (this.concurrentResult != RESULT_NONE) {
                return;
            }
            this.concurrentResult = result;
        }
        if (this.asyncWebRequest.isAsyncComplete()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Async result set but request already complete: " + formatRequestUri());
            }
            return;
        }
        if (logger.isDebugEnabled()) {
            boolean isError = result instanceof Throwable;
            logger.debug("Async " + (isError ? "error" : "result set") + ", dispatch to " + formatRequestUri());
        }
        this.asyncWebRequest.dispatch();
    }

    /**
     * Start concurrent request processing and initialize the given
     * {@link DeferredResult} with a {@link DeferredResultHandler} that saves
     * the result and dispatches the request to resume processing of that
     * result. The {@code AsyncWebRequest} is also updated with a completion
     * handler that expires the {@code DeferredResult} and a timeout handler
     * replaceduming the {@code DeferredResult} has a default timeout result.
     * @param deferredResult the DeferredResult instance to initialize
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     * @see #getConcurrentResult()
     * @see #getConcurrentResultContext()
     */
    public void startDeferredResultProcessing(final DeferredResult<?> deferredResult, Object... processingContext) throws Exception {
        replacedert.notNull(deferredResult, "DeferredResult must not be null");
        replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
        Long timeout = deferredResult.getTimeoutValue();
        if (timeout != null) {
            this.asyncWebRequest.setTimeout(timeout);
        }
        List<DeferredResultProcessingInterceptor> interceptors = new ArrayList<>();
        interceptors.add(deferredResult.getInterceptor());
        interceptors.addAll(this.deferredResultInterceptors.values());
        interceptors.add(timeoutDeferredResultInterceptor);
        final DeferredResultInterceptorChain interceptorChain = new DeferredResultInterceptorChain(interceptors);
        this.asyncWebRequest.addTimeoutHandler(() -> {
            try {
                interceptorChain.triggerAfterTimeout(this.asyncWebRequest, deferredResult);
            } catch (Throwable ex) {
                setConcurrentResultAndDispatch(ex);
            }
        });
        this.asyncWebRequest.addErrorHandler(ex -> {
            try {
                if (!interceptorChain.triggerAfterError(this.asyncWebRequest, deferredResult, ex)) {
                    return;
                }
                deferredResult.setErrorResult(ex);
            } catch (Throwable interceptorEx) {
                setConcurrentResultAndDispatch(interceptorEx);
            }
        });
        this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, deferredResult));
        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
        startAsyncProcessing(processingContext);
        try {
            interceptorChain.applyPreProcess(this.asyncWebRequest, deferredResult);
            deferredResult.setResultHandler(result -> {
                result = interceptorChain.applyPostProcess(this.asyncWebRequest, deferredResult, result);
                setConcurrentResultAndDispatch(result);
            });
        } catch (Throwable ex) {
            setConcurrentResultAndDispatch(ex);
        }
    }

    private void startAsyncProcessing(Object[] processingContext) {
        synchronized (WebAsyncManager.this) {
            this.concurrentResult = RESULT_NONE;
            this.concurrentResultContext = processingContext;
        }
        this.asyncWebRequest.startAsync();
        if (logger.isDebugEnabled()) {
            logger.debug("Started async request");
        }
    }
}

19 View Source File : WebAsyncManager.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Use the given {@link WebAsyncTask} to configure the task executor as well as
 * the timeout value of the {@code AsyncWebRequest} before delegating to
 * {@link #startCallableProcessing(Callable, Object...)}.
 * @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
 * @param processingContext additional context to save that can be accessed
 * via {@link #getConcurrentResultContext()}
 * @throws Exception if concurrent processing failed to start
 */
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
    replacedert.notNull(webAsyncTask, "WebAsyncTask must not be null");
    replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
    Long timeout = webAsyncTask.getTimeout();
    if (timeout != null) {
        this.asyncWebRequest.setTimeout(timeout);
    }
    AsyncTaskExecutor executor = webAsyncTask.getExecutor();
    if (executor != null) {
        this.taskExecutor = executor;
    } else {
        logExecutorWarning();
    }
    List<CallableProcessingInterceptor> interceptors = new ArrayList<>();
    interceptors.add(webAsyncTask.getInterceptor());
    interceptors.addAll(this.callableInterceptors.values());
    interceptors.add(timeoutCallableInterceptor);
    final Callable<?> callable = webAsyncTask.getCallable();
    final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);
    this.asyncWebRequest.addTimeoutHandler(() -> {
        logger.debug("Async request timeout for " + formatRequestUri());
        Object result = interceptorChain.triggerAfterTimeout(this.asyncWebRequest, callable);
        if (result != CallableProcessingInterceptor.RESULT_NONE) {
            setConcurrentResultAndDispatch(result);
        }
    });
    this.asyncWebRequest.addErrorHandler(ex -> {
        logger.debug("Async request error for " + formatRequestUri() + ": " + ex);
        Object result = interceptorChain.triggerAfterError(this.asyncWebRequest, callable, ex);
        result = (result != CallableProcessingInterceptor.RESULT_NONE ? result : ex);
        setConcurrentResultAndDispatch(result);
    });
    this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, callable));
    interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
    startAsyncProcessing(processingContext);
    try {
        Future<?> future = this.taskExecutor.submit(() -> {
            Object result = null;
            try {
                interceptorChain.applyPreProcess(this.asyncWebRequest, callable);
                result = callable.call();
            } catch (Throwable ex) {
                result = ex;
            } finally {
                result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, result);
            }
            setConcurrentResultAndDispatch(result);
        });
        interceptorChain.setTaskFuture(future);
    } catch (RejectedExecutionException ex) {
        Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
        setConcurrentResultAndDispatch(result);
        throw ex;
    }
}

19 View Source File : WebAsyncManager.java
License : MIT License
Project Creator : Vip-Augus

@SuppressWarnings("ConstantConditions")
private void logExecutorWarning() {
    if (taskExecutorWarning && logger.isWarnEnabled()) {
        synchronized (DEFAULT_TASK_EXECUTOR) {
            AsyncTaskExecutor executor = this.taskExecutor;
            if (taskExecutorWarning && (executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor)) {
                String executorTypeName = executor.getClreplaced().getSimpleName();
                logger.warn("\n!!!\n" + "An Executor is required to handle java.util.concurrent.Callable return values.\n" + "Please, configure a TaskExecutor in the MVC config under \"async support\".\n" + "The " + executorTypeName + " currently in use is not suitable under load.\n" + "-------------------------------\n" + "Request URI: '" + formatRequestUri() + "'\n" + "!!!");
                taskExecutorWarning = false;
            }
        }
    }
}

19 View Source File : WebAsyncManager.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Configure an AsyncTaskExecutor for use with concurrent processing via
 * {@link #startCallableProcessing(Callable, Object...)}.
 * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used.
 */
public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

19 View Source File : SimpleTaskWorkManager.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Simple JCA 1.7 {@link javax.resource.spi.work.WorkManager} implementation that
 * delegates to a Spring {@link org.springframework.core.task.TaskExecutor}.
 * Provides simple task execution including start timeouts, but without support
 * for a JCA ExecutionContext (i.e. without support for imported transactions).
 *
 * <p>Uses a {@link org.springframework.core.task.SyncTaskExecutor} for {@link #doWork}
 * calls and a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
 * for {@link #startWork} and {@link #scheduleWork} calls, by default.
 * These default task executors can be overridden through configuration.
 *
 * <p><b>NOTE: This WorkManager does not provide thread pooling by default!</b>
 * Specify a {@link org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor}
 * (or any other thread-pooling TaskExecutor) as "asyncTaskExecutor" in order to
 * achieve actual thread pooling.
 *
 * <p>This WorkManager automatically detects a specified
 * {@link org.springframework.core.task.AsyncTaskExecutor} implementation
 * and uses its extended timeout functionality where appropriate.
 * JCA WorkListeners are fully supported in any case.
 *
 * @author Juergen Hoeller
 * @since 2.0.3
 * @see #setSyncTaskExecutor
 * @see #setAsyncTaskExecutor
 */
public clreplaced SimpleTaskWorkManager implements WorkManager {

    @Nullable
    private TaskExecutor syncTaskExecutor = new SyncTaskExecutor();

    @Nullable
    private AsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor();

    /**
     * Specify the TaskExecutor to use for <i>synchronous</i> work execution
     * (i.e. {@link #doWork} calls).
     * <p>Default is a {@link org.springframework.core.task.SyncTaskExecutor}.
     */
    public void setSyncTaskExecutor(TaskExecutor syncTaskExecutor) {
        this.syncTaskExecutor = syncTaskExecutor;
    }

    /**
     * Specify the TaskExecutor to use for <i>asynchronous</i> work execution
     * (i.e. {@link #startWork} and {@link #scheduleWork} calls).
     * <p>This will typically (but not necessarily) be an
     * {@link org.springframework.core.task.AsyncTaskExecutor} implementation.
     * Default is a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
     */
    public void setAsyncTaskExecutor(AsyncTaskExecutor asyncTaskExecutor) {
        this.asyncTaskExecutor = asyncTaskExecutor;
    }

    @Override
    public void doWork(Work work) throws WorkException {
        doWork(work, WorkManager.INDEFINITE, null, null);
    }

    @Override
    public void doWork(Work work, long startTimeout, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException {
        replacedert.state(this.syncTaskExecutor != null, "No 'syncTaskExecutor' set");
        executeWork(this.syncTaskExecutor, work, startTimeout, false, executionContext, workListener);
    }

    @Override
    public long startWork(Work work) throws WorkException {
        return startWork(work, WorkManager.INDEFINITE, null, null);
    }

    @Override
    public long startWork(Work work, long startTimeout, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException {
        replacedert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
        return executeWork(this.asyncTaskExecutor, work, startTimeout, true, executionContext, workListener);
    }

    @Override
    public void scheduleWork(Work work) throws WorkException {
        scheduleWork(work, WorkManager.INDEFINITE, null, null);
    }

    @Override
    public void scheduleWork(Work work, long startTimeout, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException {
        replacedert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
        executeWork(this.asyncTaskExecutor, work, startTimeout, false, executionContext, workListener);
    }

    /**
     * Execute the given Work on the specified TaskExecutor.
     * @param taskExecutor the TaskExecutor to use
     * @param work the Work to execute
     * @param startTimeout the time duration within which the Work is supposed to start
     * @param blockUntilStarted whether to block until the Work has started
     * @param executionContext the JCA ExecutionContext for the given Work
     * @param workListener the WorkListener to clal for the given Work
     * @return the time elapsed from Work acceptance until start of execution
     * (or -1 if not applicable or not known)
     * @throws WorkException if the TaskExecutor did not accept the Work
     */
    protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout, boolean blockUntilStarted, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException {
        if (executionContext != null && executionContext.getXid() != null) {
            throw new WorkException("SimpleTaskWorkManager does not supported imported XIDs: " + executionContext.getXid());
        }
        WorkListener workListenerToUse = workListener;
        if (workListenerToUse == null) {
            workListenerToUse = new WorkAdapter();
        }
        boolean isAsync = (taskExecutor instanceof AsyncTaskExecutor);
        DelegatingWorkAdapter workHandle = new DelegatingWorkAdapter(work, workListenerToUse, !isAsync);
        try {
            if (isAsync) {
                ((AsyncTaskExecutor) taskExecutor).execute(workHandle, startTimeout);
            } else {
                taskExecutor.execute(workHandle);
            }
        } catch (TaskTimeoutException ex) {
            WorkException wex = new WorkRejectedException("TaskExecutor rejected Work because of timeout: " + work, ex);
            wex.setErrorCode(WorkException.START_TIMED_OUT);
            workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
            throw wex;
        } catch (TaskRejectedException ex) {
            WorkException wex = new WorkRejectedException("TaskExecutor rejected Work: " + work, ex);
            wex.setErrorCode(WorkException.INTERNAL);
            workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
            throw wex;
        } catch (Throwable ex) {
            WorkException wex = new WorkException("TaskExecutor failed to execute Work: " + work, ex);
            wex.setErrorCode(WorkException.INTERNAL);
            throw wex;
        }
        if (isAsync) {
            workListenerToUse.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
        }
        if (blockUntilStarted) {
            long acceptanceTime = System.currentTimeMillis();
            synchronized (workHandle.monitor) {
                try {
                    while (!workHandle.started) {
                        workHandle.monitor.wait();
                    }
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
            return (System.currentTimeMillis() - acceptanceTime);
        } else {
            return WorkManager.UNKNOWN;
        }
    }

    /**
     * Work adapter that supports start timeouts and WorkListener callbacks
     * for a given Work that it delegates to.
     */
    private static clreplaced DelegatingWorkAdapter implements Work {

        private final Work work;

        private final WorkListener workListener;

        private final boolean acceptOnExecution;

        public final Object monitor = new Object();

        public boolean started = false;

        public DelegatingWorkAdapter(Work work, WorkListener workListener, boolean acceptOnExecution) {
            this.work = work;
            this.workListener = workListener;
            this.acceptOnExecution = acceptOnExecution;
        }

        @Override
        public void run() {
            if (this.acceptOnExecution) {
                this.workListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, this.work, null));
            }
            synchronized (this.monitor) {
                this.started = true;
                this.monitor.notify();
            }
            this.workListener.workStarted(new WorkEvent(this, WorkEvent.WORK_STARTED, this.work, null));
            try {
                this.work.run();
            } catch (RuntimeException | Error ex) {
                this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(ex)));
                throw ex;
            }
            this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, null));
        }

        @Override
        public void release() {
            this.work.release();
        }
    }
}

19 View Source File : SimpleTaskWorkManager.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Specify the TaskExecutor to use for <i>asynchronous</i> work execution
 * (i.e. {@link #startWork} and {@link #scheduleWork} calls).
 * <p>This will typically (but not necessarily) be an
 * {@link org.springframework.core.task.AsyncTaskExecutor} implementation.
 * Default is a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
 */
public void setAsyncTaskExecutor(AsyncTaskExecutor asyncTaskExecutor) {
    this.asyncTaskExecutor = asyncTaskExecutor;
}

19 View Source File : AbstractEntityManagerFactoryBean.java
License : MIT License
Project Creator : Vip-Augus

@Override
public void afterPropertiesSet() throws PersistenceException {
    JpaVendorAdapter jpaVendorAdapter = getJpaVendorAdapter();
    if (jpaVendorAdapter != null) {
        if (this.persistenceProvider == null) {
            this.persistenceProvider = jpaVendorAdapter.getPersistenceProvider();
        }
        PersistenceUnitInfo pui = getPersistenceUnitInfo();
        Map<String, ?> vendorPropertyMap = (pui != null ? jpaVendorAdapter.getJpaPropertyMap(pui) : jpaVendorAdapter.getJpaPropertyMap());
        if (!CollectionUtils.isEmpty(vendorPropertyMap)) {
            vendorPropertyMap.forEach((key, value) -> {
                if (!this.jpaPropertyMap.containsKey(key)) {
                    this.jpaPropertyMap.put(key, value);
                }
            });
        }
        if (this.enreplacedyManagerFactoryInterface == null) {
            this.enreplacedyManagerFactoryInterface = jpaVendorAdapter.getEnreplacedyManagerFactoryInterface();
            if (!ClreplacedUtils.isVisible(this.enreplacedyManagerFactoryInterface, this.beanClreplacedLoader)) {
                this.enreplacedyManagerFactoryInterface = EnreplacedyManagerFactory.clreplaced;
            }
        }
        if (this.enreplacedyManagerInterface == null) {
            this.enreplacedyManagerInterface = jpaVendorAdapter.getEnreplacedyManagerInterface();
            if (!ClreplacedUtils.isVisible(this.enreplacedyManagerInterface, this.beanClreplacedLoader)) {
                this.enreplacedyManagerInterface = EnreplacedyManager.clreplaced;
            }
        }
        if (this.jpaDialect == null) {
            this.jpaDialect = jpaVendorAdapter.getJpaDialect();
        }
    }
    AsyncTaskExecutor bootstrapExecutor = getBootstrapExecutor();
    if (bootstrapExecutor != null) {
        this.nativeEnreplacedyManagerFactoryFuture = bootstrapExecutor.submit(this::buildNativeEnreplacedyManagerFactory);
    } else {
        this.nativeEnreplacedyManagerFactory = buildNativeEnreplacedyManagerFactory();
    }
    // Wrap the EnreplacedyManagerFactory in a factory implementing all its interfaces.
    // This allows interception of createEnreplacedyManager methods to return an
    // application-managed EnreplacedyManager proxy that automatically joins
    // existing transactions.
    this.enreplacedyManagerFactory = createEnreplacedyManagerFactoryProxy(this.nativeEnreplacedyManagerFactory);
}

19 View Source File : AbstractEntityManagerFactoryBean.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Specify an asynchronous executor for background bootstrapping,
 * e.g. a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
 * <p>{@code EnreplacedyManagerFactory} initialization will then switch into background
 * bootstrap mode, with a {@code EnreplacedyManagerFactory} proxy immediately returned for
 * injection purposes instead of waiting for the JPA provider's bootstrapping to complete.
 * However, note that the first actual call to a {@code EnreplacedyManagerFactory} method will
 * then block until the JPA provider's bootstrapping completed, if not ready by then.
 * For maximum benefit, make sure to avoid early {@code EnreplacedyManagerFactory} calls
 * in init methods of related beans, even for metadata introspection purposes.
 * @since 4.3
 */
public void setBootstrapExecutor(@Nullable AsyncTaskExecutor bootstrapExecutor) {
    this.bootstrapExecutor = bootstrapExecutor;
}

19 View Source File : LocalSessionFactoryBuilder.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Build the Hibernate {@code SessionFactory} through background bootstrapping,
 * using the given executor for a parallel initialization phase
 * (e.g. a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}).
 * <p>{@code SessionFactory} initialization will then switch into background
 * bootstrap mode, with a {@code SessionFactory} proxy immediately returned for
 * injection purposes instead of waiting for Hibernate's bootstrapping to complete.
 * However, note that the first actual call to a {@code SessionFactory} method will
 * then block until Hibernate's bootstrapping completed, if not ready by then.
 * For maximum benefit, make sure to avoid early {@code SessionFactory} calls
 * in init methods of related beans, even for metadata introspection purposes.
 * @since 4.3
 * @see #buildSessionFactory()
 */
public SessionFactory buildSessionFactory(AsyncTaskExecutor bootstrapExecutor) {
    replacedert.notNull(bootstrapExecutor, "AsyncTaskExecutor must not be null");
    return (SessionFactory) Proxy.newProxyInstance(this.resourcePatternResolver.getClreplacedLoader(), new Clreplaced<?>[] { SessionFactoryImplementor.clreplaced, InfrastructureProxy.clreplaced }, new BootstrapSessionFactoryInvocationHandler(bootstrapExecutor));
}

19 View Source File : LocalSessionFactoryBean.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Specify an asynchronous executor for background bootstrapping,
 * e.g. a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
 * <p>{@code SessionFactory} initialization will then switch into background
 * bootstrap mode, with a {@code SessionFactory} proxy immediately returned for
 * injection purposes instead of waiting for Hibernate's bootstrapping to complete.
 * However, note that the first actual call to a {@code SessionFactory} method will
 * then block until Hibernate's bootstrapping completed, if not ready by then.
 * For maximum benefit, make sure to avoid early {@code SessionFactory} calls
 * in init methods of related beans, even for metadata introspection purposes.
 * @since 4.3
 * @see LocalSessionFactoryBuilder#buildSessionFactory(AsyncTaskExecutor)
 */
public void setBootstrapExecutor(AsyncTaskExecutor bootstrapExecutor) {
    this.bootstrapExecutor = bootstrapExecutor;
}

19 View Source File : AsyncExecutionInterceptor.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Intercept the given method invocation, submit the actual calling of the method to
 * the correct task executor and return immediately to the caller.
 * @param invocation the method to intercept and make asynchronous
 * @return {@link Future} if the original method returns {@code Future}; {@code null}
 * otherwise.
 */
@Override
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
    Clreplaced<?> targetClreplaced = (invocation.getThis() != null ? AopUtils.getTargetClreplaced(invocation.getThis()) : null);
    Method specificMethod = ClreplacedUtils.getMostSpecificMethod(invocation.getMethod(), targetClreplaced);
    final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
    AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
    if (executor == null) {
        throw new IllegalStateException("No executor specified and no default executor set on AsyncExecutionInterceptor either");
    }
    Callable<Object> task = () -> {
        try {
            Object result = invocation.proceed();
            if (result instanceof Future) {
                return ((Future<?>) result).get();
            }
        } catch (ExecutionException ex) {
            handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
        } catch (Throwable ex) {
            handleError(ex, userDeclaredMethod, invocation.getArguments());
        }
        return null;
    };
    return doSubmit(task, executor, invocation.getMethod().getReturnType());
}

19 View Source File : WebAsyncManagerTimeoutTests.java
License : Apache License 2.0
Project Creator : SourceHot

@BeforeEach
public void setup() {
    this.servletRequest = new MockHttpServletRequest("GET", "/test");
    this.servletRequest.setAsyncSupported(true);
    this.servletResponse = new MockHttpServletResponse();
    this.asyncWebRequest = new StandardServletAsyncWebRequest(servletRequest, servletResponse);
    AsyncTaskExecutor executor = mock(AsyncTaskExecutor.clreplaced);
    this.asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
    this.asyncManager.setTaskExecutor(executor);
    this.asyncManager.setAsyncWebRequest(this.asyncWebRequest);
}

19 View Source File : WebAsyncTask.java
License : Apache License 2.0
Project Creator : SourceHot

/**
 * Holder for a {@link Callable}, a timeout value, and a task executor.
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @since 3.2
 * @param <V> the value type
 */
public clreplaced WebAsyncTask<V> implements BeanFactoryAware {

    private final Callable<V> callable;

    private Long timeout;

    private AsyncTaskExecutor executor;

    private String executorName;

    private BeanFactory beanFactory;

    private Callable<V> timeoutCallback;

    private Callable<V> errorCallback;

    private Runnable completionCallback;

    /**
     * Create a {@code WebAsyncTask} wrapping the given {@link Callable}.
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(Callable<V> callable) {
        replacedert.notNull(callable, "Callable must not be null");
        this.callable = callable;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value and a {@link Callable}.
     * @param timeout a timeout value in milliseconds
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(long timeout, Callable<V> callable) {
        this(callable);
        this.timeout = timeout;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value, an executor name, and a {@link Callable}.
     * @param timeout timeout value in milliseconds; ignored if {@code null}
     * @param executorName the name of an executor bean to use
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(@Nullable Long timeout, String executorName, Callable<V> callable) {
        this(callable);
        replacedert.notNull(executorName, "Executor name must not be null");
        this.executorName = executorName;
        this.timeout = timeout;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value, an executor instance, and a Callable.
     * @param timeout timeout value in milliseconds; ignored if {@code null}
     * @param executor the executor to use
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(@Nullable Long timeout, AsyncTaskExecutor executor, Callable<V> callable) {
        this(callable);
        replacedert.notNull(executor, "Executor must not be null");
        this.executor = executor;
        this.timeout = timeout;
    }

    /**
     * Return the {@link Callable} to use for concurrent handling (never {@code null}).
     */
    public Callable<?> getCallable() {
        return this.callable;
    }

    /**
     * Return the timeout value in milliseconds, or {@code null} if no timeout is set.
     */
    @Nullable
    public Long getTimeout() {
        return this.timeout;
    }

    /**
     * A {@link BeanFactory} to use for resolving an executor name.
     * <p>This factory reference will automatically be set when
     * {@code WebAsyncTask} is used within a Spring MVC controller.
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    /**
     * Return the AsyncTaskExecutor to use for concurrent handling,
     * or {@code null} if none specified.
     */
    @Nullable
    public AsyncTaskExecutor getExecutor() {
        if (this.executor != null) {
            return this.executor;
        } else if (this.executorName != null) {
            replacedert.state(this.beanFactory != null, "BeanFactory is required to look up an executor bean by name");
            return this.beanFactory.getBean(this.executorName, AsyncTaskExecutor.clreplaced);
        } else {
            return null;
        }
    }

    /**
     * Register code to invoke when the async request times out.
     * <p>This method is called from a container thread when an async request times
     * out before the {@code Callable} has completed. The callback is executed in
     * the same thread and therefore should return without blocking. It may return
     * an alternative value to use, including an {@link Exception} or return
     * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}.
     */
    public void onTimeout(Callable<V> callback) {
        this.timeoutCallback = callback;
    }

    /**
     * Register code to invoke for an error during async request processing.
     * <p>This method is called from a container thread when an error occurred
     * while processing an async request before the {@code Callable} has
     * completed. The callback is executed in the same thread and therefore
     * should return without blocking. It may return an alternative value to
     * use, including an {@link Exception} or return
     * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}.
     * @since 5.0
     */
    public void onError(Callable<V> callback) {
        this.errorCallback = callback;
    }

    /**
     * Register code to invoke when the async request completes.
     * <p>This method is called from a container thread when an async request
     * completed for any reason, including timeout and network error.
     */
    public void onCompletion(Runnable callback) {
        this.completionCallback = callback;
    }

    CallableProcessingInterceptor getInterceptor() {
        return new CallableProcessingInterceptor() {

            @Override
            public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
                return (timeoutCallback != null ? timeoutCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
            }

            @Override
            public <T> Object handleError(NativeWebRequest request, Callable<T> task, Throwable t) throws Exception {
                return (errorCallback != null ? errorCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
            }

            @Override
            public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
                if (completionCallback != null) {
                    completionCallback.run();
                }
            }
        };
    }
}

19 View Source File : WebAsyncManager.java
License : Apache License 2.0
Project Creator : SourceHot

/**
 * The central clreplaced for managing asynchronous request processing, mainly intended
 * as an SPI and not typically used directly by application clreplacedes.
 *
 * <p>An async scenario starts with request processing as usual in a thread (T1).
 * Concurrent request handling can be initiated by calling
 * {@link #startCallableProcessing(Callable, Object...) startCallableProcessing} or
 * {@link #startDeferredResultProcessing(DeferredResult, Object...) startDeferredResultProcessing},
 * both of which produce a result in a separate thread (T2). The result is saved
 * and the request dispatched to the container, to resume processing with the saved
 * result in a third thread (T3). Within the dispatched thread (T3), the saved
 * result can be accessed via {@link #getConcurrentResult()} or its presence
 * detected via {@link #hasConcurrentResult()}.
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @since 3.2
 * @see org.springframework.web.context.request.AsyncWebRequestInterceptor
 * @see org.springframework.web.servlet.AsyncHandlerInterceptor
 * @see org.springframework.web.filter.OncePerRequestFilter#shouldNotFilterAsyncDispatch
 * @see org.springframework.web.filter.OncePerRequestFilter#isAsyncDispatch
 */
public final clreplaced WebAsyncManager {

    private static final Object RESULT_NONE = new Object();

    private static final AsyncTaskExecutor DEFAULT_TASK_EXECUTOR = new SimpleAsyncTaskExecutor(WebAsyncManager.clreplaced.getSimpleName());

    private static final Log logger = LogFactory.getLog(WebAsyncManager.clreplaced);

    private static final CallableProcessingInterceptor timeoutCallableInterceptor = new TimeoutCallableProcessingInterceptor();

    private static final DeferredResultProcessingInterceptor timeoutDeferredResultInterceptor = new TimeoutDeferredResultProcessingInterceptor();

    private static Boolean taskExecutorWarning = true;

    private AsyncWebRequest asyncWebRequest;

    private AsyncTaskExecutor taskExecutor = DEFAULT_TASK_EXECUTOR;

    private volatile Object concurrentResult = RESULT_NONE;

    private volatile Object[] concurrentResultContext;

    private final Map<Object, CallableProcessingInterceptor> callableInterceptors = new LinkedHashMap<>();

    private final Map<Object, DeferredResultProcessingInterceptor> deferredResultInterceptors = new LinkedHashMap<>();

    /**
     * Package-private constructor.
     * @see WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
     * @see WebAsyncUtils#getAsyncManager(org.springframework.web.context.request.WebRequest)
     */
    WebAsyncManager() {
    }

    /**
     * Configure the {@link AsyncWebRequest} to use. This property may be set
     * more than once during a single request to accurately reflect the current
     * state of the request (e.g. following a forward, request/response
     * wrapping, etc). However, it should not be set while concurrent handling
     * is in progress, i.e. while {@link #isConcurrentHandlingStarted()} is
     * {@code true}.
     * @param asyncWebRequest the web request to use
     */
    public void setAsyncWebRequest(AsyncWebRequest asyncWebRequest) {
        replacedert.notNull(asyncWebRequest, "AsyncWebRequest must not be null");
        this.asyncWebRequest = asyncWebRequest;
        this.asyncWebRequest.addCompletionHandler(() -> asyncWebRequest.removeAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST));
    }

    /**
     * Configure an AsyncTaskExecutor for use with concurrent processing via
     * {@link #startCallableProcessing(Callable, Object...)}.
     * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used.
     */
    public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Whether the selected handler for the current request chose to handle the
     * request asynchronously. A return value of "true" indicates concurrent
     * handling is under way and the response will remain open. A return value
     * of "false" means concurrent handling was either not started or possibly
     * that it has completed and the request was dispatched for further
     * processing of the concurrent result.
     */
    public boolean isConcurrentHandlingStarted() {
        return (this.asyncWebRequest != null && this.asyncWebRequest.isAsyncStarted());
    }

    /**
     * Whether a result value exists as a result of concurrent handling.
     */
    public boolean hasConcurrentResult() {
        return (this.concurrentResult != RESULT_NONE);
    }

    /**
     * Provides access to the result from concurrent handling.
     * @return an Object, possibly an {@code Exception} or {@code Throwable} if
     * concurrent handling raised one.
     * @see #clearConcurrentResult()
     */
    public Object getConcurrentResult() {
        return this.concurrentResult;
    }

    /**
     * Provides access to additional processing context saved at the start of
     * concurrent handling.
     * @see #clearConcurrentResult()
     */
    public Object[] getConcurrentResultContext() {
        return this.concurrentResultContext;
    }

    /**
     * Get the {@link CallableProcessingInterceptor} registered under the given key.
     * @param key the key
     * @return the interceptor registered under that key, or {@code null} if none
     */
    @Nullable
    public CallableProcessingInterceptor getCallableInterceptor(Object key) {
        return this.callableInterceptors.get(key);
    }

    /**
     * Get the {@link DeferredResultProcessingInterceptor} registered under the given key.
     * @param key the key
     * @return the interceptor registered under that key, or {@code null} if none
     */
    @Nullable
    public DeferredResultProcessingInterceptor getDeferredResultInterceptor(Object key) {
        return this.deferredResultInterceptors.get(key);
    }

    /**
     * Register a {@link CallableProcessingInterceptor} under the given key.
     * @param key the key
     * @param interceptor the interceptor to register
     */
    public void registerCallableInterceptor(Object key, CallableProcessingInterceptor interceptor) {
        replacedert.notNull(key, "Key is required");
        replacedert.notNull(interceptor, "CallableProcessingInterceptor  is required");
        this.callableInterceptors.put(key, interceptor);
    }

    /**
     * Register a {@link CallableProcessingInterceptor} without a key.
     * The key is derived from the clreplaced name and hashcode.
     * @param interceptors one or more interceptors to register
     */
    public void registerCallableInterceptors(CallableProcessingInterceptor... interceptors) {
        replacedert.notNull(interceptors, "A CallableProcessingInterceptor is required");
        for (CallableProcessingInterceptor interceptor : interceptors) {
            String key = interceptor.getClreplaced().getName() + ":" + interceptor.hashCode();
            this.callableInterceptors.put(key, interceptor);
        }
    }

    /**
     * Register a {@link DeferredResultProcessingInterceptor} under the given key.
     * @param key the key
     * @param interceptor the interceptor to register
     */
    public void registerDeferredResultInterceptor(Object key, DeferredResultProcessingInterceptor interceptor) {
        replacedert.notNull(key, "Key is required");
        replacedert.notNull(interceptor, "DeferredResultProcessingInterceptor is required");
        this.deferredResultInterceptors.put(key, interceptor);
    }

    /**
     * Register one or more {@link DeferredResultProcessingInterceptor DeferredResultProcessingInterceptors} without a specified key.
     * The default key is derived from the interceptor clreplaced name and hash code.
     * @param interceptors one or more interceptors to register
     */
    public void registerDeferredResultInterceptors(DeferredResultProcessingInterceptor... interceptors) {
        replacedert.notNull(interceptors, "A DeferredResultProcessingInterceptor is required");
        for (DeferredResultProcessingInterceptor interceptor : interceptors) {
            String key = interceptor.getClreplaced().getName() + ":" + interceptor.hashCode();
            this.deferredResultInterceptors.put(key, interceptor);
        }
    }

    /**
     * Clear {@linkplain #getConcurrentResult() concurrentResult} and
     * {@linkplain #getConcurrentResultContext() concurrentResultContext}.
     */
    public void clearConcurrentResult() {
        synchronized (WebAsyncManager.this) {
            this.concurrentResult = RESULT_NONE;
            this.concurrentResultContext = null;
        }
    }

    /**
     * Start concurrent request processing and execute the given task with an
     * {@link #setTaskExecutor(AsyncTaskExecutor) AsyncTaskExecutor}. The result
     * from the task execution is saved and the request dispatched in order to
     * resume processing of that result. If the task raises an Exception then
     * the saved result will be the raised Exception.
     * @param callable a unit of work to be executed asynchronously
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     * @see #getConcurrentResult()
     * @see #getConcurrentResultContext()
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void startCallableProcessing(Callable<?> callable, Object... processingContext) throws Exception {
        replacedert.notNull(callable, "Callable must not be null");
        startCallableProcessing(new WebAsyncTask(callable), processingContext);
    }

    /**
     * Use the given {@link WebAsyncTask} to configure the task executor as well as
     * the timeout value of the {@code AsyncWebRequest} before delegating to
     * {@link #startCallableProcessing(Callable, Object...)}.
     * @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     */
    public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
        replacedert.notNull(webAsyncTask, "WebAsyncTask must not be null");
        replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
        Long timeout = webAsyncTask.getTimeout();
        if (timeout != null) {
            this.asyncWebRequest.setTimeout(timeout);
        }
        AsyncTaskExecutor executor = webAsyncTask.getExecutor();
        if (executor != null) {
            this.taskExecutor = executor;
        } else {
            logExecutorWarning();
        }
        List<CallableProcessingInterceptor> interceptors = new ArrayList<>();
        interceptors.add(webAsyncTask.getInterceptor());
        interceptors.addAll(this.callableInterceptors.values());
        interceptors.add(timeoutCallableInterceptor);
        final Callable<?> callable = webAsyncTask.getCallable();
        final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);
        this.asyncWebRequest.addTimeoutHandler(() -> {
            if (logger.isDebugEnabled()) {
                logger.debug("Async request timeout for " + formatRequestUri());
            }
            Object result = interceptorChain.triggerAfterTimeout(this.asyncWebRequest, callable);
            if (result != CallableProcessingInterceptor.RESULT_NONE) {
                setConcurrentResultAndDispatch(result);
            }
        });
        this.asyncWebRequest.addErrorHandler(ex -> {
            if (logger.isDebugEnabled()) {
                logger.debug("Async request error for " + formatRequestUri() + ": " + ex);
            }
            Object result = interceptorChain.triggerAfterError(this.asyncWebRequest, callable, ex);
            result = (result != CallableProcessingInterceptor.RESULT_NONE ? result : ex);
            setConcurrentResultAndDispatch(result);
        });
        this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, callable));
        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
        startAsyncProcessing(processingContext);
        try {
            Future<?> future = this.taskExecutor.submit(() -> {
                Object result = null;
                try {
                    interceptorChain.applyPreProcess(this.asyncWebRequest, callable);
                    result = callable.call();
                } catch (Throwable ex) {
                    result = ex;
                } finally {
                    result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, result);
                }
                setConcurrentResultAndDispatch(result);
            });
            interceptorChain.setTaskFuture(future);
        } catch (RejectedExecutionException ex) {
            Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
            setConcurrentResultAndDispatch(result);
            throw ex;
        }
    }

    private void logExecutorWarning() {
        if (taskExecutorWarning && logger.isWarnEnabled()) {
            synchronized (DEFAULT_TASK_EXECUTOR) {
                AsyncTaskExecutor executor = this.taskExecutor;
                if (taskExecutorWarning && (executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor)) {
                    String executorTypeName = executor.getClreplaced().getSimpleName();
                    logger.warn("\n!!!\n" + "An Executor is required to handle java.util.concurrent.Callable return values.\n" + "Please, configure a TaskExecutor in the MVC config under \"async support\".\n" + "The " + executorTypeName + " currently in use is not suitable under load.\n" + "-------------------------------\n" + "Request URI: '" + formatRequestUri() + "'\n" + "!!!");
                    taskExecutorWarning = false;
                }
            }
        }
    }

    private String formatRequestUri() {
        HttpServletRequest request = this.asyncWebRequest.getNativeRequest(HttpServletRequest.clreplaced);
        return request != null ? request.getRequestURI() : "servlet container";
    }

    private void setConcurrentResultAndDispatch(Object result) {
        synchronized (WebAsyncManager.this) {
            if (this.concurrentResult != RESULT_NONE) {
                return;
            }
            this.concurrentResult = result;
        }
        if (this.asyncWebRequest.isAsyncComplete()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Async result set but request already complete: " + formatRequestUri());
            }
            return;
        }
        if (logger.isDebugEnabled()) {
            boolean isError = result instanceof Throwable;
            logger.debug("Async " + (isError ? "error" : "result set") + ", dispatch to " + formatRequestUri());
        }
        this.asyncWebRequest.dispatch();
    }

    /**
     * Start concurrent request processing and initialize the given
     * {@link DeferredResult} with a {@link DeferredResultHandler} that saves
     * the result and dispatches the request to resume processing of that
     * result. The {@code AsyncWebRequest} is also updated with a completion
     * handler that expires the {@code DeferredResult} and a timeout handler
     * replaceduming the {@code DeferredResult} has a default timeout result.
     * @param deferredResult the DeferredResult instance to initialize
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     * @see #getConcurrentResult()
     * @see #getConcurrentResultContext()
     */
    public void startDeferredResultProcessing(final DeferredResult<?> deferredResult, Object... processingContext) throws Exception {
        replacedert.notNull(deferredResult, "DeferredResult must not be null");
        replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
        Long timeout = deferredResult.getTimeoutValue();
        if (timeout != null) {
            this.asyncWebRequest.setTimeout(timeout);
        }
        List<DeferredResultProcessingInterceptor> interceptors = new ArrayList<>();
        interceptors.add(deferredResult.getInterceptor());
        interceptors.addAll(this.deferredResultInterceptors.values());
        interceptors.add(timeoutDeferredResultInterceptor);
        final DeferredResultInterceptorChain interceptorChain = new DeferredResultInterceptorChain(interceptors);
        this.asyncWebRequest.addTimeoutHandler(() -> {
            try {
                interceptorChain.triggerAfterTimeout(this.asyncWebRequest, deferredResult);
            } catch (Throwable ex) {
                setConcurrentResultAndDispatch(ex);
            }
        });
        this.asyncWebRequest.addErrorHandler(ex -> {
            try {
                if (!interceptorChain.triggerAfterError(this.asyncWebRequest, deferredResult, ex)) {
                    return;
                }
                deferredResult.setErrorResult(ex);
            } catch (Throwable interceptorEx) {
                setConcurrentResultAndDispatch(interceptorEx);
            }
        });
        this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, deferredResult));
        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
        startAsyncProcessing(processingContext);
        try {
            interceptorChain.applyPreProcess(this.asyncWebRequest, deferredResult);
            deferredResult.setResultHandler(result -> {
                result = interceptorChain.applyPostProcess(this.asyncWebRequest, deferredResult, result);
                setConcurrentResultAndDispatch(result);
            });
        } catch (Throwable ex) {
            setConcurrentResultAndDispatch(ex);
        }
    }

    private void startAsyncProcessing(Object[] processingContext) {
        synchronized (WebAsyncManager.this) {
            this.concurrentResult = RESULT_NONE;
            this.concurrentResultContext = processingContext;
        }
        this.asyncWebRequest.startAsync();
        if (logger.isDebugEnabled()) {
            logger.debug("Started async request");
        }
    }
}

19 View Source File : WebAsyncManager.java
License : Apache License 2.0
Project Creator : SourceHot

/**
 * Use the given {@link WebAsyncTask} to configure the task executor as well as
 * the timeout value of the {@code AsyncWebRequest} before delegating to
 * {@link #startCallableProcessing(Callable, Object...)}.
 * @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
 * @param processingContext additional context to save that can be accessed
 * via {@link #getConcurrentResultContext()}
 * @throws Exception if concurrent processing failed to start
 */
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
    replacedert.notNull(webAsyncTask, "WebAsyncTask must not be null");
    replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
    Long timeout = webAsyncTask.getTimeout();
    if (timeout != null) {
        this.asyncWebRequest.setTimeout(timeout);
    }
    AsyncTaskExecutor executor = webAsyncTask.getExecutor();
    if (executor != null) {
        this.taskExecutor = executor;
    } else {
        logExecutorWarning();
    }
    List<CallableProcessingInterceptor> interceptors = new ArrayList<>();
    interceptors.add(webAsyncTask.getInterceptor());
    interceptors.addAll(this.callableInterceptors.values());
    interceptors.add(timeoutCallableInterceptor);
    final Callable<?> callable = webAsyncTask.getCallable();
    final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);
    this.asyncWebRequest.addTimeoutHandler(() -> {
        if (logger.isDebugEnabled()) {
            logger.debug("Async request timeout for " + formatRequestUri());
        }
        Object result = interceptorChain.triggerAfterTimeout(this.asyncWebRequest, callable);
        if (result != CallableProcessingInterceptor.RESULT_NONE) {
            setConcurrentResultAndDispatch(result);
        }
    });
    this.asyncWebRequest.addErrorHandler(ex -> {
        if (logger.isDebugEnabled()) {
            logger.debug("Async request error for " + formatRequestUri() + ": " + ex);
        }
        Object result = interceptorChain.triggerAfterError(this.asyncWebRequest, callable, ex);
        result = (result != CallableProcessingInterceptor.RESULT_NONE ? result : ex);
        setConcurrentResultAndDispatch(result);
    });
    this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, callable));
    interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
    startAsyncProcessing(processingContext);
    try {
        Future<?> future = this.taskExecutor.submit(() -> {
            Object result = null;
            try {
                interceptorChain.applyPreProcess(this.asyncWebRequest, callable);
                result = callable.call();
            } catch (Throwable ex) {
                result = ex;
            } finally {
                result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, result);
            }
            setConcurrentResultAndDispatch(result);
        });
        interceptorChain.setTaskFuture(future);
    } catch (RejectedExecutionException ex) {
        Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
        setConcurrentResultAndDispatch(result);
        throw ex;
    }
}

19 View Source File : WebAsyncManager.java
License : Apache License 2.0
Project Creator : SourceHot

private void logExecutorWarning() {
    if (taskExecutorWarning && logger.isWarnEnabled()) {
        synchronized (DEFAULT_TASK_EXECUTOR) {
            AsyncTaskExecutor executor = this.taskExecutor;
            if (taskExecutorWarning && (executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor)) {
                String executorTypeName = executor.getClreplaced().getSimpleName();
                logger.warn("\n!!!\n" + "An Executor is required to handle java.util.concurrent.Callable return values.\n" + "Please, configure a TaskExecutor in the MVC config under \"async support\".\n" + "The " + executorTypeName + " currently in use is not suitable under load.\n" + "-------------------------------\n" + "Request URI: '" + formatRequestUri() + "'\n" + "!!!");
                taskExecutorWarning = false;
            }
        }
    }
}

19 View Source File : SimpleRqueueListenerContainerFactoryTest.java
License : Apache License 2.0
Project Creator : sonus21

@CoreUnitTest
clreplaced SimpleRqueueListenerContainerFactoryTest extends TestBase {

    private final AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();

    private SimpleRqueueListenerContainerFactory simpleRqueueListenerContainerFactory;

    @BeforeEach
    void init() {
        simpleRqueueListenerContainerFactory = new SimpleRqueueListenerContainerFactory();
    }

    @Test
    void setTaskExecutor() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setTaskExecutor(null));
    }

    @Test
    void setAndGetTaskExecutor() {
        simpleRqueueListenerContainerFactory.setTaskExecutor(taskExecutor);
        replacedertNotNull(simpleRqueueListenerContainerFactory.getTaskExecutor());
    }

    @Test
    void setAutoStartup() {
        simpleRqueueListenerContainerFactory.setAutoStartup(false);
        replacedertFalse(simpleRqueueListenerContainerFactory.getAutoStartup());
    }

    @Test
    void getAutoStartup() {
        replacedertTrue(simpleRqueueListenerContainerFactory.getAutoStartup());
    }

    @Test
    void setRqueueMessageHandler() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setRqueueMessageHandler(null));
    }

    @Test
    void getRqueueMessageHandler() {
        replacedertNotNull(simpleRqueueListenerContainerFactory.getRqueueMessageHandler());
    }

    @Test
    void getBackOffTime() {
        replacedertEquals(5000L, simpleRqueueListenerContainerFactory.getBackOffTime());
    }

    @Test
    void setBackOffTime() {
        long backOffTime = 1000L;
        simpleRqueueListenerContainerFactory.setBackOffTime(backOffTime);
        replacedertEquals(backOffTime, simpleRqueueListenerContainerFactory.getBackOffTime());
    }

    @Test
    void setMaxNumWorkers() {
        Integer maxWorkers = 10;
        simpleRqueueListenerContainerFactory.setMaxNumWorkers(maxWorkers);
        replacedertEquals(maxWorkers, simpleRqueueListenerContainerFactory.getMaxNumWorkers());
    }

    @Test
    void setMessageConverters() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setMessageConverters(null));
    }

    @Test
    void setMessageConverters1() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setMessageConverters(new ArrayList<>()));
    }

    @Test
    void getMessageConverter() {
        replacedertNotNull(simpleRqueueListenerContainerFactory.getMessageConverter());
    }

    @Test
    void setRedisConnectionFactory() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setRedisConnectionFactory(null));
    }

    @Test
    void getRedisConnectionFactory() {
        replacedertNull(simpleRqueueListenerContainerFactory.getRedisConnectionFactory());
    }

    @Test
    void setRqueueMessageTemplate() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setRqueueMessageTemplate(null));
    }

    @Test
    void getRqueueMessageTemplate() {
        replacedertNull(simpleRqueueListenerContainerFactory.getRqueueMessageTemplate());
    }

    @Test
    void createMessageListenerContainer0() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.createMessageListenerContainer());
    }

    @Test
    void createMessageListenerContainer1() {
        simpleRqueueListenerContainerFactory.setRqueueMessageHandler(new RqueueMessageHandler(new DefaultRqueueMessageConverter()));
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.createMessageListenerContainer());
    }

    @Test
    void createMessageListenerContainer3() {
        simpleRqueueListenerContainerFactory.setRedisConnectionFactory(new LettuceConnectionFactory());
        simpleRqueueListenerContainerFactory.setRqueueMessageHandler(new RqueueMessageHandler(new DefaultRqueueMessageConverter()));
        RqueueMessageListenerContainer container = simpleRqueueListenerContainerFactory.createMessageListenerContainer();
        replacedertNotNull(container);
        replacedertNotNull(container.getRqueueMessageHandler());
        replacedertTrue(container.isAutoStartup());
        replacedertNotNull(simpleRqueueListenerContainerFactory.getRqueueMessageTemplate());
    }

    @Test
    void deadLetterMessageProcessor() {
        MessageProcessor messageProcessor = new MessageProcessor() {
        };
        simpleRqueueListenerContainerFactory.setDeadLetterQueueMessageProcessor(messageProcessor);
        replacedertEquals(messageProcessor, simpleRqueueListenerContainerFactory.getDeadLetterQueueMessageProcessor());
        simpleRqueueListenerContainerFactory.setRedisConnectionFactory(new LettuceConnectionFactory());
        simpleRqueueListenerContainerFactory.setRqueueMessageHandler(new RqueueMessageHandler(new DefaultRqueueMessageConverter()));
        RqueueMessageListenerContainer container = simpleRqueueListenerContainerFactory.createMessageListenerContainer();
        replacedertNotNull(container);
        replacedertEquals(messageProcessor, container.getDeadLetterQueueMessageProcessor());
    }

    @Test
    void discardMessageProcessorNull() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setDiscardMessageProcessor(null));
    }

    @Test
    void discardMessageProcessor() {
        MessageProcessor messageProcessor = new MessageProcessor() {
        };
        simpleRqueueListenerContainerFactory.setDiscardMessageProcessor(messageProcessor);
        replacedertEquals(messageProcessor, simpleRqueueListenerContainerFactory.getDiscardMessageProcessor());
        simpleRqueueListenerContainerFactory.setRedisConnectionFactory(new LettuceConnectionFactory());
        simpleRqueueListenerContainerFactory.setRqueueMessageHandler(new RqueueMessageHandler(new DefaultRqueueMessageConverter()));
        RqueueMessageListenerContainer container = simpleRqueueListenerContainerFactory.createMessageListenerContainer();
        replacedertNotNull(container);
        replacedertEquals(messageProcessor, container.getDiscardMessageProcessor());
    }

    @Test
    void getTaskExecutionBackOff() {
        replacedertNull(simpleRqueueListenerContainerFactory.getTaskExecutionBackOff());
    }

    @Test
    void setNullTaskExecutionBackOff() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setTaskExecutionBackOff(null));
    }

    @Test
    void setTaskExecutionBackOff() {
        FixedTaskExecutionBackOff backOff = new FixedTaskExecutionBackOff(10000L, 10);
        simpleRqueueListenerContainerFactory.setTaskExecutionBackOff(backOff);
        replacedertEquals(backOff, simpleRqueueListenerContainerFactory.getTaskExecutionBackOff());
    }

    @Test
    void getPriorityMode() {
        replacedertNull(simpleRqueueListenerContainerFactory.getPriorityMode());
    }

    @Test
    void setPriorityMode() {
        simpleRqueueListenerContainerFactory.setPriorityMode(PriorityMode.STRICT);
        replacedertEquals(PriorityMode.STRICT, simpleRqueueListenerContainerFactory.getPriorityMode());
    }

    @Test
    void setPollingInterval() {
        simpleRqueueListenerContainerFactory.setPollingInterval(1000L);
        replacedertEquals(1000L, simpleRqueueListenerContainerFactory.getPollingInterval());
    }

    @Test
    void setNullPreExecutionMessageProcessor() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setPreExecutionMessageProcessor(null));
    }

    @Test
    void setPreExecutionMessageProcessor() {
        MessageProcessor messageProcessor = new MessageProcessor() {
        };
        simpleRqueueListenerContainerFactory.setPreExecutionMessageProcessor(messageProcessor);
        replacedertEquals(messageProcessor.hashCode(), simpleRqueueListenerContainerFactory.getPreExecutionMessageProcessor().hashCode());
    }

    @Test
    void setNullPostExecutionMessageProcessor() {
        replacedertThrows(IllegalArgumentException.clreplaced, () -> simpleRqueueListenerContainerFactory.setPostExecutionMessageProcessor(null));
    }

    @Test
    void setPostExecutionMessageProcessor() {
        MessageProcessor messageProcessor = new MessageProcessor() {
        };
        simpleRqueueListenerContainerFactory.setPostExecutionMessageProcessor(messageProcessor);
        replacedertEquals(messageProcessor.hashCode(), simpleRqueueListenerContainerFactory.getPostExecutionMessageProcessor().hashCode());
    }

    @Test
    void createContainer() {
        MessageProcessor pre = new MessageProcessor() {
        };
        MessageProcessor post = new MessageProcessor() {
        };
        MessageProcessor deadLetter = new MessageProcessor() {
        };
        MessageProcessor deletion = new MessageProcessor() {
        };
        MessageProcessor discardMessageProcessor = new MessageProcessor() {
        };
        TaskExecutionBackOff backOff = new FixedTaskExecutionBackOff(1000L, 4);
        AsyncTaskExecutor executor = new TestAsyncTaskExecutor();
        simpleRqueueListenerContainerFactory.setPostExecutionMessageProcessor(post);
        simpleRqueueListenerContainerFactory.setPreExecutionMessageProcessor(pre);
        simpleRqueueListenerContainerFactory.setDeadLetterQueueMessageProcessor(deadLetter);
        simpleRqueueListenerContainerFactory.setManualDeletionMessageProcessor(deletion);
        simpleRqueueListenerContainerFactory.setDiscardMessageProcessor(discardMessageProcessor);
        simpleRqueueListenerContainerFactory.setRedisConnectionFactory(new LettuceConnectionFactory());
        simpleRqueueListenerContainerFactory.setRqueueMessageHandler(new RqueueMessageHandler(new DefaultRqueueMessageConverter()));
        simpleRqueueListenerContainerFactory.setTaskExecutionBackOff(backOff);
        simpleRqueueListenerContainerFactory.setTaskExecutor(executor);
        simpleRqueueListenerContainerFactory.setPriorityMode(PriorityMode.WEIGHTED);
        RqueueMessageListenerContainer container = simpleRqueueListenerContainerFactory.createMessageListenerContainer();
        replacedertNotNull(container);
        replacedertEquals(PriorityMode.WEIGHTED, container.getPriorityMode());
        replacedertEquals(backOff, container.getTaskExecutionBackOff());
        replacedertEquals(executor, container.getTaskExecutor());
        replacedertEquals(pre, container.getPreExecutionMessageProcessor());
        replacedertEquals(post, container.getPostExecutionMessageProcessor());
        replacedertEquals(deadLetter, container.getDeadLetterQueueMessageProcessor());
        replacedertEquals(deletion, container.getManualDeletionMessageProcessor());
        replacedertEquals(discardMessageProcessor, container.getDiscardMessageProcessor());
    }

    private clreplaced TestAsyncTaskExecutor implements AsyncTaskExecutor {

        @Override
        public void execute(Runnable task, long startTimeout) {
        }

        @Override
        public Future<?> submit(Runnable task) {
            return null;
        }

        @Override
        public <T> Future<T> submit(Callable<T> task) {
            return null;
        }

        @Override
        public void execute(Runnable task) {
        }
    }
}

19 View Source File : RqueueMessageListenerContainer.java
License : Apache License 2.0
Project Creator : sonus21

public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

19 View Source File : RqueueMessageListenerContainer.java
License : Apache License 2.0
Project Creator : sonus21

private AsyncTaskExecutor createNonConcurrencyBasedExecutor(List<QueueDetail> queueDetails, int pollerCount) {
    int workersCount = getWorkersCount(queueDetails.size());
    int maxPoolSize = workersCount + pollerCount;
    // one thread for message poller and one for executor
    int corePoolSize = queueDetails.size() + pollerCount;
    AsyncTaskExecutor executor = createTaskExecutor(corePoolSize, maxPoolSize);
    initializeThreadMap(queueDetails, executor, true, workersCount);
    return executor;
}

19 View Source File : RqueueMessageListenerContainer.java
License : Apache License 2.0
Project Creator : sonus21

private void initializeThreadMap(List<QueueDetail> queueDetails, AsyncTaskExecutor taskExecutor, boolean defaultExecutor, int workersCount) {
    Semapreplaced semapreplaced = new Semapreplaced(workersCount);
    for (QueueDetail queueDetail : queueDetails) {
        queueThreadMap.put(queueDetail.getName(), new QueueThread(defaultExecutor, taskExecutor, semapreplaced, workersCount));
    }
}

19 View Source File : RqueueMessageListenerContainer.java
License : Apache License 2.0
Project Creator : sonus21

private void createExecutor(QueueDetail queueDetail) {
    Concurrency concurrency = queueDetail.getConcurrency();
    AsyncTaskExecutor executor = createTaskExecutor(queueDetail, concurrency.getMin(), concurrency.getMax());
    Semapreplaced semapreplaced = new Semapreplaced(concurrency.getMax());
    queueThreadMap.put(queueDetail.getName(), new QueueThread(true, executor, semapreplaced, concurrency.getMax()));
}

19 View Source File : SimpleRqueueListenerContainerFactory.java
License : Apache License 2.0
Project Creator : sonus21

/**
 * Configures the {@link TaskExecutor} which is used to poll messages and execute them by calling
 * the handler methods. If no {@link TaskExecutor} is set, a default one is created. If you're
 * setting this then you should set {@link #maxNumWorkers}.
 *
 * @param taskExecutor The {@link TaskExecutor} used by the container.
 * @see RqueueMessageListenerContainer#createDefaultTaskExecutor(List)
 * @see #setMaxNumWorkers(int)
 */
public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    notNull(taskExecutor, "taskExecutor cannot be null");
    this.taskExecutor = taskExecutor;
}

19 View Source File : AsyncTask.java
License : MIT License
Project Creator : PacktPublishing

public clreplaced AsyncTask {

    @Autowired
    private AsyncTaskExecutor executor;

    public void runTasks() throws Exception {
        for (int i = 1; i <= 5; i++) {
            Runnable task = new Task(" " + i);
            executor.execute(task);
        }
    }
}

19 View Source File : ExceptionHandlingAsyncTaskExecutor.java
License : Apache License 2.0
Project Creator : paascloud

/**
 * The clreplaced Exception handling async task executor.
 *
 * @author paascloud.net @gmail.com
 */
@Slf4j
public clreplaced ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor, InitializingBean, DisposableBean {

    private final AsyncTaskExecutor executor;

    /**
     * Instantiates a new Exception handling async task executor.
     *
     * @param executor the executor
     */
    ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) {
        this.executor = executor;
    }

    /**
     * Execute.
     *
     * @param task the task
     */
    @Override
    public void execute(Runnable task) {
        executor.execute(createWrappedRunnable(task));
    }

    /**
     * Execute.
     *
     * @param task         the task
     * @param startTimeout the start timeout
     */
    @Override
    public void execute(Runnable task, long startTimeout) {
        executor.execute(createWrappedRunnable(task), startTimeout);
    }

    private <T> Callable<T> createCallable(final Callable<T> task) {
        return () -> {
            try {
                return task.call();
            } catch (Exception e) {
                handle(e);
                throw e;
            }
        };
    }

    private Runnable createWrappedRunnable(final Runnable task) {
        return () -> {
            try {
                task.run();
            } catch (Exception e) {
                handle(e);
            }
        };
    }

    /**
     * Handle.
     *
     * @param e the e
     */
    private void handle(Exception e) {
        log.error("Caught async exception", e);
    }

    /**
     * Submit future.
     *
     * @param task the task
     *
     * @return the future
     */
    @Override
    public Future<?> submit(Runnable task) {
        return executor.submit(createWrappedRunnable(task));
    }

    /**
     * Submit future.
     *
     * @param <T>  the type parameter
     * @param task the task
     *
     * @return the future
     */
    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return executor.submit(createCallable(task));
    }

    /**
     * Destroy.
     *
     * @throws Exception the exception
     */
    @Override
    public void destroy() throws Exception {
        if (executor instanceof DisposableBean) {
            DisposableBean bean = (DisposableBean) executor;
            bean.destroy();
        }
    }

    /**
     * After properties set.
     *
     * @throws Exception the exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        if (executor instanceof InitializingBean) {
            InitializingBean bean = (InitializingBean) executor;
            bean.afterPropertiesSet();
        }
    }
}

19 View Source File : RestifyAsyncConfiguration.java
License : MIT License
Project Creator : ljtfreitas

@Conditional(RestifyAsyncConfiguration.RestifyAsyncExecutorServiceCondition.clreplaced)
@Bean(name = Async.EXECUTOR_SERVICE_BEAN_NAME)
@Async
public ExecutorService restifyAsyncExecutorService(@Async AsyncTaskExecutor executor) {
    return new ExecutorServiceAdapter(executor);
}

19 View Source File : RestifyAsyncConfiguration.java
License : MIT License
Project Creator : ljtfreitas

@ConditionalOnMissingBean
@Bean
public DeferredResultEndpointCallHandlerAdapter<Object, Object> deferredResultEndpointCallHandlerAdapter(@Async AsyncTaskExecutor executor, RestifyConfigurationProperties properties) {
    return new DeferredResultEndpointCallHandlerAdapter<>(executor, properties.getAsync().getTimeout());
}

19 View Source File : RestifyAsyncConfiguration.java
License : MIT License
Project Creator : ljtfreitas

@ConditionalOnMissingBean
@Bean
public WebAsyncTaskEndpointCallHandlerAdapter<Object, Object> webAsyncTaskEndpointCallHandlerAdapter(@Async AsyncTaskExecutor executor, RestifyConfigurationProperties properties) {
    return new WebAsyncTaskEndpointCallHandlerAdapter<>(properties.getAsync().getTimeout(), executor);
}

19 View Source File : RestifyAsyncConfiguration.java
License : MIT License
Project Creator : ljtfreitas

@ConditionalOnMissingBean
@Bean
public AsyncResultEndpointCallHandlerAdapter<Object, Object> asyncResultEndpointCallHandlerAdapter(@Async AsyncTaskExecutor executor) {
    return new AsyncResultEndpointCallHandlerAdapter<>(executor);
}

19 View Source File : WebAsyncTaskEndpointCallHandlerAdapter.java
License : MIT License
Project Creator : ljtfreitas

public clreplaced WebAsyncTaskEndpointCallHandlerAdapter<T, O> implements EndpointCallHandlerAdapter<WebAsyncTask<T>, T, O> {

    private final Long timeout;

    private final AsyncTaskExecutor asyncTaskExecutor;

    public WebAsyncTaskEndpointCallHandlerAdapter() {
        this(new SimpleAsyncTaskExecutor());
    }

    public WebAsyncTaskEndpointCallHandlerAdapter(AsyncTaskExecutor asyncTaskExecutor) {
        this(null, asyncTaskExecutor);
    }

    public WebAsyncTaskEndpointCallHandlerAdapter(Long timeout) {
        this(timeout, new SimpleAsyncTaskExecutor());
    }

    public WebAsyncTaskEndpointCallHandlerAdapter(Long timeout, AsyncTaskExecutor asyncTaskExecutor) {
        this.timeout = timeout;
        this.asyncTaskExecutor = asyncTaskExecutor;
    }

    @Override
    public boolean supports(EndpointMethod endpointMethod) {
        return endpointMethod.returnType().is(WebAsyncTask.clreplaced);
    }

    @Override
    public JavaType returnType(EndpointMethod endpointMethod) {
        return JavaType.of(unwrap(endpointMethod.returnType()));
    }

    private Type unwrap(JavaType declaredReturnType) {
        return declaredReturnType.parameterized() ? declaredReturnType.as(ParameterizedType.clreplaced).getActualTypeArguments()[0] : Object.clreplaced;
    }

    @Override
    public EndpointCallHandler<WebAsyncTask<T>, O> adapt(EndpointMethod endpointMethod, EndpointCallHandler<T, O> handler) {
        return new WebAsyncTaskEndpointCallHandler(handler);
    }

    private clreplaced WebAsyncTaskEndpointCallHandler implements EndpointCallHandler<WebAsyncTask<T>, O> {

        private final EndpointCallHandler<T, O> delegate;

        public WebAsyncTaskEndpointCallHandler(EndpointCallHandler<T, O> handler) {
            this.delegate = handler;
        }

        @Override
        public JavaType returnType() {
            return delegate.returnType();
        }

        @Override
        public WebAsyncTask<T> handle(EndpointCall<O> call, Object[] args) {
            return new WebAsyncTask<T>(timeout, asyncTaskExecutor, () -> delegate.handle(call, args));
        }
    }
}

19 View Source File : AsyncSupportConfigurer.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Set the default {@link AsyncTaskExecutor} to use when a controller method
 * returns a {@link Callable}. Controller methods can override this default on
 * a per-request basis by returning a {@link WebAsyncTask}.
 *
 * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used, and it's
 * highly recommended to change that default in production since the simple
 * executor does not re-use threads.
 *
 * @param taskExecutor the task executor instance to use by default
 */
public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
    return this;
}

19 View Source File : WebAsyncManagerTimeoutTests.java
License : Apache License 2.0
Project Creator : langtianya

@Before
public void setUp() {
    this.servletRequest = new MockHttpServletRequest("GET", "/test");
    this.servletRequest.setAsyncSupported(true);
    this.servletResponse = new MockHttpServletResponse();
    this.asyncWebRequest = new StandardServletAsyncWebRequest(servletRequest, servletResponse);
    AsyncTaskExecutor executor = mock(AsyncTaskExecutor.clreplaced);
    this.asyncManager = WebAsyncUtils.getAsyncManager(servletRequest);
    this.asyncManager.setTaskExecutor(executor);
    this.asyncManager.setAsyncWebRequest(this.asyncWebRequest);
}

19 View Source File : WebAsyncManagerTests.java
License : Apache License 2.0
Project Creator : langtianya

@Test
public void startCallableProcessingWithAsyncTask() throws Exception {
    AsyncTaskExecutor executor = mock(AsyncTaskExecutor.clreplaced);
    given(this.asyncWebRequest.getNativeRequest(HttpServletRequest.clreplaced)).willReturn(this.servletRequest);
    @SuppressWarnings("unchecked")
    WebAsyncTask<Object> asyncTask = new WebAsyncTask<Object>(1000L, executor, mock(Callable.clreplaced));
    this.asyncManager.startCallableProcessing(asyncTask);
    verify(executor).submit((Runnable) notNull());
    verify(this.asyncWebRequest).setTimeout(1000L);
    verify(this.asyncWebRequest).addTimeoutHandler(any(Runnable.clreplaced));
    verify(this.asyncWebRequest).addCompletionHandler(any(Runnable.clreplaced));
    verify(this.asyncWebRequest).startAsync();
}

19 View Source File : WebAsyncTask.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Holder for a {@link Callable}, a timeout value, and a task executor.
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @since 3.2
 */
public clreplaced WebAsyncTask<V> implements BeanFactoryAware {

    private final Callable<V> callable;

    private Long timeout;

    private AsyncTaskExecutor executor;

    private String executorName;

    private BeanFactory beanFactory;

    private Callable<V> timeoutCallback;

    private Runnable completionCallback;

    /**
     * Create a {@code WebAsyncTask} wrapping the given {@link Callable}.
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(Callable<V> callable) {
        replacedert.notNull(callable, "Callable must not be null");
        this.callable = callable;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value and a {@link Callable}.
     * @param timeout a timeout value in milliseconds
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(long timeout, Callable<V> callable) {
        this(callable);
        this.timeout = timeout;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value, an executor name, and a {@link Callable}.
     * @param timeout timeout value in milliseconds; ignored if {@code null}
     * @param executorName the name of an executor bean to use
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(Long timeout, String executorName, Callable<V> callable) {
        this(callable);
        replacedert.notNull(executorName, "Executor name must not be null");
        this.executorName = executorName;
        this.timeout = timeout;
    }

    /**
     * Create a {@code WebAsyncTask} with a timeout value, an executor instance, and a Callable.
     * @param timeout timeout value in milliseconds; ignored if {@code null}
     * @param executor the executor to use
     * @param callable the callable for concurrent handling
     */
    public WebAsyncTask(Long timeout, AsyncTaskExecutor executor, Callable<V> callable) {
        this(callable);
        replacedert.notNull(executor, "Executor must not be null");
        this.executor = executor;
        this.timeout = timeout;
    }

    /**
     * Return the {@link Callable} to use for concurrent handling (never {@code null}).
     */
    public Callable<?> getCallable() {
        return this.callable;
    }

    /**
     * Return the timeout value in milliseconds, or {@code null} if no timeout is set.
     */
    public Long getTimeout() {
        return this.timeout;
    }

    /**
     * A {@link BeanFactory} to use for resolving an executor name.
     * <p>This factory reference will automatically be set when
     * {@code WebAsyncTask} is used within a Spring MVC controller.
     */
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    /**
     * Return the AsyncTaskExecutor to use for concurrent handling,
     * or {@code null} if none specified.
     */
    public AsyncTaskExecutor getExecutor() {
        if (this.executor != null) {
            return this.executor;
        } else if (this.executorName != null) {
            replacedert.state(this.beanFactory != null, "BeanFactory is required to look up an executor bean by name");
            return this.beanFactory.getBean(this.executorName, AsyncTaskExecutor.clreplaced);
        } else {
            return null;
        }
    }

    /**
     * Register code to invoke when the async request times out.
     * <p>This method is called from a container thread when an async request times
     * out before the {@code Callable} has completed. The callback is executed in
     * the same thread and therefore should return without blocking. It may return
     * an alternative value to use, including an {@link Exception} or return
     * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}.
     */
    public void onTimeout(Callable<V> callback) {
        this.timeoutCallback = callback;
    }

    /**
     * Register code to invoke when the async request completes.
     * <p>This method is called from a container thread when an async request
     * completed for any reason, including timeout and network error.
     */
    public void onCompletion(Runnable callback) {
        this.completionCallback = callback;
    }

    CallableProcessingInterceptor getInterceptor() {
        return new CallableProcessingInterceptorAdapter() {

            @Override
            public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
                return (timeoutCallback != null ? timeoutCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
            }

            @Override
            public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
                if (completionCallback != null) {
                    completionCallback.run();
                }
            }
        };
    }
}

19 View Source File : WebAsyncManager.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * The central clreplaced for managing asynchronous request processing, mainly intended
 * as an SPI and not typically used directly by application clreplacedes.
 *
 * <p>An async scenario starts with request processing as usual in a thread (T1).
 * Concurrent request handling can be initiated by calling
 * {@link #startCallableProcessing(Callable, Object...) startCallableProcessing} or
 * {@link #startDeferredResultProcessing(DeferredResult, Object...) startDeferredResultProcessing},
 * both of which produce a result in a separate thread (T2). The result is saved
 * and the request dispatched to the container, to resume processing with the saved
 * result in a third thread (T3). Within the dispatched thread (T3), the saved
 * result can be accessed via {@link #getConcurrentResult()} or its presence
 * detected via {@link #hasConcurrentResult()}.
 *
 * @author Rossen Stoyanchev
 * @since 3.2
 * @see org.springframework.web.context.request.AsyncWebRequestInterceptor
 * @see org.springframework.web.servlet.AsyncHandlerInterceptor
 * @see org.springframework.web.filter.OncePerRequestFilter#shouldNotFilterAsyncDispatch
 * @see org.springframework.web.filter.OncePerRequestFilter#isAsyncDispatch
 */
public final clreplaced WebAsyncManager {

    private static final Object RESULT_NONE = new Object();

    private static final Log logger = LogFactory.getLog(WebAsyncManager.clreplaced);

    private static final UrlPathHelper urlPathHelper = new UrlPathHelper();

    private static final CallableProcessingInterceptor timeoutCallableInterceptor = new TimeoutCallableProcessingInterceptor();

    private static final DeferredResultProcessingInterceptor timeoutDeferredResultInterceptor = new TimeoutDeferredResultProcessingInterceptor();

    private AsyncWebRequest asyncWebRequest;

    private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(this.getClreplaced().getSimpleName());

    private Object concurrentResult = RESULT_NONE;

    private Object[] concurrentResultContext;

    private final Map<Object, CallableProcessingInterceptor> callableInterceptors = new LinkedHashMap<Object, CallableProcessingInterceptor>();

    private final Map<Object, DeferredResultProcessingInterceptor> deferredResultInterceptors = new LinkedHashMap<Object, DeferredResultProcessingInterceptor>();

    /**
     * Package-private constructor.
     * @see WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
     * @see WebAsyncUtils#getAsyncManager(org.springframework.web.context.request.WebRequest)
     */
    WebAsyncManager() {
    }

    /**
     * Configure the {@link AsyncWebRequest} to use. This property may be set
     * more than once during a single request to accurately reflect the current
     * state of the request (e.g. following a forward, request/response
     * wrapping, etc). However, it should not be set while concurrent handling
     * is in progress, i.e. while {@link #isConcurrentHandlingStarted()} is
     * {@code true}.
     * @param asyncWebRequest the web request to use
     */
    public void setAsyncWebRequest(final AsyncWebRequest asyncWebRequest) {
        replacedert.notNull(asyncWebRequest, "AsyncWebRequest must not be null");
        replacedert.state(!isConcurrentHandlingStarted(), "Can't set AsyncWebRequest with concurrent handling in progress");
        this.asyncWebRequest = asyncWebRequest;
        this.asyncWebRequest.addCompletionHandler(new Runnable() {

            @Override
            public void run() {
                asyncWebRequest.removeAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
            }
        });
    }

    /**
     * Configure an AsyncTaskExecutor for use with concurrent processing via
     * {@link #startCallableProcessing(Callable, Object...)}.
     * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used.
     */
    public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Whether the selected handler for the current request chose to handle the
     * request asynchronously. A return value of "true" indicates concurrent
     * handling is under way and the response will remain open. A return value
     * of "false" means concurrent handling was either not started or possibly
     * that it has completed and the request was dispatched for further
     * processing of the concurrent result.
     */
    public boolean isConcurrentHandlingStarted() {
        return ((this.asyncWebRequest != null) && this.asyncWebRequest.isAsyncStarted());
    }

    /**
     * Whether a result value exists as a result of concurrent handling.
     */
    public boolean hasConcurrentResult() {
        return (this.concurrentResult != RESULT_NONE);
    }

    /**
     * Provides access to the result from concurrent handling.
     * @return an Object, possibly an {@code Exception} or {@code Throwable} if
     * concurrent handling raised one.
     * @see #clearConcurrentResult()
     */
    public Object getConcurrentResult() {
        return this.concurrentResult;
    }

    /**
     * Provides access to additional processing context saved at the start of
     * concurrent handling.
     * @see #clearConcurrentResult()
     */
    public Object[] getConcurrentResultContext() {
        return this.concurrentResultContext;
    }

    /**
     * Get the {@link CallableProcessingInterceptor} registered under the given key.
     * @param key the key
     * @return the interceptor registered under that key or {@code null}
     */
    public CallableProcessingInterceptor getCallableInterceptor(Object key) {
        return this.callableInterceptors.get(key);
    }

    /**
     * Get the {@link DeferredResultProcessingInterceptor} registered under the given key.
     * @param key the key
     * @return the interceptor registered under that key or {@code null}
     */
    public DeferredResultProcessingInterceptor getDeferredResultInterceptor(Object key) {
        return this.deferredResultInterceptors.get(key);
    }

    /**
     * Register a {@link CallableProcessingInterceptor} under the given key.
     * @param key the key
     * @param interceptor the interceptor to register
     */
    public void registerCallableInterceptor(Object key, CallableProcessingInterceptor interceptor) {
        replacedert.notNull(key, "Key is required");
        replacedert.notNull(interceptor, "CallableProcessingInterceptor  is required");
        this.callableInterceptors.put(key, interceptor);
    }

    /**
     * Register a {@link CallableProcessingInterceptor} without a key.
     * The key is derived from the clreplaced name and hashcode.
     * @param interceptors one or more interceptors to register
     */
    public void registerCallableInterceptors(CallableProcessingInterceptor... interceptors) {
        replacedert.notNull(interceptors, "A CallableProcessingInterceptor is required");
        for (CallableProcessingInterceptor interceptor : interceptors) {
            String key = interceptor.getClreplaced().getName() + ":" + interceptor.hashCode();
            this.callableInterceptors.put(key, interceptor);
        }
    }

    /**
     * Register a {@link DeferredResultProcessingInterceptor} under the given key.
     * @param key the key
     * @param interceptor the interceptor to register
     */
    public void registerDeferredResultInterceptor(Object key, DeferredResultProcessingInterceptor interceptor) {
        replacedert.notNull(key, "Key is required");
        replacedert.notNull(interceptor, "DeferredResultProcessingInterceptor is required");
        this.deferredResultInterceptors.put(key, interceptor);
    }

    /**
     * Register one or more {@link DeferredResultProcessingInterceptor}s without a specified key.
     * The default key is derived from the interceptor clreplaced name and hash code.
     * @param interceptors one or more interceptors to register
     */
    public void registerDeferredResultInterceptors(DeferredResultProcessingInterceptor... interceptors) {
        replacedert.notNull(interceptors, "A DeferredResultProcessingInterceptor is required");
        for (DeferredResultProcessingInterceptor interceptor : interceptors) {
            String key = interceptor.getClreplaced().getName() + ":" + interceptor.hashCode();
            this.deferredResultInterceptors.put(key, interceptor);
        }
    }

    /**
     * Clear {@linkplain #getConcurrentResult() concurrentResult} and
     * {@linkplain #getConcurrentResultContext() concurrentResultContext}.
     */
    public void clearConcurrentResult() {
        this.concurrentResult = RESULT_NONE;
        this.concurrentResultContext = null;
    }

    /**
     * Start concurrent request processing and execute the given task with an
     * {@link #setTaskExecutor(AsyncTaskExecutor) AsyncTaskExecutor}. The result
     * from the task execution is saved and the request dispatched in order to
     * resume processing of that result. If the task raises an Exception then
     * the saved result will be the raised Exception.
     * @param callable a unit of work to be executed asynchronously
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     * @see #getConcurrentResult()
     * @see #getConcurrentResultContext()
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void startCallableProcessing(Callable<?> callable, Object... processingContext) throws Exception {
        replacedert.notNull(callable, "Callable must not be null");
        startCallableProcessing(new WebAsyncTask(callable), processingContext);
    }

    /**
     * Use the given {@link WebAsyncTask} to configure the task executor as well as
     * the timeout value of the {@code AsyncWebRequest} before delegating to
     * {@link #startCallableProcessing(Callable, Object...)}.
     * @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     */
    public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
        replacedert.notNull(webAsyncTask, "WebAsyncTask must not be null");
        replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
        Long timeout = webAsyncTask.getTimeout();
        if (timeout != null) {
            this.asyncWebRequest.setTimeout(timeout);
        }
        AsyncTaskExecutor executor = webAsyncTask.getExecutor();
        if (executor != null) {
            this.taskExecutor = executor;
        }
        List<CallableProcessingInterceptor> interceptors = new ArrayList<CallableProcessingInterceptor>();
        interceptors.add(webAsyncTask.getInterceptor());
        interceptors.addAll(this.callableInterceptors.values());
        interceptors.add(timeoutCallableInterceptor);
        final Callable<?> callable = webAsyncTask.getCallable();
        final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);
        this.asyncWebRequest.addTimeoutHandler(new Runnable() {

            @Override
            public void run() {
                logger.debug("Processing timeout");
                Object result = interceptorChain.triggerAfterTimeout(asyncWebRequest, callable);
                if (result != CallableProcessingInterceptor.RESULT_NONE) {
                    setConcurrentResultAndDispatch(result);
                }
            }
        });
        this.asyncWebRequest.addCompletionHandler(new Runnable() {

            @Override
            public void run() {
                interceptorChain.triggerAfterCompletion(asyncWebRequest, callable);
            }
        });
        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
        startAsyncProcessing(processingContext);
        this.taskExecutor.submit(new Runnable() {

            @Override
            public void run() {
                Object result = null;
                try {
                    interceptorChain.applyPreProcess(asyncWebRequest, callable);
                    result = callable.call();
                } catch (Throwable ex) {
                    result = ex;
                } finally {
                    result = interceptorChain.applyPostProcess(asyncWebRequest, callable, result);
                }
                setConcurrentResultAndDispatch(result);
            }
        });
    }

    private void setConcurrentResultAndDispatch(Object result) {
        synchronized (WebAsyncManager.this) {
            if (hasConcurrentResult()) {
                return;
            }
            this.concurrentResult = result;
        }
        if (this.asyncWebRequest.isAsyncComplete()) {
            logger.error("Could not complete async processing due to timeout or network error");
            return;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Concurrent result value [" + this.concurrentResult + "] - dispatching request to resume processing");
        }
        this.asyncWebRequest.dispatch();
    }

    /**
     * Start concurrent request processing and initialize the given
     * {@link DeferredResult} with a {@link DeferredResultHandler} that saves
     * the result and dispatches the request to resume processing of that
     * result. The {@code AsyncWebRequest} is also updated with a completion
     * handler that expires the {@code DeferredResult} and a timeout handler
     * replaceduming the {@code DeferredResult} has a default timeout result.
     * @param deferredResult the DeferredResult instance to initialize
     * @param processingContext additional context to save that can be accessed
     * via {@link #getConcurrentResultContext()}
     * @throws Exception if concurrent processing failed to start
     * @see #getConcurrentResult()
     * @see #getConcurrentResultContext()
     */
    public void startDeferredResultProcessing(final DeferredResult<?> deferredResult, Object... processingContext) throws Exception {
        replacedert.notNull(deferredResult, "DeferredResult must not be null");
        replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
        Long timeout = deferredResult.getTimeoutValue();
        if (timeout != null) {
            this.asyncWebRequest.setTimeout(timeout);
        }
        List<DeferredResultProcessingInterceptor> interceptors = new ArrayList<DeferredResultProcessingInterceptor>();
        interceptors.add(deferredResult.getInterceptor());
        interceptors.addAll(this.deferredResultInterceptors.values());
        interceptors.add(timeoutDeferredResultInterceptor);
        final DeferredResultInterceptorChain interceptorChain = new DeferredResultInterceptorChain(interceptors);
        this.asyncWebRequest.addTimeoutHandler(new Runnable() {

            @Override
            public void run() {
                try {
                    interceptorChain.triggerAfterTimeout(asyncWebRequest, deferredResult);
                } catch (Throwable ex) {
                    setConcurrentResultAndDispatch(ex);
                }
            }
        });
        this.asyncWebRequest.addCompletionHandler(new Runnable() {

            @Override
            public void run() {
                interceptorChain.triggerAfterCompletion(asyncWebRequest, deferredResult);
            }
        });
        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
        startAsyncProcessing(processingContext);
        try {
            interceptorChain.applyPreProcess(this.asyncWebRequest, deferredResult);
            deferredResult.setResultHandler(new DeferredResultHandler() {

                @Override
                public void handleResult(Object result) {
                    result = interceptorChain.applyPostProcess(asyncWebRequest, deferredResult, result);
                    setConcurrentResultAndDispatch(result);
                }
            });
        } catch (Throwable ex) {
            setConcurrentResultAndDispatch(ex);
        }
    }

    private void startAsyncProcessing(Object[] processingContext) {
        clearConcurrentResult();
        this.concurrentResultContext = processingContext;
        this.asyncWebRequest.startAsync();
        if (logger.isDebugEnabled()) {
            HttpServletRequest request = this.asyncWebRequest.getNativeRequest(HttpServletRequest.clreplaced);
            String requestUri = urlPathHelper.getRequestUri(request);
            logger.debug("Concurrent handling starting for " + request.getMethod() + " [" + requestUri + "]");
        }
    }
}

19 View Source File : WebAsyncManager.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Use the given {@link WebAsyncTask} to configure the task executor as well as
 * the timeout value of the {@code AsyncWebRequest} before delegating to
 * {@link #startCallableProcessing(Callable, Object...)}.
 * @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
 * @param processingContext additional context to save that can be accessed
 * via {@link #getConcurrentResultContext()}
 * @throws Exception if concurrent processing failed to start
 */
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
    replacedert.notNull(webAsyncTask, "WebAsyncTask must not be null");
    replacedert.state(this.asyncWebRequest != null, "AsyncWebRequest must not be null");
    Long timeout = webAsyncTask.getTimeout();
    if (timeout != null) {
        this.asyncWebRequest.setTimeout(timeout);
    }
    AsyncTaskExecutor executor = webAsyncTask.getExecutor();
    if (executor != null) {
        this.taskExecutor = executor;
    }
    List<CallableProcessingInterceptor> interceptors = new ArrayList<CallableProcessingInterceptor>();
    interceptors.add(webAsyncTask.getInterceptor());
    interceptors.addAll(this.callableInterceptors.values());
    interceptors.add(timeoutCallableInterceptor);
    final Callable<?> callable = webAsyncTask.getCallable();
    final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);
    this.asyncWebRequest.addTimeoutHandler(new Runnable() {

        @Override
        public void run() {
            logger.debug("Processing timeout");
            Object result = interceptorChain.triggerAfterTimeout(asyncWebRequest, callable);
            if (result != CallableProcessingInterceptor.RESULT_NONE) {
                setConcurrentResultAndDispatch(result);
            }
        }
    });
    this.asyncWebRequest.addCompletionHandler(new Runnable() {

        @Override
        public void run() {
            interceptorChain.triggerAfterCompletion(asyncWebRequest, callable);
        }
    });
    interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
    startAsyncProcessing(processingContext);
    this.taskExecutor.submit(new Runnable() {

        @Override
        public void run() {
            Object result = null;
            try {
                interceptorChain.applyPreProcess(asyncWebRequest, callable);
                result = callable.call();
            } catch (Throwable ex) {
                result = ex;
            } finally {
                result = interceptorChain.applyPostProcess(asyncWebRequest, callable, result);
            }
            setConcurrentResultAndDispatch(result);
        }
    });
}

19 View Source File : SimpleTaskWorkManager.java
License : Apache License 2.0
Project Creator : langtianya

/**
 * Simple JCA 1.5 {@link javax.resource.spi.work.WorkManager} implementation that
 * delegates to a Spring {@link org.springframework.core.task.TaskExecutor}.
 * Provides simple task execution including start timeouts, but without support
 * for a JCA ExecutionContext (i.e. without support for imported transactions).
 *
 * <p>Uses a {@link org.springframework.core.task.SyncTaskExecutor} for {@link #doWork}
 * calls and a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
 * for {@link #startWork} and {@link #scheduleWork} calls, by default.
 * These default task executors can be overridden through configuration.
 *
 * <p><b>NOTE: This WorkManager does not provide thread pooling by default!</b>
 * Specify a {@link org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor}
 * (or any other thread-pooling TaskExecutor) as "asyncTaskExecutor" in order to
 * achieve actual thread pooling.
 *
 * <p>This WorkManager automatically detects a specified
 * {@link org.springframework.core.task.AsyncTaskExecutor} implementation
 * and uses its extended timeout functionality where appropriate.
 * JCA WorkListeners are fully supported in any case.
 *
 * @author Juergen Hoeller
 * @since 2.0.3
 * @see #setSyncTaskExecutor
 * @see #setAsyncTaskExecutor
 */
public clreplaced SimpleTaskWorkManager implements WorkManager {

    private TaskExecutor syncTaskExecutor = new SyncTaskExecutor();

    private AsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor();

    /**
     * Specify the TaskExecutor to use for <i>synchronous</i> work execution
     * (i.e. {@link #doWork} calls).
     * <p>Default is a {@link org.springframework.core.task.SyncTaskExecutor}.
     */
    public void setSyncTaskExecutor(TaskExecutor syncTaskExecutor) {
        this.syncTaskExecutor = syncTaskExecutor;
    }

    /**
     * Specify the TaskExecutor to use for <i>asynchronous</i> work execution
     * (i.e. {@link #startWork} and {@link #scheduleWork} calls).
     * <p>This will typically (but not necessarily) be an
     * {@link org.springframework.core.task.AsyncTaskExecutor} implementation.
     * Default is a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
     */
    public void setAsyncTaskExecutor(AsyncTaskExecutor asyncTaskExecutor) {
        this.asyncTaskExecutor = asyncTaskExecutor;
    }

    @Override
    public void doWork(Work work) throws WorkException {
        doWork(work, WorkManager.INDEFINITE, null, null);
    }

    @Override
    public void doWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener) throws WorkException {
        replacedert.state(this.syncTaskExecutor != null, "No 'syncTaskExecutor' set");
        executeWork(this.syncTaskExecutor, work, startTimeout, false, executionContext, workListener);
    }

    @Override
    public long startWork(Work work) throws WorkException {
        return startWork(work, WorkManager.INDEFINITE, null, null);
    }

    @Override
    public long startWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener) throws WorkException {
        replacedert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
        return executeWork(this.asyncTaskExecutor, work, startTimeout, true, executionContext, workListener);
    }

    @Override
    public void scheduleWork(Work work) throws WorkException {
        scheduleWork(work, WorkManager.INDEFINITE, null, null);
    }

    @Override
    public void scheduleWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener) throws WorkException {
        replacedert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
        executeWork(this.asyncTaskExecutor, work, startTimeout, false, executionContext, workListener);
    }

    /**
     * Execute the given Work on the specified TaskExecutor.
     * @param taskExecutor the TaskExecutor to use
     * @param work the Work to execute
     * @param startTimeout the time duration within which the Work is supposed to start
     * @param blockUntilStarted whether to block until the Work has started
     * @param executionContext the JCA ExecutionContext for the given Work
     * @param workListener the WorkListener to clal for the given Work
     * @return the time elapsed from Work acceptance until start of execution
     * (or -1 if not applicable or not known)
     * @throws WorkException if the TaskExecutor did not accept the Work
     */
    protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout, boolean blockUntilStarted, ExecutionContext executionContext, WorkListener workListener) throws WorkException {
        if (executionContext != null && executionContext.getXid() != null) {
            throw new WorkException("SimpleTaskWorkManager does not supported imported XIDs: " + executionContext.getXid());
        }
        WorkListener workListenerToUse = workListener;
        if (workListenerToUse == null) {
            workListenerToUse = new WorkAdapter();
        }
        boolean isAsync = (taskExecutor instanceof AsyncTaskExecutor);
        DelegatingWorkAdapter workHandle = new DelegatingWorkAdapter(work, workListenerToUse, !isAsync);
        try {
            if (isAsync) {
                ((AsyncTaskExecutor) taskExecutor).execute(workHandle, startTimeout);
            } else {
                taskExecutor.execute(workHandle);
            }
        } catch (TaskTimeoutException ex) {
            WorkException wex = new WorkRejectedException("TaskExecutor rejected Work because of timeout: " + work, ex);
            wex.setErrorCode(WorkException.START_TIMED_OUT);
            workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
            throw wex;
        } catch (TaskRejectedException ex) {
            WorkException wex = new WorkRejectedException("TaskExecutor rejected Work: " + work, ex);
            wex.setErrorCode(WorkException.INTERNAL);
            workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
            throw wex;
        } catch (Throwable ex) {
            WorkException wex = new WorkException("TaskExecutor failed to execute Work: " + work, ex);
            wex.setErrorCode(WorkException.INTERNAL);
            throw wex;
        }
        if (isAsync) {
            workListenerToUse.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
        }
        if (blockUntilStarted) {
            long acceptanceTime = System.currentTimeMillis();
            synchronized (workHandle.monitor) {
                try {
                    while (!workHandle.started) {
                        workHandle.monitor.wait();
                    }
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
            return (System.currentTimeMillis() - acceptanceTime);
        } else {
            return WorkManager.UNKNOWN;
        }
    }

    /**
     * Work adapter that supports start timeouts and WorkListener callbacks
     * for a given Work that it delegates to.
     */
    private static clreplaced DelegatingWorkAdapter implements Work {

        private final Work work;

        private final WorkListener workListener;

        private final boolean acceptOnExecution;

        public final Object monitor = new Object();

        public boolean started = false;

        public DelegatingWorkAdapter(Work work, WorkListener workListener, boolean acceptOnExecution) {
            this.work = work;
            this.workListener = workListener;
            this.acceptOnExecution = acceptOnExecution;
        }

        @Override
        public void run() {
            if (this.acceptOnExecution) {
                this.workListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
            }
            synchronized (this.monitor) {
                this.started = true;
                this.monitor.notify();
            }
            this.workListener.workStarted(new WorkEvent(this, WorkEvent.WORK_STARTED, this.work, null));
            try {
                this.work.run();
            } catch (RuntimeException ex) {
                this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(ex)));
                throw ex;
            } catch (Error err) {
                this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(err)));
                throw err;
            }
            this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, null));
        }

        @Override
        public void release() {
            this.work.release();
        }
    }
}

19 View Source File : DelExpireLog.java
License : BSD 3-Clause "New" or "Revised" License
Project Creator : hxnlyw

/**
 * 清除过期日志记录
 * @author gourd.hu
 */
@Slf4j
public clreplaced DelExpireLog {

    @Resource
    private OperateLogService operateLogService;

    @Autowired
    private AsyncTaskExecutor asyncTaskExecutor;

    /**
     * 每天0点执行一次删除过期日志
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void doTask() {
        log.info(">o< 删除过期日志定时任务开始执行: " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + "  " + Thread.currentThread().getName());
        while (true) {
            Page page = new Page<>(1, 500);
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.le("expire_time", LocalDateTime.now());
            IPage<SysOperateLog> logIPage = operateLogService.page(page, queryWrapper);
            List<SysOperateLog> logPOS = logIPage.getRecords();
            if (CollectionUtils.isEmpty(logPOS)) {
                break;
            }
            List<Long> logIds = logPOS.stream().map(e -> e.getId()).collect(Collectors.toList());
            asyncTaskExecutor.execute(() -> operateLogService.deleteLogs(logIds));
        }
        log.info(">o< 删除过期日志定时任务结束: " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + "  " + Thread.currentThread().getName());
    }
}

19 View Source File : ContextAwareAsyncTaskExecutorTest.java
License : Apache License 2.0
Project Creator : enadim

public clreplaced ContextAwareAsyncTaskExecutorTest extends AbstractExecutionContextAwareExecutorTest {

    private final AsyncTaskExecutor delegate = mock(AsyncTaskExecutor.clreplaced);

    private final ContextAwareAsyncTaskExecutor propagator = new ContextAwareAsyncTaskExecutor(delegate);

    @Test
    public void execute() throws Exception {
        propagator.execute(runnable, 0);
        verify(delegate).execute(any(ContextAwareRunnable.clreplaced), anyLong());
    }

    @Test
    public void submitRunnable() throws Exception {
        propagator.submit(runnable);
        verify(delegate).submit(any(ContextAwareRunnable.clreplaced));
    }

    @Test
    public void submitCallable() throws Exception {
        propagator.submit(callable);
        verify(delegate).submit(any(ContextAwareCallable.clreplaced));
    }
}

19 View Source File : ContextAwareAsyncTaskExecutor.java
License : Apache License 2.0
Project Creator : enadim

/**
 * Copies current {@link ExecutionContext} to delegate async task executor task.
 *
 * @author Nadim Benabdenbi
 */
public clreplaced ContextAwareAsyncTaskExecutor extends ContextAwareExecutor implements AsyncTaskExecutor {

    /**
     * The delegate async task executor.
     */
    private final AsyncTaskExecutor delegate;

    /**
     * Sole Constructor.
     *
     * @param delegate the delegate async task executor..
     */
    public ContextAwareAsyncTaskExecutor(@NotNull AsyncTaskExecutor delegate) {
        super(delegate);
        this.delegate = delegate;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final void execute(Runnable task, long startTimeout) {
        delegate.execute(ContextAwareRunnable.wrap(task), startTimeout);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Future<?> submit(Runnable task) {
        return delegate.submit(ContextAwareRunnable.wrap(task));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final <T> Future<T> submit(Callable<T> task) {
        return delegate.submit(ContextAwareCallable.wrap(task));
    }
}

19 View Source File : SimpleMessageListenerContainer.java
License : Apache License 2.0
Project Creator : awspring

/**
 * @author Agim Emruli
 * @author Alain Sahli
 * @author Mete Alpaslan Katırcıoğlu
 * @since 1.0
 */
public clreplaced SimpleMessageListenerContainer extends AbstractMessageListenerContainer {

    private static final int DEFAULT_WORKER_THREADS = 2;

    private static final String DEFAULT_THREAD_NAME_PREFIX = ClreplacedUtils.getShortName(SimpleMessageListenerContainer.clreplaced) + "-";

    private boolean defaultTaskExecutor;

    private long backOffTime = 10000;

    private long queueStopTimeout = 20000;

    private AsyncTaskExecutor taskExecutor;

    private ConcurrentHashMap<String, Future<?>> scheduledFutureByQueue;

    private ConcurrentHashMap<String, Boolean> runningStateByQueue;

    protected AsyncTaskExecutor getTaskExecutor() {
        return this.taskExecutor;
    }

    public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * @return The number of milliseconds the polling thread must wait before trying to
     * recover when an error occurs (e.g. connection timeout)
     */
    public long getBackOffTime() {
        return this.backOffTime;
    }

    /**
     * The number of milliseconds the polling thread must wait before trying to recover
     * when an error occurs (e.g. connection timeout). Default is 10000 milliseconds.
     * @param backOffTime in milliseconds
     */
    public void setBackOffTime(long backOffTime) {
        this.backOffTime = backOffTime;
    }

    /**
     * @return The number of milliseconds the
     * {@link SimpleMessageListenerContainer#stop(String)} method waits for a queue to
     * stop before interrupting the current thread. Default value is 10000 milliseconds
     * (10 seconds).
     */
    public long getQueueStopTimeout() {
        return this.queueStopTimeout;
    }

    /**
     * The number of milliseconds the {@link SimpleMessageListenerContainer#stop(String)}
     * method waits for a queue to stop before interrupting the current thread. Default
     * value is 20000 milliseconds (20 seconds).
     * @param queueStopTimeout in milliseconds
     */
    public void setQueueStopTimeout(long queueStopTimeout) {
        this.queueStopTimeout = queueStopTimeout;
    }

    @Override
    protected void initialize() {
        super.initialize();
        if (this.taskExecutor == null) {
            this.defaultTaskExecutor = true;
            this.taskExecutor = createDefaultTaskExecutor();
        }
        initializeRunningStateByQueue();
        this.scheduledFutureByQueue = new ConcurrentHashMap<>(getRegisteredQueues().size());
    }

    private void initializeRunningStateByQueue() {
        this.runningStateByQueue = new ConcurrentHashMap<>(getRegisteredQueues().size());
        for (String queueName : getRegisteredQueues().keySet()) {
            this.runningStateByQueue.put(queueName, false);
        }
    }

    @Override
    protected void doStart() {
        synchronized (this.getLifecycleMonitor()) {
            scheduleMessageListeners();
        }
    }

    @Override
    protected void doStop() {
        notifyRunningQueuesToStop();
        waitForRunningQueuesToStop();
    }

    private void notifyRunningQueuesToStop() {
        for (Map.Entry<String, Boolean> runningStateByQueue : this.runningStateByQueue.entrySet()) {
            if (runningStateByQueue.getValue()) {
                stopQueue(runningStateByQueue.getKey());
            }
        }
    }

    private void waitForRunningQueuesToStop() {
        for (Map.Entry<String, Boolean> queueRunningState : this.runningStateByQueue.entrySet()) {
            String logicalQueueName = queueRunningState.getKey();
            Future<?> queueSpinningThread = this.scheduledFutureByQueue.get(logicalQueueName);
            if (queueSpinningThread != null) {
                try {
                    queueSpinningThread.get(getQueueStopTimeout(), TimeUnit.MILLISECONDS);
                } catch (ExecutionException | TimeoutException e) {
                    getLogger().warn("An exception occurred while stopping queue '" + logicalQueueName + "'", e);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    @Override
    protected void doDestroy() {
        if (this.defaultTaskExecutor) {
            ((ThreadPoolTaskExecutor) this.taskExecutor).destroy();
        }
    }

    /**
     * Create a default TaskExecutor. Called if no explicit TaskExecutor has been
     * specified.
     * <p>
     * The default implementation builds a
     * {@link org.springframework.core.task.SimpleAsyncTaskExecutor} with the specified
     * bean name (or the clreplaced name, if no bean name specified) as thread name prefix.
     * @return a {@link org.springframework.core.task.SimpleAsyncTaskExecutor} configured
     * with the thread name prefix
     * @see org.springframework.core.task.SimpleAsyncTaskExecutor#SimpleAsyncTaskExecutor(String)
     */
    protected AsyncTaskExecutor createDefaultTaskExecutor() {
        String beanName = getBeanName();
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setThreadNamePrefix(beanName != null ? beanName + "-" : DEFAULT_THREAD_NAME_PREFIX);
        int spinningThreads = this.getRegisteredQueues().size();
        if (spinningThreads > 0) {
            threadPoolTaskExecutor.setCorePoolSize(spinningThreads * DEFAULT_WORKER_THREADS);
            int maxNumberOfMessagePerBatch = getMaxNumberOfMessages() != null ? getMaxNumberOfMessages() : DEFAULT_MAX_NUMBER_OF_MESSAGES;
            threadPoolTaskExecutor.setMaxPoolSize(spinningThreads * (maxNumberOfMessagePerBatch + 1));
        }
        // No use of a thread pool executor queue to avoid retaining message to long in
        // memory
        threadPoolTaskExecutor.setQueueCapacity(0);
        threadPoolTaskExecutor.afterPropertiesSet();
        return threadPoolTaskExecutor;
    }

    private void scheduleMessageListeners() {
        for (Map.Entry<String, QueueAttributes> registeredQueue : getRegisteredQueues().entrySet()) {
            startQueue(registeredQueue.getKey(), registeredQueue.getValue());
        }
    }

    protected void executeMessage(org.springframework.messaging.Message<String> stringMessage) {
        getMessageHandler().handleMessage(stringMessage);
    }

    /**
     * Stops and waits until the specified queue has stopped. If the wait timeout
     * specified by {@link SimpleMessageListenerContainer#getQueueStopTimeout()} is
     * reached, the current thread is interrupted.
     * @param logicalQueueName the name as defined on the listener method
     */
    public void stop(String logicalQueueName) {
        stopQueue(logicalQueueName);
        try {
            if (isRunning(logicalQueueName)) {
                Future<?> future = this.scheduledFutureByQueue.remove(logicalQueueName);
                if (future != null) {
                    future.get(this.queueStopTimeout, TimeUnit.MILLISECONDS);
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException | TimeoutException e) {
            getLogger().warn("Error stopping queue with name: '" + logicalQueueName + "'", e);
        }
    }

    protected void stopQueue(String logicalQueueName) {
        replacedert.isTrue(this.runningStateByQueue.containsKey(logicalQueueName), "Queue with name '" + logicalQueueName + "' does not exist");
        this.runningStateByQueue.put(logicalQueueName, false);
    }

    public void start(String logicalQueueName) {
        replacedert.isTrue(this.runningStateByQueue.containsKey(logicalQueueName), "Queue with name '" + logicalQueueName + "' does not exist");
        QueueAttributes queueAttributes = this.getRegisteredQueues().get(logicalQueueName);
        startQueue(logicalQueueName, queueAttributes);
    }

    /**
     * Checks if the spinning thread for the specified queue {@code logicalQueueName} is
     * still running (polling for new messages) or not.
     * @param logicalQueueName the name as defined on the listener method
     * @return {@code true} if the spinning thread for the specified queue is running
     * otherwise {@code false}.
     */
    public boolean isRunning(String logicalQueueName) {
        Future<?> future = this.scheduledFutureByQueue.get(logicalQueueName);
        return future != null && !future.isCancelled() && !future.isDone();
    }

    protected void startQueue(String queueName, QueueAttributes queueAttributes) {
        if (isQueueRunning(queueName)) {
            return;
        }
        this.runningStateByQueue.put(queueName, true);
        Future<?> future = getTaskExecutor().submit(new AsynchronousMessageListener(queueName, queueAttributes));
        this.scheduledFutureByQueue.put(queueName, future);
    }

    protected boolean isQueueRunning(String logicalQueueName) {
        if (this.runningStateByQueue.containsKey(logicalQueueName)) {
            return this.runningStateByQueue.get(logicalQueueName);
        } else {
            getLogger().warn("Stopped queue '" + logicalQueueName + "' because it was not listed as running queue.");
            return false;
        }
    }

    private static final clreplaced SignalExecutingRunnable implements Runnable {

        private final CountDownLatch countDownLatch;

        private final Runnable runnable;

        private SignalExecutingRunnable(CountDownLatch endSignal, Runnable runnable) {
            this.countDownLatch = endSignal;
            this.runnable = runnable;
        }

        @Override
        public void run() {
            try {
                this.runnable.run();
            } finally {
                this.countDownLatch.countDown();
            }
        }
    }

    private final clreplaced AsynchronousMessageListener implements Runnable {

        private final QueueAttributes queueAttributes;

        private final String logicalQueueName;

        private AsynchronousMessageListener(String logicalQueueName, QueueAttributes queueAttributes) {
            this.logicalQueueName = logicalQueueName;
            this.queueAttributes = queueAttributes;
        }

        @Override
        public void run() {
            while (isQueueRunning(this.logicalQueueName)) {
                try {
                    ReceiveMessageResult receiveMessageResult = getAmazonSqs().receiveMessage(this.queueAttributes.getReceiveMessageRequest());
                    final List<MessageGroup> messageGroups = queueAttributes.isFifo() ? groupByMessageGroupId(receiveMessageResult) : groupByMessage(receiveMessageResult);
                    CountDownLatch messageBatchLatch = new CountDownLatch(messageGroups.size());
                    for (MessageGroup messageGroup : messageGroups) {
                        if (isQueueRunning(this.logicalQueueName)) {
                            MessageGroupExecutor messageGroupExecutor = new MessageGroupExecutor(this.logicalQueueName, messageGroup, this.queueAttributes);
                            getTaskExecutor().execute(new SignalExecutingRunnable(messageBatchLatch, messageGroupExecutor));
                        } else {
                            messageBatchLatch.countDown();
                        }
                    }
                    try {
                        messageBatchLatch.await();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                } catch (Exception e) {
                    getLogger().warn("An Exception occurred while polling queue '{}'. The failing operation will be " + "retried in {} milliseconds", this.logicalQueueName, getBackOffTime(), e);
                    try {
                        // noinspection BusyWait
                        Thread.sleep(getBackOffTime());
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
            SimpleMessageListenerContainer.this.scheduledFutureByQueue.remove(this.logicalQueueName);
        }

        private List<MessageGroup> groupByMessageGroupId(final ReceiveMessageResult receiveMessageResult) {
            return receiveMessageResult.getMessages().stream().collect(Collectors.groupingBy(message -> message.getAttributes().get(MessageSystemAttributeName.MessageGroupId.name()))).values().stream().map(MessageGroup::new).collect(Collectors.toList());
        }

        private List<MessageGroup> groupByMessage(final ReceiveMessageResult receiveMessageResult) {
            return receiveMessageResult.getMessages().stream().map(MessageGroup::new).collect(Collectors.toList());
        }
    }

    private static final clreplaced MessageGroup {

        private final List<Message> messages;

        MessageGroup(final Message message) {
            this.messages = Collections.singletonList(message);
        }

        MessageGroup(final List<Message> messages) {
            this.messages = messages;
        }

        public List<Message> getMessages() {
            return this.messages;
        }
    }

    private final clreplaced MessageGroupExecutor implements Runnable {

        private final MessageGroup messageGroup;

        private final String logicalQueueName;

        private final String queueUrl;

        private final boolean hasRedrivePolicy;

        private final SqsMessageDeletionPolicy deletionPolicy;

        private MessageGroupExecutor(String logicalQueueName, MessageGroup messageGroup, QueueAttributes queueAttributes) {
            this.logicalQueueName = logicalQueueName;
            this.messageGroup = messageGroup;
            this.queueUrl = queueAttributes.getReceiveMessageRequest().getQueueUrl();
            this.hasRedrivePolicy = queueAttributes.hasRedrivePolicy();
            this.deletionPolicy = queueAttributes.getDeletionPolicy();
        }

        @Override
        public void run() {
            for (Message message : this.messageGroup.getMessages()) {
                String receiptHandle = message.getReceiptHandle();
                org.springframework.messaging.Message<String> queueMessage = getMessageForExecution(message);
                try {
                    executeMessage(queueMessage);
                    applyDeletionPolicyOnSuccess(receiptHandle);
                } catch (MessagingException messagingException) {
                    applyDeletionPolicyOnError(receiptHandle);
                }
            }
        }

        private void applyDeletionPolicyOnSuccess(String receiptHandle) {
            if (this.deletionPolicy == SqsMessageDeletionPolicy.ON_SUCCESS || this.deletionPolicy == SqsMessageDeletionPolicy.ALWAYS || this.deletionPolicy == SqsMessageDeletionPolicy.NO_REDRIVE) {
                deleteMessage(receiptHandle);
            }
        }

        private void applyDeletionPolicyOnError(String receiptHandle) {
            if (this.deletionPolicy == SqsMessageDeletionPolicy.ALWAYS || (this.deletionPolicy == SqsMessageDeletionPolicy.NO_REDRIVE && !this.hasRedrivePolicy)) {
                deleteMessage(receiptHandle);
            }
        }

        private void deleteMessage(String receiptHandle) {
            getAmazonSqs().deleteMessageAsync(new DeleteMessageRequest(this.queueUrl, receiptHandle), new DeleteMessageHandler(receiptHandle));
        }

        private org.springframework.messaging.Message<String> getMessageForExecution(final Message message) {
            HashMap<String, Object> additionalHeaders = new HashMap<>();
            additionalHeaders.put(QueueMessageHandler.LOGICAL_RESOURCE_ID, this.logicalQueueName);
            if (this.deletionPolicy == SqsMessageDeletionPolicy.NEVER) {
                String receiptHandle = message.getReceiptHandle();
                QueueMessageAcknowledgment acknowledgment = new QueueMessageAcknowledgment(SimpleMessageListenerContainer.this.getAmazonSqs(), this.queueUrl, receiptHandle);
                additionalHeaders.put(QueueMessageHandler.ACKNOWLEDGMENT, acknowledgment);
            }
            additionalHeaders.put(QueueMessageHandler.VISIBILITY, new QueueMessageVisibility(SimpleMessageListenerContainer.this.getAmazonSqs(), this.queueUrl, message.getReceiptHandle()));
            return createMessage(message, additionalHeaders);
        }
    }
}

19 View Source File : SimpleMessageListenerContainerFactory.java
License : Apache License 2.0
Project Creator : awspring

/**
 * @author Alain Sahli
 * @author Mete Alpaslan Katırcıoğlu
 * @since 1.0
 */
public clreplaced SimpleMessageListenerContainerFactory {

    private AsyncTaskExecutor taskExecutor;

    private Integer maxNumberOfMessages;

    private Integer visibilityTimeout;

    private Integer waitTimeOut;

    private Long queueStopTimeout;

    private boolean autoStartup = true;

    private AmazonSQSAsync amazonSqs;

    private QueueMessageHandler queueMessageHandler;

    private ResourceIdResolver resourceIdResolver;

    private DestinationResolver<String> destinationResolver;

    private Long backOffTime;

    /**
     * Configures the {@link TaskExecutor} which is used to poll messages and execute them
     * by calling the handler methods. If no {@link TaskExecutor} is set, a default one is
     * created.
     * @param taskExecutor The {@link TaskExecutor} used by the container
     * @see SimpleMessageListenerContainer#createDefaultTaskExecutor()
     */
    public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * Configure the maximum number of messages that should be retrieved during one poll
     * to the Amazon SQS system. This number must be a positive, non-zero number that has
     * a maximum number of 10. Values higher then 10 are currently not supported by the
     * queueing system.
     * @param maxNumberOfMessages the maximum number of messages (between 1-10)
     */
    public void setMaxNumberOfMessages(Integer maxNumberOfMessages) {
        this.maxNumberOfMessages = maxNumberOfMessages;
    }

    /**
     * Configures the duration (in seconds) that the received messages are hidden from
     * subsequent poll requests after being retrieved from the system.
     * @param visibilityTimeout the visibility timeout in seconds
     */
    public void setVisibilityTimeout(Integer visibilityTimeout) {
        this.visibilityTimeout = visibilityTimeout;
    }

    /**
     * Configures the wait timeout that the poll request will wait for new message to
     * arrive if the are currently no messages on the queue. Higher values will reduce
     * poll request to the system significantly. The value should be between 1 and 20. For
     * more information read the <a href=
     * "https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html">doreplacedentation</a>.
     * @param waitTimeOut - the wait time out in seconds
     */
    public void setWaitTimeOut(Integer waitTimeOut) {
        this.waitTimeOut = waitTimeOut;
    }

    /**
     * Configures the queue stop timeout that waits for a queue to stop before
     * interrupting the running thread.
     * @param queueStopTimeout in milliseconds
     */
    public void setQueueStopTimeout(Long queueStopTimeout) {
        this.queueStopTimeout = queueStopTimeout;
    }

    /**
     * Configures if this container should be automatically started. The default value is
     * true.
     * @param autoStartup - false if the container will be manually started
     */
    public void setAutoStartup(boolean autoStartup) {
        this.autoStartup = autoStartup;
    }

    public AmazonSQS getAmazonSqs() {
        return this.amazonSqs;
    }

    /**
     * Sets the {@link AmazonSQSAsync} that is going to be used by the container to
     * interact with the messaging (SQS) API.
     * @param amazonSqs The {@link AmazonSQSAsync}, must not be {@code null}.
     */
    public void setAmazonSqs(AmazonSQSAsync amazonSqs) {
        replacedert.notNull(amazonSqs, "amazonSqs must not be null");
        this.amazonSqs = amazonSqs;
    }

    public QueueMessageHandler getQueueMessageHandler() {
        return this.queueMessageHandler;
    }

    /**
     * Configures the {@link QueueMessageHandler} that must be used to handle incoming
     * messages.
     * <p>
     * <b>NOTE</b>: It is rather unlikely that the {@link QueueMessageHandler} must be
     * configured with this setter. Consider using the {@link QueueMessageHandlerFactory}
     * to configure the {@link QueueMessageHandler} before using this setter.
     * </p>
     * @param messageHandler the {@link QueueMessageHandler} that must be used by the
     * container, must not be {@code null}.
     * @see QueueMessageHandlerFactory
     */
    public void setQueueMessageHandler(QueueMessageHandler messageHandler) {
        replacedert.notNull(messageHandler, "messageHandler must not be null");
        this.queueMessageHandler = messageHandler;
    }

    public ResourceIdResolver getResourceIdResolver() {
        return this.resourceIdResolver;
    }

    /**
     * This value must be set if no destination resolver has been set.
     * @param resourceIdResolver the resourceIdResolver to use for resolving logical to
     * physical ids in a CloudFormation environment. Must not be null.
     */
    public void setResourceIdResolver(ResourceIdResolver resourceIdResolver) {
        this.resourceIdResolver = resourceIdResolver;
    }

    /**
     * Configures the destination resolver used to retrieve the queue url based on the
     * destination name configured for this instance. <br>
     * This setter can be used when a custom configured {@link DestinationResolver} must
     * be provided. (For example if one want to have the
     * {@link io.awspring.cloud.messaging.support.destination.DynamicQueueUrlDestinationResolver}
     * with the auto creation of queues set to {@code true}.
     * @param destinationResolver another or customized {@link DestinationResolver}
     */
    public void setDestinationResolver(DestinationResolver<String> destinationResolver) {
        this.destinationResolver = destinationResolver;
    }

    /**
     * @return The number of milliseconds the polling thread must wait before trying to
     * recover when an error occurs (e.g. connection timeout)
     */
    public Long getBackOffTime() {
        return this.backOffTime;
    }

    /**
     * The number of milliseconds the polling thread must wait before trying to recover
     * when an error occurs (e.g. connection timeout). Default value is 10000
     * milliseconds.
     * @param backOffTime in milliseconds
     */
    public void setBackOffTime(Long backOffTime) {
        this.backOffTime = backOffTime;
    }

    public SimpleMessageListenerContainer createSimpleMessageListenerContainer() {
        replacedert.notNull(this.amazonSqs, "amazonSqs must not be null");
        SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer();
        simpleMessageListenerContainer.setAmazonSqs(this.amazonSqs);
        simpleMessageListenerContainer.setAutoStartup(this.autoStartup);
        if (this.taskExecutor != null) {
            simpleMessageListenerContainer.setTaskExecutor(this.taskExecutor);
        }
        if (this.maxNumberOfMessages != null) {
            simpleMessageListenerContainer.setMaxNumberOfMessages(this.maxNumberOfMessages);
        }
        if (this.visibilityTimeout != null) {
            simpleMessageListenerContainer.setVisibilityTimeout(this.visibilityTimeout);
        }
        if (this.waitTimeOut != null) {
            simpleMessageListenerContainer.setWaitTimeOut(this.waitTimeOut);
        }
        if (this.queueStopTimeout != null) {
            simpleMessageListenerContainer.setQueueStopTimeout(this.queueStopTimeout);
        }
        if (this.resourceIdResolver != null) {
            simpleMessageListenerContainer.setResourceIdResolver(this.resourceIdResolver);
        }
        if (this.destinationResolver != null) {
            simpleMessageListenerContainer.setDestinationResolver(this.destinationResolver);
        }
        if (this.backOffTime != null) {
            simpleMessageListenerContainer.setBackOffTime(this.backOffTime);
        }
        return simpleMessageListenerContainer;
    }
}

19 View Source File : SimpleMessageListenerContainerFactory.java
License : Apache License 2.0
Project Creator : awspring

/**
 * Configures the {@link TaskExecutor} which is used to poll messages and execute them
 * by calling the handler methods. If no {@link TaskExecutor} is set, a default one is
 * created.
 * @param taskExecutor The {@link TaskExecutor} used by the container
 * @see SimpleMessageListenerContainer#createDefaultTaskExecutor()
 */
public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

18 View Source File : AsyncSupportConfigurer.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Helps with configuring options for asynchronous request processing.
 *
 * @author Rossen Stoyanchev
 * @since 3.2
 */
public clreplaced AsyncSupportConfigurer {

    @Nullable
    private AsyncTaskExecutor taskExecutor;

    @Nullable
    private Long timeout;

    private final List<CallableProcessingInterceptor> callableInterceptors = new ArrayList<>();

    private final List<DeferredResultProcessingInterceptor> deferredResultInterceptors = new ArrayList<>();

    /**
     * The provided task executor is used to:
     * <ol>
     * <li>Handle {@link Callable} controller method return values.
     * <li>Perform blocking writes when streaming to the response
     * through a reactive (e.g. Reactor, RxJava) controller method return value.
     * </ol>
     * <p>By default only a {@link SimpleAsyncTaskExecutor} is used. However when
     * using the above two use cases, it's recommended to configure an executor
     * backed by a thread pool such as {@link ThreadPoolTaskExecutor}.
     * @param taskExecutor the task executor instance to use by default
     */
    public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
        return this;
    }

    /**
     * Specify the amount of time, in milliseconds, before asynchronous request
     * handling times out. In Servlet 3, the timeout begins after the main request
     * processing thread has exited and ends when the request is dispatched again
     * for further processing of the concurrently produced result.
     * <p>If this value is not set, the default timeout of the underlying
     * implementation is used, e.g. 10 seconds on Tomcat with Servlet 3.
     * @param timeout the timeout value in milliseconds
     */
    public AsyncSupportConfigurer setDefaultTimeout(long timeout) {
        this.timeout = timeout;
        return this;
    }

    /**
     * Configure lifecycle interceptors with callbacks around concurrent request
     * execution that starts when a controller returns a
     * {@link java.util.concurrent.Callable}.
     * @param interceptors the interceptors to register
     */
    public AsyncSupportConfigurer registerCallableInterceptors(CallableProcessingInterceptor... interceptors) {
        this.callableInterceptors.addAll(Arrays.asList(interceptors));
        return this;
    }

    /**
     * Configure lifecycle interceptors with callbacks around concurrent request
     * execution that starts when a controller returns a {@link DeferredResult}.
     * @param interceptors the interceptors to register
     */
    public AsyncSupportConfigurer registerDeferredResultInterceptors(DeferredResultProcessingInterceptor... interceptors) {
        this.deferredResultInterceptors.addAll(Arrays.asList(interceptors));
        return this;
    }

    @Nullable
    protected AsyncTaskExecutor getTaskExecutor() {
        return this.taskExecutor;
    }

    @Nullable
    protected Long getTimeout() {
        return this.timeout;
    }

    protected List<CallableProcessingInterceptor> getCallableInterceptors() {
        return this.callableInterceptors;
    }

    protected List<DeferredResultProcessingInterceptor> getDeferredResultInterceptors() {
        return this.deferredResultInterceptors;
    }
}

18 View Source File : WebAsyncManagerTests.java
License : MIT License
Project Creator : Vip-Augus

@SuppressWarnings("unchecked")
@Test
public void startCallableProcessingWithAsyncTask() throws Exception {
    AsyncTaskExecutor executor = mock(AsyncTaskExecutor.clreplaced);
    given(this.asyncWebRequest.getNativeRequest(HttpServletRequest.clreplaced)).willReturn(this.servletRequest);
    WebAsyncTask<Object> asyncTask = new WebAsyncTask<>(1000L, executor, mock(Callable.clreplaced));
    this.asyncManager.startCallableProcessing(asyncTask);
    verify(executor).submit((Runnable) notNull());
    verify(this.asyncWebRequest).setTimeout(1000L);
    verify(this.asyncWebRequest).addTimeoutHandler(any(Runnable.clreplaced));
    verify(this.asyncWebRequest).addErrorHandler(any(Consumer.clreplaced));
    verify(this.asyncWebRequest).addCompletionHandler(any(Runnable.clreplaced));
    verify(this.asyncWebRequest).startAsync();
}

18 View Source File : AbstractEntityManagerFactoryBean.java
License : MIT License
Project Creator : Vip-Augus

/**
 * Abstract {@link org.springframework.beans.factory.FactoryBean} that creates
 * a local JPA {@link javax.persistence.EnreplacedyManagerFactory} instance within
 * a Spring application context.
 *
 * <p>Encapsulates the common functionality between the different JPA bootstrap
 * contracts (standalone as well as container).
 *
 * <p>Implements support for standard JPA configuration conventions as well as
 * Spring's customizable {@link JpaVendorAdapter} mechanism, and controls the
 * EnreplacedyManagerFactory's lifecycle.
 *
 * <p>This clreplaced also implements the
 * {@link org.springframework.dao.support.PersistenceExceptionTranslator}
 * interface, as autodetected by Spring's
 * {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor},
 * for AOP-based translation of native exceptions to Spring DataAccessExceptions.
 * Hence, the presence of e.g. LocalEnreplacedyManagerFactoryBean automatically enables
 * a PersistenceExceptionTranslationPostProcessor to translate JPA exceptions.
 *
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @since 2.0
 * @see LocalEnreplacedyManagerFactoryBean
 * @see LocalContainerEnreplacedyManagerFactoryBean
 */
@SuppressWarnings("serial")
public abstract clreplaced AbstractEnreplacedyManagerFactoryBean implements FactoryBean<EnreplacedyManagerFactory>, BeanClreplacedLoaderAware, BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean, EnreplacedyManagerFactoryInfo, PersistenceExceptionTranslator, Serializable {

    /**
     * Logger available to subclreplacedes.
     */
    protected final Log logger = LogFactory.getLog(getClreplaced());

    @Nullable
    private PersistenceProvider persistenceProvider;

    @Nullable
    private String persistenceUnitName;

    private final Map<String, Object> jpaPropertyMap = new HashMap<>();

    @Nullable
    private Clreplaced<? extends EnreplacedyManagerFactory> enreplacedyManagerFactoryInterface;

    @Nullable
    private Clreplaced<? extends EnreplacedyManager> enreplacedyManagerInterface;

    @Nullable
    private JpaDialect jpaDialect;

    @Nullable
    private JpaVendorAdapter jpaVendorAdapter;

    @Nullable
    private AsyncTaskExecutor bootstrapExecutor;

    private ClreplacedLoader beanClreplacedLoader = getClreplaced().getClreplacedLoader();

    @Nullable
    private BeanFactory beanFactory;

    @Nullable
    private String beanName;

    /**
     * Raw EnreplacedyManagerFactory as returned by the PersistenceProvider.
     */
    @Nullable
    private EnreplacedyManagerFactory nativeEnreplacedyManagerFactory;

    /**
     * Future for lazily initializing raw target EnreplacedyManagerFactory.
     */
    @Nullable
    private Future<EnreplacedyManagerFactory> nativeEnreplacedyManagerFactoryFuture;

    /**
     * Exposed client-level EnreplacedyManagerFactory proxy.
     */
    @Nullable
    private EnreplacedyManagerFactory enreplacedyManagerFactory;

    /**
     * Set the PersistenceProvider implementation clreplaced to use for creating the
     * EnreplacedyManagerFactory. If not specified, the persistence provider will be
     * taken from the JpaVendorAdapter (if any) or retrieved through scanning
     * (as far as possible).
     * @see JpaVendorAdapter#getPersistenceProvider()
     * @see javax.persistence.spi.PersistenceProvider
     * @see javax.persistence.Persistence
     */
    public void setPersistenceProviderClreplaced(Clreplaced<? extends PersistenceProvider> persistenceProviderClreplaced) {
        this.persistenceProvider = BeanUtils.instantiateClreplaced(persistenceProviderClreplaced);
    }

    /**
     * Set the PersistenceProvider instance to use for creating the
     * EnreplacedyManagerFactory. If not specified, the persistence provider
     * will be taken from the JpaVendorAdapter (if any) or determined
     * by the persistence unit deployment descriptor (as far as possible).
     * @see JpaVendorAdapter#getPersistenceProvider()
     * @see javax.persistence.spi.PersistenceProvider
     * @see javax.persistence.Persistence
     */
    public void setPersistenceProvider(@Nullable PersistenceProvider persistenceProvider) {
        this.persistenceProvider = persistenceProvider;
    }

    @Override
    @Nullable
    public PersistenceProvider getPersistenceProvider() {
        return this.persistenceProvider;
    }

    /**
     * Specify the name of the EnreplacedyManagerFactory configuration.
     * <p>Default is none, indicating the default EnreplacedyManagerFactory
     * configuration. The persistence provider will throw an exception if
     * ambiguous EnreplacedyManager configurations are found.
     * @see javax.persistence.Persistence#createEnreplacedyManagerFactory(String)
     */
    public void setPersistenceUnitName(@Nullable String persistenceUnitName) {
        this.persistenceUnitName = persistenceUnitName;
    }

    @Override
    @Nullable
    public String getPersistenceUnitName() {
        return this.persistenceUnitName;
    }

    /**
     * Specify JPA properties, to be preplaceded into
     * {@code Persistence.createEnreplacedyManagerFactory} (if any).
     * <p>Can be populated with a String "value" (parsed via PropertiesEditor) or a
     * "props" element in XML bean definitions.
     * @see javax.persistence.Persistence#createEnreplacedyManagerFactory(String, java.util.Map)
     * @see javax.persistence.spi.PersistenceProvider#createContainerEnreplacedyManagerFactory(javax.persistence.spi.PersistenceUnitInfo, java.util.Map)
     */
    public void setJpaProperties(Properties jpaProperties) {
        CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.jpaPropertyMap);
    }

    /**
     * Specify JPA properties as a Map, to be preplaceded into
     * {@code Persistence.createEnreplacedyManagerFactory} (if any).
     * <p>Can be populated with a "map" or "props" element in XML bean definitions.
     * @see javax.persistence.Persistence#createEnreplacedyManagerFactory(String, java.util.Map)
     * @see javax.persistence.spi.PersistenceProvider#createContainerEnreplacedyManagerFactory(javax.persistence.spi.PersistenceUnitInfo, java.util.Map)
     */
    public void setJpaPropertyMap(@Nullable Map<String, ?> jpaProperties) {
        if (jpaProperties != null) {
            this.jpaPropertyMap.putAll(jpaProperties);
        }
    }

    /**
     * Allow Map access to the JPA properties to be preplaceded to the persistence
     * provider, with the option to add or override specific entries.
     * <p>Useful for specifying entries directly, for example via
     * "jpaPropertyMap[myKey]".
     */
    public Map<String, Object> getJpaPropertyMap() {
        return this.jpaPropertyMap;
    }

    /**
     * Specify the (potentially vendor-specific) EnreplacedyManagerFactory interface
     * that this EnreplacedyManagerFactory proxy is supposed to implement.
     * <p>The default will be taken from the specific JpaVendorAdapter, if any,
     * or set to the standard {@code javax.persistence.EnreplacedyManagerFactory}
     * interface else.
     * @see JpaVendorAdapter#getEnreplacedyManagerFactoryInterface()
     */
    public void setEnreplacedyManagerFactoryInterface(Clreplaced<? extends EnreplacedyManagerFactory> emfInterface) {
        this.enreplacedyManagerFactoryInterface = emfInterface;
    }

    /**
     * Specify the (potentially vendor-specific) EnreplacedyManager interface
     * that this factory's EnreplacedyManagers are supposed to implement.
     * <p>The default will be taken from the specific JpaVendorAdapter, if any,
     * or set to the standard {@code javax.persistence.EnreplacedyManager}
     * interface else.
     * @see JpaVendorAdapter#getEnreplacedyManagerInterface()
     * @see EnreplacedyManagerFactoryInfo#getEnreplacedyManagerInterface()
     */
    public void setEnreplacedyManagerInterface(@Nullable Clreplaced<? extends EnreplacedyManager> emInterface) {
        this.enreplacedyManagerInterface = emInterface;
    }

    @Override
    @Nullable
    public Clreplaced<? extends EnreplacedyManager> getEnreplacedyManagerInterface() {
        return this.enreplacedyManagerInterface;
    }

    /**
     * Specify the vendor-specific JpaDialect implementation to replacedociate with
     * this EnreplacedyManagerFactory. This will be exposed through the
     * EnreplacedyManagerFactoryInfo interface, to be picked up as default dialect by
     * accessors that intend to use JpaDialect functionality.
     * @see EnreplacedyManagerFactoryInfo#getJpaDialect()
     */
    public void setJpaDialect(@Nullable JpaDialect jpaDialect) {
        this.jpaDialect = jpaDialect;
    }

    @Override
    @Nullable
    public JpaDialect getJpaDialect() {
        return this.jpaDialect;
    }

    /**
     * Specify the JpaVendorAdapter implementation for the desired JPA provider,
     * if any. This will initialize appropriate defaults for the given provider,
     * such as persistence provider clreplaced and JpaDialect, unless locally
     * overridden in this FactoryBean.
     */
    public void setJpaVendorAdapter(@Nullable JpaVendorAdapter jpaVendorAdapter) {
        this.jpaVendorAdapter = jpaVendorAdapter;
    }

    /**
     * Return the JpaVendorAdapter implementation for this EnreplacedyManagerFactory,
     * or {@code null} if not known.
     */
    @Nullable
    public JpaVendorAdapter getJpaVendorAdapter() {
        return this.jpaVendorAdapter;
    }

    /**
     * Specify an asynchronous executor for background bootstrapping,
     * e.g. a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
     * <p>{@code EnreplacedyManagerFactory} initialization will then switch into background
     * bootstrap mode, with a {@code EnreplacedyManagerFactory} proxy immediately returned for
     * injection purposes instead of waiting for the JPA provider's bootstrapping to complete.
     * However, note that the first actual call to a {@code EnreplacedyManagerFactory} method will
     * then block until the JPA provider's bootstrapping completed, if not ready by then.
     * For maximum benefit, make sure to avoid early {@code EnreplacedyManagerFactory} calls
     * in init methods of related beans, even for metadata introspection purposes.
     * @since 4.3
     */
    public void setBootstrapExecutor(@Nullable AsyncTaskExecutor bootstrapExecutor) {
        this.bootstrapExecutor = bootstrapExecutor;
    }

    /**
     * Return the asynchronous executor for background bootstrapping, if any.
     * @since 4.3
     */
    @Nullable
    public AsyncTaskExecutor getBootstrapExecutor() {
        return this.bootstrapExecutor;
    }

    @Override
    public void setBeanClreplacedLoader(ClreplacedLoader clreplacedLoader) {
        this.beanClreplacedLoader = clreplacedLoader;
    }

    @Override
    public ClreplacedLoader getBeanClreplacedLoader() {
        return this.beanClreplacedLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    @Override
    public void afterPropertiesSet() throws PersistenceException {
        JpaVendorAdapter jpaVendorAdapter = getJpaVendorAdapter();
        if (jpaVendorAdapter != null) {
            if (this.persistenceProvider == null) {
                this.persistenceProvider = jpaVendorAdapter.getPersistenceProvider();
            }
            PersistenceUnitInfo pui = getPersistenceUnitInfo();
            Map<String, ?> vendorPropertyMap = (pui != null ? jpaVendorAdapter.getJpaPropertyMap(pui) : jpaVendorAdapter.getJpaPropertyMap());
            if (!CollectionUtils.isEmpty(vendorPropertyMap)) {
                vendorPropertyMap.forEach((key, value) -> {
                    if (!this.jpaPropertyMap.containsKey(key)) {
                        this.jpaPropertyMap.put(key, value);
                    }
                });
            }
            if (this.enreplacedyManagerFactoryInterface == null) {
                this.enreplacedyManagerFactoryInterface = jpaVendorAdapter.getEnreplacedyManagerFactoryInterface();
                if (!ClreplacedUtils.isVisible(this.enreplacedyManagerFactoryInterface, this.beanClreplacedLoader)) {
                    this.enreplacedyManagerFactoryInterface = EnreplacedyManagerFactory.clreplaced;
                }
            }
            if (this.enreplacedyManagerInterface == null) {
                this.enreplacedyManagerInterface = jpaVendorAdapter.getEnreplacedyManagerInterface();
                if (!ClreplacedUtils.isVisible(this.enreplacedyManagerInterface, this.beanClreplacedLoader)) {
                    this.enreplacedyManagerInterface = EnreplacedyManager.clreplaced;
                }
            }
            if (this.jpaDialect == null) {
                this.jpaDialect = jpaVendorAdapter.getJpaDialect();
            }
        }
        AsyncTaskExecutor bootstrapExecutor = getBootstrapExecutor();
        if (bootstrapExecutor != null) {
            this.nativeEnreplacedyManagerFactoryFuture = bootstrapExecutor.submit(this::buildNativeEnreplacedyManagerFactory);
        } else {
            this.nativeEnreplacedyManagerFactory = buildNativeEnreplacedyManagerFactory();
        }
        // Wrap the EnreplacedyManagerFactory in a factory implementing all its interfaces.
        // This allows interception of createEnreplacedyManager methods to return an
        // application-managed EnreplacedyManager proxy that automatically joins
        // existing transactions.
        this.enreplacedyManagerFactory = createEnreplacedyManagerFactoryProxy(this.nativeEnreplacedyManagerFactory);
    }

    private EnreplacedyManagerFactory buildNativeEnreplacedyManagerFactory() {
        EnreplacedyManagerFactory emf;
        try {
            emf = createNativeEnreplacedyManagerFactory();
        } catch (PersistenceException ex) {
            if (ex.getClreplaced() == PersistenceException.clreplaced) {
                // Plain PersistenceException wrapper for underlying exception?
                // Make sure the nested exception message is properly exposed,
                // along the lines of Spring's NestedRuntimeException.getMessage()
                Throwable cause = ex.getCause();
                if (cause != null) {
                    String message = ex.getMessage();
                    String causeString = cause.toString();
                    if (!message.endsWith(causeString)) {
                        throw new PersistenceException(message + "; nested exception is " + causeString, cause);
                    }
                }
            }
            throw ex;
        }
        JpaVendorAdapter jpaVendorAdapter = getJpaVendorAdapter();
        if (jpaVendorAdapter != null) {
            jpaVendorAdapter.postProcessEnreplacedyManagerFactory(emf);
        }
        if (logger.isInfoEnabled()) {
            logger.info("Initialized JPA EnreplacedyManagerFactory for persistence unit '" + getPersistenceUnitName() + "'");
        }
        return emf;
    }

    /**
     * Create a proxy for the given {@link EnreplacedyManagerFactory}. We do this to be able to
     * return a transaction-aware proxy for an application-managed {@link EnreplacedyManager}.
     * @param emf the EnreplacedyManagerFactory as returned by the persistence provider,
     * if initialized already
     * @return the EnreplacedyManagerFactory proxy
     */
    protected EnreplacedyManagerFactory createEnreplacedyManagerFactoryProxy(@Nullable EnreplacedyManagerFactory emf) {
        Set<Clreplaced<?>> ifcs = new LinkedHashSet<>();
        Clreplaced<?> enreplacedyManagerFactoryInterface = this.enreplacedyManagerFactoryInterface;
        if (enreplacedyManagerFactoryInterface != null) {
            ifcs.add(enreplacedyManagerFactoryInterface);
        } else if (emf != null) {
            ifcs.addAll(ClreplacedUtils.getAllInterfacesForClreplacedreplacedet(emf.getClreplaced(), this.beanClreplacedLoader));
        } else {
            ifcs.add(EnreplacedyManagerFactory.clreplaced);
        }
        ifcs.add(EnreplacedyManagerFactoryInfo.clreplaced);
        try {
            return (EnreplacedyManagerFactory) Proxy.newProxyInstance(this.beanClreplacedLoader, ClreplacedUtils.toClreplacedArray(ifcs), new ManagedEnreplacedyManagerFactoryInvocationHandler(this));
        } catch (IllegalArgumentException ex) {
            if (enreplacedyManagerFactoryInterface != null) {
                throw new IllegalStateException("EnreplacedyManagerFactory interface [" + enreplacedyManagerFactoryInterface + "] seems to conflict with Spring's EnreplacedyManagerFactoryInfo mixin - consider resetting the " + "'enreplacedyManagerFactoryInterface' property to plain [javax.persistence.EnreplacedyManagerFactory]", ex);
            } else {
                throw new IllegalStateException("Conflicting EnreplacedyManagerFactory interfaces - " + "consider specifying the 'jpaVendorAdapter' or 'enreplacedyManagerFactoryInterface' property " + "to select a specific EnreplacedyManagerFactory interface to proceed with", ex);
            }
        }
    }

    /**
     * Delegate an incoming invocation from the proxy, dispatching to EnreplacedyManagerFactoryInfo
     * or the native EnreplacedyManagerFactory accordingly.
     */
    Object invokeProxyMethod(Method method, @Nullable Object[] args) throws Throwable {
        if (method.getDeclaringClreplaced().isreplacedignableFrom(EnreplacedyManagerFactoryInfo.clreplaced)) {
            return method.invoke(this, args);
        } else if (method.getName().equals("createEnreplacedyManager") && args != null && args.length > 0 && args[0] == SynchronizationType.SYNCHRONIZED) {
            // JPA 2.1's createEnreplacedyManager(SynchronizationType, Map)
            // Redirect to plain createEnreplacedyManager and add synchronization semantics through Spring proxy
            EnreplacedyManager rawEnreplacedyManager = (args.length > 1 ? getNativeEnreplacedyManagerFactory().createEnreplacedyManager((Map<?, ?>) args[1]) : getNativeEnreplacedyManagerFactory().createEnreplacedyManager());
            return ExtendedEnreplacedyManagerCreator.createApplicationManagedEnreplacedyManager(rawEnreplacedyManager, this, true);
        }
        // Look for Query arguments, primarily JPA 2.1's addNamedQuery(String, Query)
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                Object arg = args[i];
                if (arg instanceof Query && Proxy.isProxyClreplaced(arg.getClreplaced())) {
                    // replacedumably a Spring-generated proxy from SharedEnreplacedyManagerCreator:
                    // since we're preplaceding it back to the native EnreplacedyManagerFactory,
                    // let's unwrap it to the original Query object from the provider.
                    try {
                        args[i] = ((Query) arg).unwrap(null);
                    } catch (RuntimeException ex) {
                    // Ignore - simply proceed with given Query object then
                    }
                }
            }
        }
        // Standard delegation to the native factory, just post-processing EnreplacedyManager return values
        Object retVal = method.invoke(getNativeEnreplacedyManagerFactory(), args);
        if (retVal instanceof EnreplacedyManager) {
            // Any other createEnreplacedyManager variant - expecting non-synchronized semantics
            EnreplacedyManager rawEnreplacedyManager = (EnreplacedyManager) retVal;
            retVal = ExtendedEnreplacedyManagerCreator.createApplicationManagedEnreplacedyManager(rawEnreplacedyManager, this, false);
        }
        return retVal;
    }

    /**
     * Subclreplacedes must implement this method to create the EnreplacedyManagerFactory
     * that will be returned by the {@code getObject()} method.
     * @return the EnreplacedyManagerFactory instance returned by this FactoryBean
     * @throws PersistenceException if the EnreplacedyManager cannot be created
     */
    protected abstract EnreplacedyManagerFactory createNativeEnreplacedyManagerFactory() throws PersistenceException;

    /**
     * Implementation of the PersistenceExceptionTranslator interface, as
     * autodetected by Spring's PersistenceExceptionTranslationPostProcessor.
     * <p>Uses the dialect's conversion if possible; otherwise falls back to
     * standard JPA exception conversion.
     * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
     * @see JpaDialect#translateExceptionIfPossible
     * @see EnreplacedyManagerFactoryUtils#convertJpaAccessExceptionIfPossible
     */
    @Override
    @Nullable
    public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
        JpaDialect jpaDialect = getJpaDialect();
        return (jpaDialect != null ? jpaDialect.translateExceptionIfPossible(ex) : EnreplacedyManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex));
    }

    @Override
    public EnreplacedyManagerFactory getNativeEnreplacedyManagerFactory() {
        if (this.nativeEnreplacedyManagerFactory != null) {
            return this.nativeEnreplacedyManagerFactory;
        } else {
            replacedert.state(this.nativeEnreplacedyManagerFactoryFuture != null, "No native EnreplacedyManagerFactory available");
            try {
                return this.nativeEnreplacedyManagerFactoryFuture.get();
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
                throw new IllegalStateException("Interrupted during initialization of native EnreplacedyManagerFactory", ex);
            } catch (ExecutionException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof PersistenceException) {
                    // Rethrow a provider configuration exception (possibly with a nested cause) directly
                    throw (PersistenceException) cause;
                }
                throw new IllegalStateException("Failed to asynchronously initialize native EnreplacedyManagerFactory: " + ex.getMessage(), cause);
            }
        }
    }

    @Override
    @Nullable
    public PersistenceUnitInfo getPersistenceUnitInfo() {
        return null;
    }

    @Override
    @Nullable
    public DataSource getDataSource() {
        return null;
    }

    /**
     * Return the singleton EnreplacedyManagerFactory.
     */
    @Override
    @Nullable
    public EnreplacedyManagerFactory getObject() {
        return this.enreplacedyManagerFactory;
    }

    @Override
    public Clreplaced<? extends EnreplacedyManagerFactory> getObjectType() {
        return (this.enreplacedyManagerFactory != null ? this.enreplacedyManagerFactory.getClreplaced() : EnreplacedyManagerFactory.clreplaced);
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    /**
     * Close the EnreplacedyManagerFactory on bean factory shutdown.
     */
    @Override
    public void destroy() {
        if (this.enreplacedyManagerFactory != null) {
            if (logger.isInfoEnabled()) {
                logger.info("Closing JPA EnreplacedyManagerFactory for persistence unit '" + getPersistenceUnitName() + "'");
            }
            this.enreplacedyManagerFactory.close();
        }
    }

    // ---------------------------------------------------------------------
    // Serialization support
    // ---------------------------------------------------------------------
    private void readObject(ObjectInputStream ois) throws IOException, ClreplacedNotFoundException {
        throw new NotSerializableException("An EnreplacedyManagerFactoryBean itself is not deserializable - " + "just a SerializedEnreplacedyManagerFactoryBeanReference is");
    }

    protected Object writeReplace() throws ObjectStreamException {
        if (this.beanFactory != null && this.beanName != null) {
            return new SerializedEnreplacedyManagerFactoryBeanReference(this.beanFactory, this.beanName);
        } else {
            throw new NotSerializableException("EnreplacedyManagerFactoryBean does not run within a BeanFactory");
        }
    }

    /**
     * Minimal bean reference to the surrounding AbstractEnreplacedyManagerFactoryBean.
     * Resolved to the actual AbstractEnreplacedyManagerFactoryBean instance on deserialization.
     */
    @SuppressWarnings("serial")
    private static clreplaced SerializedEnreplacedyManagerFactoryBeanReference implements Serializable {

        private final BeanFactory beanFactory;

        private final String lookupName;

        public SerializedEnreplacedyManagerFactoryBeanReference(BeanFactory beanFactory, String beanName) {
            this.beanFactory = beanFactory;
            this.lookupName = BeanFactory.FACTORY_BEAN_PREFIX + beanName;
        }

        private Object readResolve() {
            return this.beanFactory.getBean(this.lookupName, AbstractEnreplacedyManagerFactoryBean.clreplaced);
        }
    }

    /**
     * Dynamic proxy invocation handler for an {@link EnreplacedyManagerFactory}, returning a
     * proxy {@link EnreplacedyManager} (if necessary) from {@code createEnreplacedyManager} methods.
     */
    @SuppressWarnings("serial")
    private static clreplaced ManagedEnreplacedyManagerFactoryInvocationHandler implements InvocationHandler, Serializable {

        private final AbstractEnreplacedyManagerFactoryBean enreplacedyManagerFactoryBean;

        public ManagedEnreplacedyManagerFactoryInvocationHandler(AbstractEnreplacedyManagerFactoryBean emfb) {
            this.enreplacedyManagerFactoryBean = emfb;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            try {
                if (method.getName().equals("equals")) {
                    // Only consider equal when proxies are identical.
                    return (proxy == args[0]);
                } else if (method.getName().equals("hashCode")) {
                    // Use hashCode of EnreplacedyManagerFactory proxy.
                    return System.idenreplacedyHashCode(proxy);
                } else if (method.getName().equals("unwrap")) {
                    // Handle JPA 2.1 unwrap method - could be a proxy match.
                    Clreplaced<?> targetClreplaced = (Clreplaced<?>) args[0];
                    if (targetClreplaced == null) {
                        return this.enreplacedyManagerFactoryBean.getNativeEnreplacedyManagerFactory();
                    } else if (targetClreplaced.isInstance(proxy)) {
                        return proxy;
                    }
                }
                return this.enreplacedyManagerFactoryBean.invokeProxyMethod(method, args);
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }
}

See More Examples