cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

APOC 4.4 not compatible with Spring Boot 2.6.2

boyenvangorp
Node Clone

We are in the process of upgrading our Spring Boot stack due to the vulnerability of Log4j.

However, because APOC uses an old version of jackson (2.10) that is not compatible with the current spring boot version of jackson (2.13+), we get a runtime error on deserialization with jackson. See: Spring batch 2.4.1 + Wildfly 20 final - java.lang.NoSuchFieldError: BLOCK_UNSAFE_POLYMORPHIC_BASE_TY...

The exception is the following:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'batchConfigurer' defined in class path resource [org/springframework/boot/autoconfigure/batch/BatchConfigurerConfiguration$JpaBatchConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoSuchFieldError: BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:671)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:659)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1300)
	at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration.initialize(SimpleBatchConfiguration.java:115)
	at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$ReferenceTargetSource.createObject(SimpleBatchConfiguration.java:143)
	at org.springframework.aop.target.AbstractLazyCreationTargetSource.getTarget(AbstractLazyCreationTargetSource.java:88)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:195)
	at com.sun.proxy.$Proxy180.register(Unknown Source)
	at org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor.postProcessAfterInitialization(JobRegistryBeanPostProcessor.java:146)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
	... 106 more
Caused by: java.lang.NoSuchFieldError: BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES
	at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.<init>(Jackson2ExecutionContextStringSerializer.java:119)
	at org.springframework.batch.core.repository.support.JobRepositoryFactoryBean.afterPropertiesSet(JobRepositoryFactoryBean.java:194)
	at org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer.createJobRepository(BasicBatchConfigurer.java:133)
	at org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer.initialize(BasicBatchConfigurer.java:101)
	at org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer.afterPropertiesSet(BasicBatchConfigurer.java:95)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
	... 124 more

Our (minimal) setup as such:

plugins {
	id 'org.springframework.boot' version '2.6.2'
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-batch'
        implementation 'org.neo4j.procedure:apoc:4.4.0.1:all'
        implementation 'org.neo4j.test:neo4j-harness:4.4.3'
}

I have made an issue on the APOC github, but haven't seen any feedback: APOC uses Jackson version prior to 2.11 not compatible with latest spring-boot · Issue #2468 · neo4j...

If anyone has advice on how to deal with this it would be much appreciated.

1 ACCEPTED SOLUTION

APOC is not build nor promises compatibility with the latest Spring Boot (or Spring Batch or fastxml-jackson).

I think this sums up this topic. That's disappointing. We will need to consider a stack that is reliable in that case.

View solution in original post

8 REPLIES 8

gerrit_meier
Neo4j
Neo4j

First of all, I am assuming that you are running embedded, right?
So the problem is more that your whole dependency chain somewhere defines an older version of the jackson library. I am not so experienced with Gradle but in Maven it is possible to either

  • define the newest version / the version to use explicitly
  • exclude the transient dependency from the dependency that should not define it in you application

Both ideas would imply that APOC would run with newer version, what I assume.

Also please refrain from using such topic names because it is a wild mixture of libraries in your application and it has barely anything to do with Log4j.

Also please refrain from using such topic names because it is a wild mixture of libraries in your application and it has barely anything to do with Log4j.

Gerrit, while I appreciate your help, this does in fact have everything to do with Log4j.
-> We must upgrade to the latest spring boot due to log4j
-> Spring boot 2.6.2 uses Jackson 2.13
-> APOC 4.4.0.1 uses Jackson 2.10
-> You cannot run Jackson 2.13 and 2.10 simultaneously, see: Spring batch 2.4.1 + Wildfly 20 final - java.lang.NoSuchFieldError: BLOCK_UNSAFE_POLYMORPHIC_BASE_TY...
-> APOC 4.4.0.1 cannot run version Jackson 2.13, which is the default behaviour
-> Spring boot (batch) cannot run Jackson 2.10 which is the manual behaviour I've overridden

In effect, our application is now not running. There's nothing wild about our setup. This is standard behaviour that should work, and would work if I could get APOC to update their dependencies.

Then update the log4j dependency itself. This will do the job.
But you are relying on a third party component and its dependency definitions (Spring Boot in this case) and do an overall dependency upgrade of your application (not only log4j). APOC is not build nor promises compatibility with the latest Spring Boot (or Spring Batch or fastxml-jackson).
I do not want to say that asking for a dependency upgrade in APOC is the wrong thing. Of course please do this and it should be resolved but there is no urgent because you can define the new version of the critical library in your stack yourself.

APOC is not build nor promises compatibility with the latest Spring Boot (or Spring Batch or fastxml-jackson).

I think this sums up this topic. That's disappointing. We will need to consider a stack that is reliable in that case.

To be honest, I do not get your (negative) point in the whole story. Would you consider that any library in the Java space does cross-testing with other libraries on release of those libraries?

Gerrit, I don't believe there's anything wrong with my disappointment. We assumed that we can rely on APOC to be compatible with the Spring Boot stack, you have said that that assumption is incorrect. As we have built on APOC and work and investment has already been done here, the least I should be is disappointed.

Your suggestion of manually fixing log4j issues and staying on a lower Spring Boot version because APOC has not upgraded the Jackson dependency is not acceptable from both a maintenance and and architectural point of view. As such, our only option is to no longer rely on APOC as a library to be compatible with the Spring Boot.

What I did hope is that when I posted the issue in git, and posted on this forum that there is a dependency missmatch causing runtime errors, is that it would trigger action on the maintainers of the APOC library. This under the assumption that Spring Boot compatibility is desirable. As my assumption is wrong, I understand that there is no pressure from an APOC point of view to be in sync with the Spring Boot stack. Which means that we need to consider another way.

Side note: Neo4j harness is meant for tests, not for bringing up embedded instances in production applications. You should probably revisit that.

About APOC: this library is primarily meant to be deployed to a standalone server or a cluster. It of course works with embedded instances, but I do not think APOC will ever guarantee to work well with Spring Boot. The combination of APOC (server-side plugin) and Spring Boot (application framework) is quite uncommon, in my experience.

I can only repeat what Gerrit said: the most accurate, least invasive way to solve your issue at hand is to manage the Log4j version yourself.

I was just making a minimal project to replicate the issue.

As for invasiveness, I will repeat what I've said. The moment an APOC library is limiting which Spring updates we can do we're going down a rabbit hole of bad architecture and poor maintainability. If the official stance is that we cannot rely on APOC to have the latest updates (in sync with Spring boot), then we cannot rely on APOC for this (Spring boot) project period.