Spring Batch serialization problem when using Jackson - java

While upgrading an application from Spring Boot 1.3.x to 2.1.x I encountered a problem with Spring Batch. Apparently, Spring Batch needs to serialize its execution context and used XStream so far, but switched to Jackson sometime in the version history.
Now, I get an exception when running a job:
2019-10-08 15:50:58:630 ERROR [main] [:] o.s.b.c.j.AbstractJob [] Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:142) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:313) [spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:144) [spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:137) [spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
[…]
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: Ended flow=synchronizeBasicCustomerJob at state=synchronizeBasicCustomerJob.writeJobIntoJobContextStep0 with exception
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:178) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:136) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
... 41 more
Caused by: java.lang.IllegalArgumentException: Could not serialize the execution context
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.serializeContext(JdbcExecutionContextDao.java:306) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.updateExecutionContext(JdbcExecutionContextDao.java:146) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.repository.support.SimpleJobRepository.updateExecutionContext(SimpleJobRepository.java:216) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_202]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_202]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_202]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_202]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at com.sun.proxy.$Proxy242.updateExecutionContext(Unknown Source) ~[?:?]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:159) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:136) ~[spring-batch-core-4.1.2.RELEASE.jar:4.1.2.RELEASE]
... 41 more
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: org.springframework.batch.core.JobExecution["stepExecutions"]->java.util.Collections$UnmodifiableRandomAccessList[0]->org.springframework.batch.core.StepExecution["jobExecution"]->org.springframework.batch.core.JobExecution["stepExecutions"]->java.util.Collections$UnmodifiableRandomAccessList[0]->org.springframework.batch.core.StepExecution["jobExecution"]->org.springframework.batch.core.JobExecution["stepExecutions"]->java.util.Collections$UnmodifiableRandomAccessList[0]->org.springframework.batch.core.StepExecution["jobExecution"]->org.springframework.batch.core.JobExecution["stepExecutions"]->…
The cause is pretty straightforward: The entity JobExecution has a list of StepExecutions and StepExecution has a backreference to JobExecution, which is cyclic, which causes Jackson to throw this ugly error.
The recommended solution to this problem seems to be to annotate the classes to be serialized with Jackson annotations (#JsonManagedReference and #JsonBackReference). But that is not possible in this context, as the offending classes are Spring Batch's.
Another solution is to configure another ExecutionContextSerializer, i.e. the XStreamExecutionContextStringSerializer. This solution works for me, but the XStreamExecutionContextStringSerializer class is deprecated and I'd rather not use that one.
Other people (Migration to Spring Boot 2 and using Spring Batch 4) have the reverse problem: In their case the deserialization of the persisted execution context fails because it was written by XStream and now can not be read by Jackson. But in my case, the serialization fails, so this is not a compatibility issue between XStream and Jackson.
What am I doing wrong?

As I stated in the comments section, you can use Jackson MixIns to address your issue since you don't have access to the spring batch source code in your project.
It would work like
public abstract class JobExecutionMixin {
#JsonManagedReference
private Collection<StepExecution> stepExecutions;
}
And for the back reference:
public abstract class StepExecutionsMixin {
#JsonBackReference
private final JobExecution jobExecution;
}
And then, you will have to implement the ObjectMapper bean in your spring boot app with something like:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(org.springframework.batch.core.StepExecutions.class, StepExecutionsMixin.class);
mapper.addMixInAnnotations(org.springframework.batch.core.JobExecution.class, JobExecutionMixin.class);

Related

Spring `superinterface check failed` when using Java modules (for Axon Framework Spring Boot app)

I am currently experimenting with Spring Boot, the Axon Framework and java modules (using JDK 17).
I have created a repo to illustrate the problem: here
The problem is that the application does not start and I get the exception as follows:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accountViewProjection' defined in file [C:\workspace\axon\_issue_replication_repos\axon-module-error\axon-example-app\build\classes\java\main\io\github\vab2048\axon\example_bug\app\query\account\AccountViewProjection.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.IllegalAccessError-->superinterface check failed: class io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection$$EnhancerBySpringCGLIB$$159eee6a (in module io.github.vab2048.axon.example_bug.app) cannot access class org.springframework.aop.framework.Advised (in unnamed module #0x732d0d24) because module io.github.vab2048.axon.example_bug.app does not read unnamed module #0x732d0d24
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.20.jar:na]
at spring.context#5.3.20/org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.20.jar:na]
at spring.context#5.3.20/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.20.jar:na]
at spring.boot#2.7.0/org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.0.jar:na]
at spring.boot#2.7.0/org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.0.jar:na]
at spring.boot#2.7.0/org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.0.jar:na]
at spring.boot#2.7.0/org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.0.jar:na]
at spring.boot#2.7.0/org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar:na]
at spring.boot#2.7.0/org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar:na]
at io.github.vab2048.axon.example_bug.app/io.github.vab2048.axon.example_bug.app.AxonApplication.main(AxonApplication.java:10) ~[main/:na]
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.IllegalAccessError-->superinterface check failed: class io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection$$EnhancerBySpringCGLIB$$159eee6a (in module io.github.vab2048.axon.example_bug.app) cannot access class org.springframework.aop.framework.Advised (in unnamed module #0x732d0d24) because module io.github.vab2048.axon.example_bug.app does not read unnamed module #0x732d0d24
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:209) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110) ~[spring-aop-5.3.20.jar:5.3.20]
at org.axonframework.spring#4.5.9/org.axonframework.spring.config.AbstractAnnotationHandlerBeanPostProcessor.createAdapterProxy(AbstractAnnotationHandlerBeanPostProcessor.java:190) ~[axon-spring-4.5.9.jar:na]
at org.axonframework.spring#4.5.9/org.axonframework.spring.config.AbstractAnnotationHandlerBeanPostProcessor.postProcessAfterInitialization(AbstractAnnotationHandlerBeanPostProcessor.java:89) ~[axon-spring-4.5.9.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808) ~[spring-beans-5.3.20.jar:na]
at spring.beans#5.3.20/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.20.jar:na]
... 15 common frames omitted
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.IllegalAccessError-->superinterface check failed: class io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection$$EnhancerBySpringCGLIB$$159eee6a (in module io.github.vab2048.axon.example_bug.app) cannot access class org.springframework.aop.framework.Advised (in unnamed module #0x732d0d24) because module io.github.vab2048.axon.example_bug.app does not read unnamed module #0x732d0d24
at spring.core#5.3.20/org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:512) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[spring-core-5.3.20.jar:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at spring.core#5.3.20/org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572) ~[spring-core-5.3.20.jar:na]
at spring.core#5.3.20/org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:419) ~[spring-core-5.3.20.jar:na]
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:57) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:206) ~[spring-aop-5.3.20.jar:5.3.20]
... 21 common frames omitted
Caused by: java.lang.IllegalAccessError: superinterface check failed: class io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection$$EnhancerBySpringCGLIB$$159eee6a (in module io.github.vab2048.axon.example_bug.app) cannot access class org.springframework.aop.framework.Advised (in unnamed module #0x732d0d24) because module io.github.vab2048.axon.example_bug.app does not read unnamed module #0x732d0d24
at java.base/java.lang.ClassLoader.defineClass0(Native Method) ~[na:na]
at java.base/java.lang.System$2.defineClass(System.java:2307) ~[na:na]
at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2439) ~[na:na]
at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2416) ~[na:na]
at java.base/java.lang.invoke.MethodHandles$Lookup.defineClass(MethodHandles.java:1843) ~[na:na]
at java.base/jdk.internal.reflect.GeneratedMethodAccessor33.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at spring.core#5.3.20/org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:507) ~[spring-core-5.3.20.jar:na]
... 35 common frames omitted
The offending code seems to to be in io.github.vab2048.axon.example_bug.app.query.account.AccountViewProjection:
#QueryHandler
public AccountView getAccount(GetAccountView query) {
log.debug("Handling: {}", query);
return repository.findById(query.id()).orElseThrow();
}
It is the Axon annotation #QueryHandler which causes it (you can verify this by commenting it out and then everything works). This is strange because none of the other Axon annotations cause this problem. The package itself is both exported and open in the module-info.java file.
What am I doing wrong? I am aware there may be command line arguments which may be added to solve this issue but am not sure what exactly to use (ideally I shouldn't have to give any command line arguments at all).
I am somewhat in doubt about posting this as an answer, but I will do it regardless.
Have you tried removing Spring AOP from the mix?
It seems like Spring AOP is making some inner classes that cause the IllegalAccessError, not so much Axon Framework.
If this solves the issue, I'd wager there's something to be done with Spring AOP to make this work.
Sadly, this isn't my forte, so I'd have to investigate what kind of settings, if any, would help in that perspective.

Spring data hibernate upsert transaction error #TransactionalEventListener and #Transactinal

I have error with transaction handling in spring data.
Spring boot version with correlating spring data - 2.3.7.
Java - 11
I have a method in my service class(annotated as a Service)
#Transactional
public void incrementSomething(SomeData data) {
myRepository.someIncrement(data);
}
My repository(I wanted to have upsert operation):
#Repository
public interface MyRepository extends PagingAndSortingRepository<SomeData, Long> {
#Transactional
#Modifying
#Query(value = "INSERT INTO my_table (.....) VALUES (.....) " +
"ON CONFLICT ON CONSTRAINT some_contraint DO UPDATE " +
"set something = my_table.something + 1", nativeQuery = true)
public void someIncrement(#Param("someparam") String data);
However I have a strange exception occurring(I have enabled TRACE transaction in springframework).
Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.someIncrement] after exception: javax.persistence.TransactionRequiredException: Executing an update/delete query
I have no idea why is it happening, because I can see the logs that transaction started, and then completing transaction is happening with error. I have tried to look for similar errors on StackOverflow or similar pages, however none of them works.
Do You know why does this error occur? And how to fix it?
PS:
My Transactional method is from:
import org.springframework.transaction.annotation.Transactional;
Stacktrace:
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:403)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:531)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy222.incrementCounter(Unknown Source)
...
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
...
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:305)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:190)
at org.springframework.transaction.event.ApplicationListenerMethodTransactionalAdapter$TransactionSynchronizationEventAdapter.processEvent(ApplicationListenerMethodTransactionalAdapter.java:129)
at org.springframework.transaction.event.ApplicationListenerMethodTransactionalAdapter$TransactionSynchronizationEventAdapter.afterCompletion(ApplicationListenerMethodTransactionalAdapter.java:118)
at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCompletion(TransactionSynchronizationUtils.java:171)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.invokeAfterCompletion(AbstractPlatformTransactionManager.java:989)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(AbstractPlatformTransactionManager.java:964)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:785)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:633)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:386)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
...
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
...
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:413)
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1668)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:238)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 56 common frames omitted
UPDATE 1:
I have added tests with test containers and the same postgres version. I have verified that running the class which invokes this method works just as expected. The problem starts with the class before -> which sends an event and the event handler(annotated as #TransactionalEventListener) receives it after the commit and then the same path is being invoked and exception occurs.
So currently for me it looks like #TransactionalEventListener doesn't work well with #Transactional.
UPDATE 2:
It works only when #Transaction(propagation = REQUIRES_NEW) is set up(as stated in the comments. However I would like to understand why is that. Normal #Transaction works the same as #Transaction(propagation = REQUIRES_NEW) when no transaction is running and it is directly this case. I am still unable to tell why we need propagation requires new and no simple transactional.
I think you need to create a new transaction (#Transactional(propagation = REQUIRES_NEW) when invoking such services from within a transaction listener.

#Transactional works on public method in service but not with protected method

I am trying to call a service method(B) from another service method(A) from same service impl class. Now when I put #Transactional on #A, everything works fine, but when I put the same on #B everything breaks apart. And the error that I get is
Exception: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.childs, could not initialize proxy - no Session
at <reference to my code>
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at <reference to my code>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_162]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_162]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:223) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:483) ~[spring-cloud-context-2.0.0.RC1.jar:2.0.0.RC1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at <reference to my code>
at <reference to my code>
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) ~[na:1.8.0_162]
at <reference to my code>
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.childs, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:277) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at <reference to my code>
... 24 common frames omitted
My class call structure is like this
A = fail case
B = success case
doProcessS() ==> public void
doSubProcessS() ==> protected void
I am using SpringBoot 2.0.0.RELEASE
I want to execute everything in 'A' way and not 'B' as I want to execute another check in doProcessS() based on data committed to DB in doSubProcess()
#Transactional is based on Spring AOP
Spring AOP does not work in self-invocation method (Within the same class)
You can fix it by mark your doProcessS() in ServiceImpl as #Transactional
Reference
This means that method calls on that object reference will be calls on
the proxy, and as such the proxy will be able to delegate to all of
the interceptors (advice) that are relevant to that particular method
call. However, once the call has finally reached the target object,
the SimplePojo reference in this case, any method calls that it may
make on itself, such as this.bar() or this.foo(), are going to be
invoked against the this reference, and not the proxy. This has
important implications. It means that self-invocation is not going to
result in the advice associated with a method invocation getting a
chance to execute.
If you want to separate your transaction, delegate doSubProcessS to other class and mark it propagation type as Propagation.REQUIRES_NEW

