ClassNotFoundException when using TaskManager in Data Center

We’re experiencing issues with TaskManager on a DC 8.5 instance. Apparently the Callables we submit to the TaskManager are serialized into a queue and later deserialized by the LocalQCacheOpReader. Since this object runs within Jira’s own context, it cannot see classes provided by installed plugins (like our implementation of TaskContext).

My presumption is that since reading the task fails with an Exception, the task is also not even executed anymore, which is a serious problem.

Apparently all of this is not documented anywhere, nor has TaskManager been deprecated, to my knowledge. Are we supposed to replace all usages of TaskManager with JobRunners? Has anyone else found a workaround for this problem? We have quite a few apps using tasks and it would be a lot of work to change/test/etc. them all.

Stack trace looks like this:

localq-reader-16 ERROR      [c.a.j.c.distribution.localq.LocalQCacheOpReader] Critical state of local cache replication queue - cannot peek from queue: [queueId=queue_blablanode_198e0a0290ffd6adb75ab5658, queuePath=/opt/jira/data/localq/queue_blablanode_0a0290ffd6adb75ab5658], error: Failed to peek.
com.squareup.tape.FileException: Failed to peek.
	at com.squareup.tape.FileObjectQueue.peek(FileObjectQueue.java:59)
	at com.atlassian.jira.cluster.distribution.localq.tape.TapeLocalQCacheOpQueue.peek(TapeLocalQCacheOpQueue.java:198)
	at com.atlassian.jira.cluster.distribution.localq.tape.TapeLocalQCacheOpQueue.peekOrBlock(TapeLocalQCacheOpQueue.java:216)
	at com.atlassian.jira.cluster.distribution.localq.LocalQCacheOpQueueWithStats.peekOrBlock(LocalQCacheOpQueueWithStats.java:199)
	at com.atlassian.jira.cluster.distribution.localq.LocalQCacheOpReader.peekOrBlock(LocalQCacheOpReader.java:156)
	at com.atlassian.jira.cluster.distribution.localq.LocalQCacheOpReader.run(LocalQCacheOpReader.java:72)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: java.lang.ClassNotFoundException: my.package.MyTask
	at com.atlassian.jira.cluster.distribution.localq.tape.TapeLocalQCacheOpConverter.from(TapeLocalQCacheOpConverter.java:25)
	at com.atlassian.jira.cluster.distribution.localq.tape.TapeLocalQCacheOpConverter.from(TapeLocalQCacheOpConverter.java:16)
	at com.squareup.tape.FileObjectQueue.peek(FileObjectQueue.java:57)
	... 10 more
Caused by: java.lang.ClassNotFoundException: my.package.MyTask

It seems like Atlassian was aware of this problem and moved the TaskContext for their own Jira Importer from the app into Jira core as a workaround (something we cannot do; looks like TaskContexts are useless then). See javadoc comment on EmptyTaskContext:

This class is moved from JIM to here as a workaround for solving ClassNotFoundException related to replication over RMI.

  • See JRASERVER-64286 for details.