是 it/How 从托管 Spring bean 向线程提供 SecureContext

Is it/How to provide SecureContext to a Thread from a managed Spring bean

我希望能够异步启动 Alfresco 节点的创建以防止创建瓶颈。

为此,我正在尝试使用 ScheduledExecutorService 初始化值 10。

执行处理如下:

来自我的 UploadServlet --> (public) UploadManager#createNodeRef(SOME_PARAMS) --> (私有同步) UploadManager#createNodeRef(SOME_PARAMS)

交易在内部管理 UploadServlet

代码:

private synchronized NodeRef createNodeRef(ARGS) {
  //
  // Creation Code using other Alfresco/Spring beans
  //
  return RETURN_VALUE;
}

异步代码(我正在尝试做的)

    private NodeRef makeAsyncNodeCreation(ARGS) {
    final ScheduledFuture<NodeRef> scheduledFuture = nodeCreationExecutor.schedule(new Callable<NodeRef>() {
        @Override
        public NodeRef call() throws Exception {
            // HERE I MAKE THE EFFECTIVE NODE CREATION
            return createNodeRef(filename, type, parentNode, label, kinematic);
        }
    }, MAX_NODE_CREATION_DELAY_IN_SECONDS, SECONDS);

    try {
        return scheduledFuture.get();
    } catch (InterruptedException e) {
        throw new AsyncNodeCreationException(e);
    } catch (ExecutionException e) {
        throw new AsyncNodeCreationException(e);
    }
}

然后public方法

public NodeRef create(ARGS) {
    return makeAsyncNodeCreation(ARGS);
}

问题

我有以下异常

net.sf.acegisecurity.AuthenticationCredentialsNotFoundException: A valid SecureContext was not provided in the RequestContext

我的问题 为什么我的异步调用中不再存在 SecureContext?

因为 SecurityContextSecurityContextHolder 保存在 ThreadLocal 变量(默认策略)中,因此是当前线程,您需要将 SecurityContext 传递给 Callable 因为它是 运行 在不同的线程中,然后将其注入到 SecurityContextHolder.

中它自己的 ThreadLocal

我希望这个解决方案适用于 Acegi Security :

 // Get the SecurityContext hold by the main thread
 final SecurityContext securityContext = SecurityContextHolder.getContext();

 final ScheduledFuture<NodeRef> scheduledFuture = nodeCreationExecutor.schedule(new Callable<NodeRef>() {

  @Override
   public NodeRef call() throws Exception {

    // Inject the securityContext 
    SecurityContextHolder.setContext(securityContext);

    // HERE I MAKE THE EFFECTIVE NODE CREATION
    NodeRef noderef = createNodeRef(filename, type, parentNode, label, kinematic);

    // Cleaning...the thread may be recycled
    SecurityContextHolder.setContext(null);

    return noderef;

 }
}, MAX_NODE_CREATION_DELAY_IN_SECONDS, SECONDS);