ClassFormatError: Duplicate method name&signature from EnhancerBySpringCGLIB

I"m really stumped here. I've upgraded our Spring libraries from 4.0.6 to 4.3.2. One of our tests fail when running with 4.3.2. This is the code in question:
#Bean(name = SCHEDULER_FACTORY)
public SchedulerFactoryBean getSchedulerFactory()
{
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(schedulerConfig);
schedulerFactory.setResourceLoader(null);
schedulerFactory.setDataSource(dataSource);
schedulerFactory.setJobFactory(getSchedulerJobFactory());
schedulerFactory.setAutoStartup(false);
return schedulerFactory;
}
#Bean(name = SCHEDULER)
public Scheduler getScheduler()
{
return getSchedulerFactory().getScheduler();
}
I'm getting the error java.lang.ClassFormatError: Duplicate method name&signature in class file org/springframework/scheduling/quartz/SchedulerFactoryBean$$EnhancerBySpringCGLIB$$bee87fe8$$EnhancerBySpringCGLIB$$6bb26669.
Running the test using spring 4.0.6 framework works perfectly fine, but with 4.3.2, it's failing. When using 4.0.6, I was using cglib no dependencies library. With 4.3.2, the tests fail regardless of whether or not I use cglib.
Spring embeds cglib and objensis into 4.3.* core library. "Furthermore, Spring Framework 4.3 embeds the updated ASM 5.1, CGLIB 3.2.4, and Objenesis 2.4 in spring-core.jar." SpringDocs
We were using Java 8 and cglib-no-dep 2.2 with Spring framework 4.0.6. We tried running this code with and without the standalone library and see the same results.
Stack trace:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.quartz.Scheduler]: Factory method 'getScheduler' threw exception; nested exception is org.springframework.cglib.core.CodeGenerationException:java.lang.reflect.InvocationTargetException >null
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver$3.run(ConstructorResolver.java:582)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:579)
... 112 more
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException >null
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 188.486 sec
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.enhanceFactoryBean(ConfigurationClassEnhancer.java:452)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:338)
at com.example.SpringConfiguration$$EnhancerBySpringCGLIB$$54d3cb35.getSchedulerFactory(<generated>)
at com.example.SpringConfiguration.getScheduler(SpringConfiguration.java:242)
at com.example.SpringConfiguration$$EnhancerBySpringCGLIB$$54d3cb35.CGLIB$getScheduler$24(<generated>)
at com.example.SpringConfiguration$$EnhancerBySpringCGLIB$$54d3cb35$$FastClassBySpringCGLIB$$a2a6e004.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at com.example.SpringConfiguration$$EnhancerBySpringCGLIB$$54d3cb35.getScheduler(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 115 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor26.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:413)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)
... 140 more
Caused by: java.lang.ClassFormatError: Duplicate method name&signature in class file org/springframework/scheduling/quartz/SchedulerFactoryBean$$EnhancerBySpringCGLIB$$bee87fe8$$EnhancerBySpringCGLIB$$6bb26669
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
... 145 more
This is definetly a bug in cglib. It seems like it does not currectly determines a method in the type hierarchy to be equal to another method. Are you using Java 8 in combination with default methods in interfaces?
Cglib is not really tested for modern Java versions and experiences only little maintenance. Newer features sometimes cause trouble when using the library.

