Okay this is a sad error pointing with spring initialization order. We have an extension mechanism designed to allow beans to look up things in the spring application context. If a bean does so during construction the initialization dependency is not visible to spring and thus it cannot ensure the bean is ready for use.
I have a GeoServer with just the magic combination of extensions to result in an unlucky spring initialization order:
GridSetBroker.afterPropertiesSet()
→ GridSetBroker.getConfigurations()
→ GeoWebCacheExtensions.configurations()
→ GeoWebCacheExtensions.extensions()
→ GeoWebCacheExtensions.getBeansNamesOrderedByPriority()
→ gwcFacade (gs-gwc-2.23-SNAPSHOT.jar | geowebcache-geoserver-context.xml )
→ DiskQuotaMonitor ( gs-gwc-2.23-SNAPSHOT.jar | geowebcache-diskquota-context.xml )
As shown below:
12:43:48 ERROR [geowebcache.GeoWebCacheExtensions] - bean lookup error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gwcFacade' defined in URL [jar:file:/Users/jgarnett/.sdkman/candidates/tomcat/9.0.56/webapps/geoserver/WEB-INF/lib/gs-gwc-2.23-SNAPSHOT.jar!/geowebcache-geoserver-context.xml]: Cannot resolve reference to bean 'DiskQuotaMonitor' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DiskQuotaMonitor' defined in URL [jar:file:/Users/jgarnett/.sdkman/candidates/tomcat/9.0.56/webapps/geoserver/WEB-INF/lib/gs-gwc-2.23-SNAPSHOT.jar!/geowebcache-diskquota-context.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:342)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:707)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:198)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
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.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:673)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:661)
at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1302)
at org.geowebcache.GeoWebCacheExtensions.getBeansNamesOrderedByPriority(GeoWebCacheExtensions.java:157)
at org.geowebcache.GeoWebCacheExtensions.extensions(GeoWebCacheExtensions.java:102)
at org.geowebcache.GeoWebCacheExtensions.configurations(GeoWebCacheExtensions.java:205)
at org.geowebcache.grid.GridSetBroker.getConfigurations(GridSetBroker.java:229)
at org.geowebcache.grid.GridSetBroker.afterPropertiesSet(GridSetBroker.java:65)
Ideas for resolution:
- spring bean order may be an option?
- artificially introduce dependency: A dummy spring bean that can depend on DiskQuotaMonitor before gwcFacade ?
- Troubleshoot gwcFacade so it does not look up friends in the spring-context until later? It could wait for an event indicating the context is loaded
My unsafe workaround is to randomly additional extensions (in this case geopackage-wfs-ouput ) which changed the spring initialization order just enough that the problem to be avoided.
|