Search code examples
spring-data-gemfire

Repository infrastructure throws StackOverflowError in SDG 1.9.11.BUILD-SNAPSHOT when using Query Post Processing


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)

Solution

  • 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