Why does InboundChannelAdapter not work in SpringBootTest - java

In a spring-boot project i am using the following code:
import org.springframework.integration.core.MessageSource;
#Configuration
public class Config
{
#Bean
#InboundChannelAdapter(channel = "channel1", autoStartup = "false",
poller = #Poller("poller"))
public MessageSource messages() throws Exception
{
...
to poll a mailaccount for incoming messages. This works fine so far.
The problem arises when i try to call some tests in a class that is annotated with #SpringBootTest. Then the initialisation of my testclass fails:
2023-01-12T16:43:03.846+01:00 ERROR 3625 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener#63648ee9] to prepare test instance [MyClass#b849fa6]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:131) ~[spring-test-6.0.0-M5.jar:6.0.0-M5]
<... stacktrace ...>
Caused by: java.lang.IllegalArgumentException: The 'interface org.springframework.integration.annotation.InboundChannelAdapter' on #Bean method level is allowed only for: org.springframework.integration.core.MessageSource, or java.util.function.Supplier, or kotlin.jvm.functions.Function0 beans
<... more stacktrace...>
I can't see the problem here, since the annotation is used together with MessageSource. Can someone help me on this one, please?
update in reply to the comment from Vitaly Chura:
in fact, that does not tell me much, unfortunately, but i will give it a try:
Caused by: java.lang.IllegalArgumentException: The 'interface org.springframework.integration.annotation.InboundChannelAdapter' on #Bean method level is allowed only for: org.springframework.integration.core.MessageSource, or java.util.function.Supplier, or kotlin.jvm.functions.Function0 beans
at org.springframework.util.Assert.isTrue(Assert.java:139) ~[spring-core-6.0.0-M5.jar:6.0.0-M5]
at org.springframework.integration.config.annotation.InboundChannelAdapterAnnotationPostProcessor.createMessageSource(InboundChannelAdapterAnnotationPostProcessor.java:100) ~[spring-integration-core-6.0.0-M4.jar:6.0.0-M4]
at org.springframework.integration.config.annotation.InboundChannelAdapterAnnotationPostProcessor.postProcess(InboundChannelAdapterAnnotationPostProcessor.java:72) ~[spring-integration-core-6.0.0-M4.jar:6.0.0-M4]
at org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor.postProcessMethodAndRegisterEndpointIfAny(MessagingAnnotationPostProcessor.java:231) ~[spring-integration-core-6.0.0-M4.jar:6.0.0-M4]
at org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor.lambda$processAnnotationTypeOnMethod$4(MessagingAnnotationPostProcessor.java:220) ~[spring-integration-core-6.0.0-M4.jar:6.0.0-M4]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor.afterSingletonsInstantiated(MessagingAnnotationPostProcessor.java:135) ~[spring-integration-core-6.0.0-M4.jar:6.0.0-M4]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:941) ~[spring-beans-6.0.0-M5.jar:6.0.0-M5]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:926) ~[spring-context-6.0.0-M5.jar:6.0.0-M5]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:592) ~[spring-context-6.0.0-M5.jar:6.0.0-M5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-3.0.0-M4.jar:3.0.0-M4]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:430) ~[spring-boot-3.0.0-M4.jar:3.0.0-M4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[spring-boot-3.0.0-M4.jar:3.0.0-M4]
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132) ~[spring-boot-test-3.0.0-M4.jar:3.0.0-M4]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) ~[spring-test-6.0.0-M5.jar:6.0.0-M5]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:123) ~[spring-test-6.0.0-M5.jar:6.0.0-M5]
... 72 common frames omitted

I know this does not explain the IllegalArgumentException, but for reasons of pragmatism i circumvented this problem by implementing a dummy configuration class inside the test-folder of the maven-project that provides the same beans as the original but does not use the #InboundChannelAdapter, as suggested by Matheus Santz in how-to-exclude-java-configuration-class-from-test-context. So for the tests this new dummy class is used.
Thanx to Vitaly Chura and all others reading.

Related

the #target annotation does not work when i work with spring aop

