When using the new QueryPostProcessor
feature and switching to SDG 1.9.11.BUILD-SNAPSHOT
from 1.9.10.RELEASE
, a StackOverflowError
is thrown during Spring context initialization...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.StackOverflowError
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1630)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 155 more
Caused by: java.lang.StackOverflowError
at org.springframework.data.util.TypeDiscoverer.getSuperTypeInformation(TypeDiscoverer.java:465)
at org.springframework.data.util.ClassTypeInformation.getSuperTypeInformation(ClassTypeInformation.java:43)
at org.springframework.data.util.TypeDiscoverer.getSuperTypeInformation(TypeDiscoverer.java:490)
at org.springframework.data.util.ClassTypeInformation.getSuperTypeInformation(ClassTypeInformation.java:43)
at org.springframework.data.util.TypeDiscoverer.getSuperTypeInformation(TypeDiscoverer.java:490)
at org.springframework.data.util.ClassTypeInformation.getSuperTypeInformation(ClassTypeInformation.java:43)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
That is a rather interesting result (i.e. StackOverflowError
) and may possibly be a bug/issue with the Spring Data Commons o.s.d.util.TypeDiscoverer
; I am not sure and I have not investigated yet (more on the StackOverflowError
below).
In a nutshell, SDG uses the Spring Data (Commons) TypeDiscover
class to "inspect" all beans (definitions) declared and registered in the Spring application context of the nature, and by way of the example...
@Component
class MyUserRepositoryQueryPostProcessor
implements QueryPostProcessor<UserRepository, String> {
...
}
Implementing the o.s.d.g.repository.query.QueryPostProcessor
interface requires 2 bits of information: the interface type to which the QueryPostProcessor
should be applied and the type of the query, which in SDG's case is a java.lang.String
since OQL is expressed as a String
, currently (though this could change in the future).
Here is one example in the SDG test suite.
So the question is, how to effectively declare and register an application Repository interface QueryPostProcessor
as bean definition in a Spring context?
In my integration test, I "explicitly" registered my QueryPostProcessors
as @Bean
definitions in a Spring @Configuration
class, whereas you are mostly like using Spring's classpath component scanning given the use of the Spring @Component
stereotype annotation, which can be problematic in certain cases.
The discovery of the QueryPostProcessors
in SDG is tied to the "parsing phase" of the Repository infrastructure. The Spring container may not have "parsed" the bean definitions (based on the use @Component
annotation) for your QueryPostProcessors
. You can usually adjust the parsing order by moving your bean definitions around in your config, for both XML and JavaConfig in fact, but it is usually better to be explicit about your configuration.
While classpath component scanning is convenient, it is less obvious when something goes wrong with the scanning, parsing, and registration process.
I need to think on this more and run some tests.
For now you can follow what I have done in my integration test.
Hope this helps!
Regards, John