Multithreading with Executor Service in IBM Liberty Profile

1k views Asked by At

I'm doing some tests using the ExecutorService to perform multithreading inside Liberty. From my tests it seems that the only way to start a thread that can use JCICS APi ( for example create a new TSQ ) is to use the static method

CICSExecutorService.runAsCics(task1)

If I start a thread in another way, for example:

// in this way, the OSGi should create an instance of CICSExecutorService automatically
ExecutorService cicsExecutor = Executors.newFixedThreadPool(1); 
cicsExecutor .submit(task1);

the thread couldn't use JCICS APi; in particoular I get this error:

java.util.concurrent.ExecutionException: com.ibm.cics.server.CicsRuntimeException: DTCTSQ_READITEM: 
                                            No JCICS context is associated with the current thread. 

Is that correct? Thanks.

2

There are 2 answers

1
Ivan Hargreaves On

That's correct, submitting your runnable/callable (task1) to your own newly created Executor will not run on a CICS capable thread (nor a Liberty managed thread).

If you are on CICS TS v5.3 or later then a number of methods are available, you can use the CICSExecutorService.runAsCICS() which is optimised to use Liberty's Managed Executor. You can look-up Liberty's Managed Executor from OSGi services directly, or you can @Inject an instance of the Executor and add the Liberty concurrent-1.0 feature to your server.xml (see later answer for details).

If you are on a release prior to v5.3 then the CICSExecutorService.runAsCICS() method is available, but it will not integrate with Liberty's Managed Executor and so you will be restricted to JCICS operations only and Java EE (Liberty) function will not be available in that runnable/callable task.

0
Andy Guibert On

The trick is to use a managed executor (i.e. ManagedExecutorService) which will allow the work you submit to it to run on Liberty threads, as opposed to using an unmanaged executor (e.g. Executors.newFixedThreadPool(1)) which will run work on un-managed threads that do not have the necessary context to perform the operation.

To obtain a ManagedExecutorService you need to:

  1. Enable the concurrent-1.0 feature in your server.xml

  2. Inject or lookup the executor by doing:

@Inject
ManagedExecutorService exec;

// or

// NOTE: This also requires the jndi-1.0 feature to be enabled
ManagedExecutorService exec = InitialContext.doLookup("java:comp/ManagedExecutorService");