When I used the annotation on the spring aop interception class, I used a #target limit matching method. But when debugging, the following error is prompted.
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:138)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:536)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1082)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1071)
at com.example.springbootdemo.SpringbootdemoApplication.main(SpringbootdemoApplication.java:20)
Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:135)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:535)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:177)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory$$FastClassBySpringCGLIB$$bc74f446.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:173)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory$$EnhancerBySpringCGLIB$$bda70dbb.getEmbeddedServletContainer(<generated>)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:162)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:135)
... 8 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'metricsFilter' defined in class path resource [org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class org.springframework.boot.actuate.autoconfigure.MetricsFilter: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.actuate.autoconfigure.MetricsFilter
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481)
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.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:212)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:165)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:160)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAdaptableBeans(ServletContextInitializerBeans.java:145)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:78)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getServletContextInitializerBeans(EmbeddedWebApplicationContext.java:240)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.selfInitialize(EmbeddedWebApplicationContext.java:214)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.access$000(EmbeddedWebApplicationContext.java:91)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext$1.onStartup(EmbeddedWebApplicationContext.java:205)
at org.springframework.boot.context.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:53)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5154)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class org.springframework.boot.actuate.autoconfigure.MetricsFilter: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.actuate.autoconfigure.MetricsFilter
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:209)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:463)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:346)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:295)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:421)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1634)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
... 24 common frames omitted
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.actuate.autoconfigure.MetricsFilter
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:565)
at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.aop.framework.CglibAopProxy$ClassLoaderAwareUndeclaredThrowableStrategy.generate(CglibAopProxy.java:1001)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
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$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
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.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:54)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:201)
... 31 common frames omitted
My cut point is like this
#Pointcut("#target(com.example.springbootdemo.aspect.TimeIt)")
public void calcTime() {}
Where TimeIt is a annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE,ElementType.METHOD})
public #interface TimeIt {
boolean enabled() default true;
}
I changed the cut point to be able to run
#Pointcut("#within(com.example.springbootdemo.aspect.TimeIt)")
public void calcTime() {}
What I don't quite understand is that the MetricsFilter class doesn't have this annotation, so why generate a proxy?
Can anyone help me? Thank you very much.
I cannot run your code because you only provide a few little snippets, but what I noticed is:
As for the difference between #target() and #within() in Spring AOP and also in AspectJ, see my answer here.
Your annotation has #Target({ElementType.TYPE, ElementType.METHOD}), but both your pointcuts only target annotated types, not annotated methods. For that you would need to use #annotation. I.e. your annotated method will never be matched by this pointcut and consequently the advice will never fire.
Your exception must come from another pointcut/advice pair, not the ones you have shown in your question - probably something global like execution(* *(..)) or within(*) or target(*) which will try to weave into all kinds of Spring components, both your own and internal ones. So you need to limit that other pointcut to something like execution(* my.base.package..*(..)) or within(my.base.package..*) or target(my.base.package..*) or at least exclude internal Spring packages you don't wish to intercept via !within(org.springframework..*).

Redis health check for spring boot 2 hangs

