-
Bug Report
-
Resolution: Unresolved
-
L3 - Default
-
None
-
None
-
None
Environment (Required on creation):
- Spring Boot Starter
- Spin
Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):
Spring offers Developer Tools [1] that can reload resources during development. This is implemented by an additional classloader (`RestartClassLoader`) which can result in problems with object deserialization.
Steps to reproduce (Required on creation):
- Setup a process with asynchronous continuation on service task that fetches a Java Object and deserializes it via the spin library. See below or check the attached applicationĀ example-classloading-issue.zip
- Java Object (doesn't implement Serializable)
public class MyPojo { protected String bar; public String getBar() { return bar; } }
- Java delegate
@Component public class Service implements JavaDelegate { public void execute(DelegateExecution delegateExecution) { MyPojo myPojo = (MyPojo) delegateExecution.getVariable("foo"); } }
- Java Object (doesn't implement Serializable)
- Add the process to Spring Boot Starter app
- Add `spring-boot-devtools` library to the pom.xml
- Start the application via IDE (which will start it with enabled Spring Dev Tools)
- Start a process instance
Observed Behavior (Required on creation):
When the Job executor executes the service task, the job fails with
java.lang.ClassCastException: com.example.workflow.MyPojo cannot be cast to com.example.workflow.MyPojo at com.example.workflow.ServiceB.execute(ServiceB.java:28) ~[classes/:na] at org.camunda.bpm.engine.impl.bpmn.delegate.JavaDelegateInvocation.invoke(JavaDelegateInvocation.java:40) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:58) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocationInContext(DefaultDelegateInterceptor.java:92) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:63) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:118) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:102) ~[camunda-engine-7.15.0.jar:7.15.0] ... at org.camunda.bpm.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:81) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:40) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.persistence.entity.JobEntity.execute(JobEntity.java:134) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:110) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:43) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:28) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:110) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:72) ~[camunda-engine-spring-7.15.0.jar:7.15.0] at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.4.jar:5.3.4] at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:70) ~[camunda-engine-spring-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:70) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.interceptor.CommandCounterInterceptor.execute(CommandCounterInterceptor.java:35) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:57) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.executeJob(ExecuteJobsRunnable.java:110) ~[camunda-engine-7.15.0.jar:7.15.0] at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:71) ~[camunda-engine-7.15.0.jar:7.15.0] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
Expected behavior (Required on creation):
The job is successfully executed.
Root Cause (Required on prioritization):
- The Java class MyPojo is loaded with the `RestartClassLoader` as the beans are loaded via the applicationContextClassloader which is restart classloader when the dev tools are enabled to reload the classes if necessary
- The variable is deserialized and loaded with `SpinObjectValueSerializer#deserializeFromByteArray` that uses the classloader of the current thread `sun.misc.Launcher` (parent of the RestartClassLoader). For details have a look at `DomXmlDataFormatMapper#mapInternalToJava` -> `SpinReflectUtil.loadClass`.
Solution Ideas (Optional):
- Try to use the process engine configuration classloader instead of the current thread's classloader
- ...
Hints (Optional):
- Similar issue of a classloading problem when dev tools are enabled -
CAM-9043
[1] https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using.devtools
This is the controller panel for Smart Panels app
- is related to
-
CAM-9043 Classloading issues when using Spring Boot Starter and Spring Dev Tools
- Closed