Get user that runs an asynchronous method

delegatingsecuritycontextasynctaskexecutor
mode_inheritablethreadlocal

I'm trying to get the user from spring context in an application spring as follows:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

The problem is that the methods are asynchronous, with annotation @Async:

@Service
@Transactional
public class FooServiceImpl implements FooService {

    @Async("asyncExecutor")
    public void fooMethod(String bar) {
        System.out.println("Foo: " + bar);
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    }
}

The problem is that the asynchronous method runs in another thread in another context. I have tried using a SecurityContextDelegationAsyncTaskExecutor. The user is propagated to the asynchronous method but if I logout, the user in the asynchronous method is null. This is my code:

@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {

    @Override
    @Bean(name = "asyncExecutor")
    public Executor getAsyncExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setMaxPoolSize(1);
        executor.setThreadGroupName("MyCustomExecutor");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setBeanName("asyncExecutor");
        executor.initialize();

        return new DelegatingSecurityContextAsyncTaskExecutor(executor);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }
}

I have also used a ThreadPoolTaskExecutor and setting the context of spring security with "MODE_INHERITABLETHREADLOCAL". But the result is the same. The user is not null if I am logged into the application. If I'm not logged the user is null. I really want the user that runs the method, not the current user logged. My code:

@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {

    @Override
    @Bean(name = "asyncExecutor")
    public Executor getAsyncExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setMaxPoolSize(1);
        executor.setThreadGroupName("MyCustomExecutor");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setBeanName("asyncExecutor");
        executor.initialize();

        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }

}

@Configuration
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter({Controller.class}), useDefaultFilters = true)
public class MvcConfiguration extends WebMvcConfigurationSupport {

    //others beans

    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean() {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
        methodInvokingFactoryBean.setTargetMethod("setStrategyName");
        methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
        return methodInvokingFactoryBean;
    }
}

Finally, I found this post . I try with a CustomThreadPoolTaskExecutor overriding execute method. But this method never runs. The method of ThreadPoolTaskExecutor that run is:

<T> Future<T> submit(Callable<T> task)

My code:

@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {

    @Override
    @Bean(name = "asyncExecutor")
    public Executor getAsyncExecutor() {

        CustomThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor();

        executor.setMaxPoolSize(1);
        executor.setThreadGroupName("MyCustomExecutor");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setBeanName("asyncExecutor");
        executor.initialize();

        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }

}

public class CustomThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

    private static final long serialVersionUID = 1L;

    @Override
    public void execute(final Runnable r) {
        final Authentication a = SecurityContextHolder.getContext().getAuthentication();

        super.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    SecurityContext ctx = SecurityContextHolder.createEmptyContext();
                    ctx.setAuthentication(a);
                    SecurityContextHolder.setContext(ctx);
                    r.run();
                } finally {
                    SecurityContextHolder.clearContext();
                }
            }
        });
    }
}

My custom executes method never run. What am I doing wrong in the Custom ThreadPoolTaskExecutor? Some other way to get the user that runs an asynchronous method. No the current user of context.

Maybe this helps to get execute-method called (worked in my case):

@Override
@Bean(name = "asyncExecutor")
public Executor getAsyncExecutor() {

    CustomThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor();

    executor.setMaxPoolSize(1);
    executor.setThreadGroupName("MyCustomExecutor");
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.setBeanName("asyncExecutor");
    executor.initialize();

    return new DelegatingSecurityContextAsyncTaskExecutor(executor);
}

Getting Started, You will build a lookup service that queries GitHub user information and retrieves data through GitHub's API. One approach to scaling services is to run� The task calculates the sum of the integers between 1 and 1,000,000. As the output from the example shows, the task executed by calling the RunSynchronously method runs on the application thread, while the asynchronous task does not.

Spring support for sending asynchronous requests with propagated SecurityContext. From a programming model perspective, the new capabilities appear deceptively simple. You can access to user info in async methods by setting security content strategy name in your security configurer class:

@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {

    public SpringAsyncConfig() {
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }

}

Using Task.Run in Conjunction with Async/Await, The async/await approach in C# is great in part because it isolates the But if it is a long-running operation, you may need to find a way to make it asynchronous. This is especially so for applications that have a graphical user The Run method queues code to run on a different thread (usually from the� There is an easy solution: Pass the result of your method to the Task object's static FromResult method, which will load the Task object's Result property (which, really, is what all that async/await processing depends on). Here's an example of some code that creates a Customer object:

This is my implementation, I've used TaskDecorator to copy the SecurityContext in the new thread, the new thread runs with this new SecurityContext even the user logout during the execution of the async task.

Xml declaration for executor

<bean id="securityContextCopyingDecorator" class="com.myapp.task.SecurityContextCopyingDecorator"/>

<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="1"/>
    <property name="maxPoolSize" value="5"/>
    <property name="queueCapacity" value="100"/> 
    <property name="taskDecorator" ref="securityContextCopyingDecorator"/>   
</bean>

<task:annotation-driven executor="threadPoolTaskExecutor"/>

this is the class SecurityContextCopyingDecorator

package com.myapp.task;

import org.springframework.core.task.TaskDecorator;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

public class SecurityContextCopyingDecorator implements TaskDecorator {

    @Override
      public Runnable decorate(Runnable runnable) {
        final Authentication a = SecurityContextHolder.getContext().getAuthentication();
        return () -> {
          try {
              SecurityContext ctx = SecurityContextHolder.createEmptyContext();
              ctx.setAuthentication(a);
              SecurityContextHolder.setContext(ctx);
            runnable.run();
          } finally {
              SecurityContextHolder.clearContext();
          }
        };
      }


}

finally annotate some method to use threadPoolTaskExecutor in async mode

@Async
public void myAsyncMethod() {

}

Asynchronous programming in C#, The Task asynchronous programming model (TAP) provides an but executes in a much more complicated order based on external For a parallel algorithm, you'd need multiple cooks (or threads). you write client programs, you want the UI to be responsive to user input. You'll get a hot breakfast. The preceding method has the async modifier in its signature. That signals to the compiler that this method contains an await statement; it contains asynchronous operations. This method represents the task that toasts the bread, then adds butter and jam. This method returns a Task<TResult> that represents the composition of those three

Asynchronous programming, Learn about the C# language-level asynchronous programming (downloading data asynchronously) without getting bogged down in use async and await without Task.Run . You should not use the Task Parallel Library. that the user // sees the progress bar before execution of this method is yielded. We use the async and await keywords to asynchronously run a method. The program begins a long-running method (HandleFileAsync). Part 1: We create a Task instance by calling HandleFileAsync. The task starts, and (later in Main) we call Wait() for it to finish. Part 2: This async method displays a status message, and does some long-running

C# async, await Examples, Allocate: This method does a slow-running computation. But when run asynchronously, it does not cause the program to freeze. Result: Many user inputs can be� When an application calls an asynchronous method, it can simultaneously execute along with the execution of the asynchronous method that performs its task. An asynchronous method runs in a thread separate from the main application thread. The processing results are fetched through another call on another thread.

Async/await, It's just a more elegant syntax of getting the promise result than promise.then As said, await only works inside an async function. read our JSON let response = await fetch('/article/promise-chaining/user.json'); let user� Running an async operation from a synchronous function Posted by Sanjeev October 22, 2014 October 22, 2014 Leave a comment on Running an async operation from a synchronous function One of those things that you almost never need, but if you need it, you need it.

Comments
  • In my question I use DelegatingSecurityContextAsyncTaskExecutor too. Thanks for de answer. My final solution was to pass the user as a parameter.