I have implemented some redis stuff in my spring boot 2.1.5 application. It works fine.
I also want the health check for redis. If I switch off the redis server the health check (actuator/health) hangs forever.
How can I configure a sensible timeout?
I have created a little demo of this problem here:
https://github.com/markuskruse/demo-redis-health-bug
Clone, run, stop redis, check health (wait forever), start redis (health returns).
This is my gradle for redis:
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
This is my application.yaml:
spring:
redis:
timeout: 5000
host: localhost
This is my RedisConfig.java
#Configuration
#EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {
#Bean
public LettuceConnectionFactory redisConnectionFactory(
#Value("${spring.redis.host:localhost}") String redisHost) {
RedisStandaloneConfiguration redisStandaloneConfiguration =
new RedisStandaloneConfiguration(redisHost);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
#Bean
public StringRedisTemplate redisTemplate(RedisConnectionFactory jedisConnectionFactory) {
final StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(jedisConnectionFactory);
template.afterPropertiesSet();
return template;
}
}
According to this issue on github, it is a mere configuration issue:
https://github.com/spring-projects/spring-boot/issues/15542
According to this jira ticket, it should be fixed in spring boot 2.1.4 (I'm on 2.1.5).
https://jira.spring.io/browse/DATAREDIS-918
They mention a workaround that I have tried:
#Bean
public ClientOptions clientOptions() {
return ClientOptions.builder()
.timeoutOptions(TimeoutOptions.enabled())
.build();
}
By itself, it had no effect. I have to inject it somewhere. Googling gave this:
#Bean
LettucePoolingClientConfiguration lettucePoolConfig(ClientOptions options, ClientResources dcr){
return LettucePoolingClientConfiguration.builder()
.clientOptions(options)
.clientResources(dcr)
.build();
}
Then I get this:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration]: Factory method 'lettucePoolConfig' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
... 50 more
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration$LettucePoolingClientConfigurationBuilder.<init>(LettucePoolingClientConfiguration.java:91)
at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration.builder(LettucePoolingClientConfiguration.java:50)
at com.ikea.cps.mhs.config.RedisConfig.lettucePoolConfig(RedisConfig.java:50)
at com.ikea.cps.mhs.config.RedisConfig$$EnhancerBySpringCGLIB$$3804d114.CGLIB$lettucePoolConfig$3(<generated>)
at com.ikea.cps.mhs.config.RedisConfig$$EnhancerBySpringCGLIB$$3804d114$$FastClassBySpringCGLIB$$ccabed80.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.ikea.cps.mhs.config.RedisConfig$$EnhancerBySpringCGLIB$$3804d114.lettucePoolConfig(<generated>)
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.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 51 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 64 more
I can maybe work around this. But I am thinking that I am doing something (fundamentally) wrong. It should already be fixed.
Edit: I added the commons pool and the error goes away, but health check still hangs forever.
I also tried this below, to no effect.
#Component
public class RedisConfigurer implements LettuceClientConfigurationBuilderCustomizer {
#Override
public void customize(LettuceClientConfigurationBuilder builder) {
builder.clientOptions(ClientOptions.builder()
.timeoutOptions(TimeoutOptions.enabled(Duration.of(5, SECONDS))).build());
}
}
It seems that your problem is in your manual Connection factory configuration.
If you remove that part, everything should be fine as you expected.
Otherwise you need to provide a LettuceClientConfiguration for the second argument of the LettuceConnectionFactory constructor and there you can configure ClientOptions with enabled TimeoutOptions

Error creating bean with name 'resourceHandlerMapping'