Solr custom UpdateRequestProcessorFactory fails with "Error Instantiating UpdateRequestProcessorFactory"

I have a custom class extending UpdateRequestProcessorFactory doing some work on a document when it gets added to the index. This was working fine in v4.10.3 in standalone Solr. I moved to SolrCloud v5.2 and it throws this error when adding the Collection (node):
ERROR - 2015-06-14 12:25:11.071; [ docs_shard1_replica1] org.apache.solr.common.SolrException; org.apache.solr.common.SolrException: Error CREATEing SolrCore 'docs_shard1_replica1': Unable to create core [docs_shard1_replica1] Caused by: class com.example.solr.update.processor.SelfTaggerUpdateProcessorFactory
at org.apache.solr.handler.admin.CoreAdminHandler.handleCreateAction(CoreAdminHandler.java:661)
at org.apache.solr.handler.admin.CoreAdminHandler.handleRequestInternal(CoreAdminHandler.java:213)
at org.apache.solr.handler.admin.CoreAdminHandler.handleRequestBody(CoreAdminHandler.java:193)
at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:143)
at org.apache.solr.servlet.HttpSolrCall.handleAdminRequest(HttpSolrCall.java:646)
at org.apache.solr.servlet.HttpSolrCall.call(HttpSolrCall.java:417)
at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:227)
at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:196)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.solr.common.SolrException: Unable to create core [docs_shard1_replica1]
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:651)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:611)
at org.apache.solr.handler.admin.CoreAdminHandler.handleCreateAction(CoreAdminHandler.java:628)
... 27 more
Caused by: org.apache.solr.common.SolrException: Error Instantiating UpdateRequestProcessorFactory, com.example.solr.update.processor.SelfTaggerUpdateProcessorFactory failed to instantiate org.apache.solr.update.processor.UpdateRequestProcessorFactory
at org.apache.solr.core.SolrCore.<init>(SolrCore.java:815)
at org.apache.solr.core.SolrCore.<init>(SolrCore.java:658)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:637)
... 29 more
Caused by: org.apache.solr.common.SolrException: Error Instantiating UpdateRequestProcessorFactory, com.example.solr.update.processor.SelfTaggerUpdateProcessorFactory failed to instantiate org.apache.solr.update.processor.UpdateRequestProcessorFactory
at org.apache.solr.core.SolrCore.createInstance(SolrCore.java:587)
at org.apache.solr.core.SolrCore.createInitInstance(SolrCore.java:622)
at org.apache.solr.core.SolrCore.initPlugins(SolrCore.java:2281)
at org.apache.solr.update.processor.UpdateRequestProcessorChain.init(UpdateRequestProcessorChain.java:126)
at org.apache.solr.core.SolrCore.createInitInstance(SolrCore.java:624)
at org.apache.solr.core.SolrCore.initPlugins(SolrCore.java:2265)
at org.apache.solr.core.SolrCore.initPlugins(SolrCore.java:2259)
at org.apache.solr.core.SolrCore.loadUpdateProcessorChains(SolrCore.java:1069)
at org.apache.solr.core.SolrCore.<init>(SolrCore.java:766)
... 31 more
Caused by: java.lang.ClassCastException: class com.example.solr.update.processor.SelfTaggerUpdateProcessorFactory
at java.lang.Class.asSubclass(Class.java:3208)
at org.apache.solr.core.SolrResourceLoader.findClass(SolrResourceLoader.java:475)
at org.apache.solr.core.SolrResourceLoader.findClass(SolrResourceLoader.java:422)
at org.apache.solr.core.SolrCore.createInstance(SolrCore.java:566)
... 39 more
In solrconfig.xml I have configured like this:
<updateRequestProcessorChain>
<processor class="com.example.solr.update.processor.SelfTaggerUpdateProcessorFactory" lib="custom-libs" version="1">
<arr name="source">
<str>title</str>
<str>desc</str>
<str>subject</str>
<str>content</str>
</arr>
<str name="dest">category</str>
</processor>
...
</updateRequestProcessorChain>
I have tried to add my custom jar in two ways:
Add it to the server/lib/ folder where all the Jetty jars are located. This fails with Error Instantiating UpdateRequestProcessorFactory
Add it to the .system collection as suggested and then make it available to the <processor /> using the lib and version attributes, which fails with a Caused by: java.lang.ClassNotFoundException: com.example.solr.update.processor.SelfTaggerUpdateProcessorFactory
Does this Error Instantiating UpdateRequestProcessorFactory exception tell something I don't see? Does the move from standalone to Solrcloud require something for my custom code I missed?
I think the issue is moving from standalone Solr to a Cloud one. Specifically, about where you store your jar file with the custom component. It is probably not visible to all the nodes and therefore fails.
However, Solr 5.2 does have new functionality related to that you may want to use. It allows to use the Config API to add the library, assuming you enable that functionality.
The issue is a classloader issue. I had added my custom jar into the server/lib/ folder.
When I added the Collection, it would instantiate my custom class which needs the UpdateRequestProcessorFactory class but is not available in that classloader.
I solved this by rmoving my jar from server/lib/ and adding this line to solrconfig.xml:
<lib dir="${solr.install.dir:../../..}/custom-libs/" regex="solr-.*\.jar" />
and putting my custom jar in a custom-libs/ folder in ${SOLR_HOME}. This way I make sure that my custom classes are only loaded when the Collection is added, and not before, so they are in the correct classloader.

Categories