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
19
View Source File : EntityManagerFactoryBuilder.java
License : Apache License 2.0
Project Creator : yuanmabiji
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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