I have an application with spring that use a JpaConfiguration class to deal with my database, and a WebAppMvcConfigurer class to deal with the front via json message. Both have an #Configuration and are in the same package. I have an App class in a root package with #Configuration and #ComponentScan with my main method.
When I launch App class I get this error :
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:89)
at com.bnpp.creditauto.App.main(App.java:22)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
... 14 more
Caused by: java.lang.IllegalStateException: No ServletContext set
at org.springframework.util.Assert.state(Assert.java:73)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping(WebMvcConfigurationSupport.java:533)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 15 more
What "works" so far is delete one of the two #Configuration in either JpaConfiguration or WebAppMvcConfigurer. If i delete the #Configuration WebApp one i can interact with my database no problem, but cant access anything from my angular application.
If I delete the #Configuration in JpaConf the front part of the application works and I can access the json my Java application sends with my angular application no problem, but cant do anything with my database.
Somewhere I read to change #Configuation to #WebAppConfiguration in WebAppMvcConfigurer, it does the same as removing the #Configuration, JpaConfiguration works fine and front part doesnt work.
I checked dependencies and tried the last version without success.
I tried to change in App : #ComponentScan(basePackages = { "org.example.springproject" }, excludeFilters = { #Filter(type = FilterType.ANNOTATION, value = Configuration.class) })
without success too, it is the same as deleting both #Configuration in Jpa and webapp
My app class :
package com.bnpp.creditauto;
#Configuration
#ComponentScan//("com.bnpp.creditauto")
public class App {
public static void main(String[] args) {
...
}
JpaConfiguration class :
package com.bnpp.creditauto.config;
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class JpaConfiguration {
...
}
WebAppMvcConfigurer class :
package com.bnpp.creditauto.config;
#Configuration
#EnableWebMvc
public class WebAppMvcConfigurer implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
So I found the answer, you can't launch the main method with a spring context when you have a #Configuration in a WebMvcConfigurer class and #Configuration in a class handling your Jpa configuration.
If you remove either config you can use your main method but the class without #Configuration will stop working. To create a method that initializes or tests and call it with HTTP request in a browser or your application dealing with the front part and it will work fine.
Thought of adding another scenario if someone cant still find the issue. So with the annotation "#SpringBootApplication" spring takes care most of the sub annotations like "#ComponentScan". let's say you have a test config class and you give your own component scan packages, then the default application level context loading wont happen. so in this case you only want to stick with other configuration like injecting your own property files with datasources (mem dbs)

Spring Boot autowire field in singleton service/controller by request scoped bean

I have a singleton service class with an autowired field like:
#Service
public class MyService{
#Autowired
private List<POJO> listWithObjectsForRequest;
}
the listWithObjectsForRequest is used im multiple services and components of my Spring Boot Application and a lot of calculations are required to create this list. It also depends on the current request that is running. So I thought I could write a request scoped bean, that will be injected by Spring every time a request enters my application:
#Configuration
public class MyServiceConfiguration{
#Bean
#RequestScope
public List<POJO> listWithObjectsForRequest(){
return heavyCalculations() // signature: public List<POJO> heavyCalculations()...
}
}
But I get the following error on application startup:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myService': Unsatisfied dependency expressed through field 'listWithObjectsForRequest'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.listWithObjectsForRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
... 31 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.listWithObjectsForRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:365)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193)
at com.sun.proxy.$Proxy84.equals(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.containsValue(ConcurrentHashMap.java:985)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.determineAutowireCandidate(DefaultListableBeanFactory.java:1501)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1222)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
... 44 common frames omitted
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:42)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353)
... 53 common frames omitted
I thought I found the answer here: Inject request scoped bean into another bean but my application still fails with this error message.
I know that the listWithObjectsForRequest can only be calculated in request scope, but how to tell spring that the field of MyService should only be initialized (once) in request?
You will get this exception because you are trying to inject request scope into singleton. Singleton will be created once and dependency will be injected once. You might be using some functionality which is depended on request, and during bean initialization of singleton, spring is unable to find it.
If you want to inject request scope bean into singleton you can do this by either
Inject ApplicationContext into MyService like -
#Autowired
private ApplicationContext context;
Then instead of autowiring listWithObjectsForRequest, get bean reference from the application context every time. Though this approach will solve the issue, but will bound your code with the Spring. If you are OK with it you can use it.
Or
You can use method injection as mentioned here - https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-method-injection
As already mentioned in other answers, you are getting this error because of injecting request scoped bean into a singleton scoped bean aka narrower bean DI problem
You just need to use
#Autowired
// provider from javax.inject.Provider;
private Provider<List<POJO>> listWithObjectsForRequest;
References
When to use javax.inject.Provider in Spring?
in Class POJO
try
#Scope("prototype")
before class declaration

springSecurityFilterChain - ObjectPostProcessor is a required bean Exception

I am building a Spring Boot application with Spring Security (spring-boot-starter-web and spring-boot-starter-security). I receive the following error from my application during boot:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalStateException: org.springframework.security.config.annotation.ObjectPostProcessor is a required bean. Ensure you have used #EnableWebSecurity and #Configuration
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:625) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:455) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
...
My application class consists of the following:
#SpringBootApplication
public class CustomPropertiesApplication {
public static void main(String[] args) {
SpringApplication.run(CustomPropertiesApplication.class, args);
}
}
The bean in this next class appears to be the issue. If it's excluded then the application will boot without error.
#Configuration
#EnableWebSecurity
public class MyConfig extends WebSecurityConfigurerAdapter {
#Bean
public CustomPropertyPlaceholderConfigurer propertyConfigurer(ApplicationContext context) {
return new CustomPropertyPlaceholderConfigurer();
}
}
Right now this CustomPropertyPlaceholderConfigurer class does nothing, I have some legacy classes that are similar, but in trying to troubleshoot this issue I eliminated everything else from my test application.
public class CustomPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
}
I'm at a loss of what to try next. I've looked for details in Spring Security and Spring Boot about building a custom property placeholder configurer, but I didn't find anything useful.
Versions: Spring Boot - 2.1.0.RELEASE | Spring Security - 5.1.1.RELEASE | JDK 1.8
Also, I realize this app doesn't really do anything, there is a much larger application that has much more complicated logic, and this sample app here is just to replicate my issue to make it small for stackoverflow.
I see now that the answer was right in my output logs and I just failed to see it.
o.s.c.a.ConfigurationClassEnhancer : #Bean method MyConfig.propertyConfigurer is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as #Autowired, #Resource and #PostConstruct within the method's declaring #Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see #Bean javadoc for complete details.
Adding static to my bean fixed the issue.

Categories

Resources