The Spring Framework provides abstractions for asynchronous execution of tasks by using
the TaskExecutor interface. Executors are the Java SE name for the concept of thread pools. Spring’s
TaskExecutor interface is identical to the java.util.concurrent.Executor interface. The TaskExecutor
was originally created to give other Spring components an abstraction for thread pooling where
needed. Spring includes a number of pre-built implementations of TaskExecutor but it is the DefaultManagedTaskExecutor that is most useful for integration
with CICS as it looks up the application server's defaultExecutor - which in CICS Liberty is
designed to provide CICS enabled threads.
About this task
To run asynchronous tasks in your Spring Boot application by using CICS enabled threads, there
are two options. You can either set an Asynchronous Executor for the whole application, or you can
choose to specify an AsyncExecutor on a per method basis. If all the tasks you spawn asynchronously
require CICS services, then setting the Asynchronous Executor for the whole application is the
simplest approach. Otherwise, you need to specify the Asynchronous Executor to use for each and
every method where you require asynchronous capability. Here, we demonstrate the whole application
approach.
Procedure
-
On your main Spring Boot Application class add the @EnableAsync annotation, implement the
interface AsyncConfigurer, and override the getAsyncExecutor() and AsyncUncaughtExceptionHandler methods. Ensure you return an instance of the
DefaultManagedTaskExecutor in the getAsyncExecutor() method as this obtains new threads from
Liberty's defaultExecutor, which in turn is configured to return CICS enabled threads. For more
information about the AsyncConfigurer, see the AsyncConfigurer in the Spring Boot documentation. For usage examples, see EnableAsync in the Spring Boot documentation.
@SpringBootApplication
@EnableAsync
public class MyApplication implements AsyncConfigurer
{
public static void main(String[] args)
{
SpringApplication.run(MyApplication.class, args);
}
@Override
@Bean(name = "CICSEnabledTaskExecutor")
public Executor getAsyncExecutor()
{
return new DefaultManagedTaskExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler()
{
return new CustomAsyncExceptionHandler();
}
}
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler
{
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj)
{
System.out.println("Exception Cause - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : obj)
{
System.out.println("Parameter value - " + param);
}
}
}
- Add the @Async annotation to either: a class in your application if you wish to run all
methods on that class asynchronously, or to individual methods that you wish to run asynchronously.
i.e.
@Async("CICSEnabledTaskExecutor")
- Add the concurrent-1.0 feature to server.xml