我想使用 Spring Boot 将会话范围的事件总线注入到 Vaadin 项目中的 Spring 服务中。
我的服务如下所示:
@Service
@EnableVaadinEventBus
public class MyService implements EventBusListener<Object> {
@Autowired
EventBus.SessionEventBus eventBus;
@PostConstruct
void init() {
eventBus.subscribe(this);
}
void myServiceMethod() {
....
}
@Override
public void onEvent(Event<Object> event) {}
}
该类被自动装配到一个用和MyService
注释的视图中。@SpringComponent
@SpringView(name = MyView.VIEW_NAME)
当我启动我的应用程序时,我得到了异常
java.lang.IllegalStateException: No VaadinSession bound to current thread
at com.vaadin.spring.internal.VaadinSessionScope$VaadinSessionBeanStoreRetrievalStrategy.getVaadinSession(VaadinSessionScope.java:119) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at com.vaadin.spring.internal.VaadinSessionScope$VaadinSessionBeanStoreRetrievalStrategy.getBeanStore(VaadinSessionScope.java:131) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at com.vaadin.spring.internal.VaadinSessionScope.getBeanStore(VaadinSessionScope.java:96) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at com.vaadin.spring.internal.VaadinSessionScope.get(VaadinSessionScope.java:72) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:339) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
... 30 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionEventBus': Scope 'vaadin-session' 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 VaadinSession bound to current thread
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:354) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1145) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1069) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:967) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:543) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
... 25 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.vaadin.spring.events.EventBus$SessionEventBus MyService.eventBus; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionEventBus': Scope 'vaadin-session' 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 VaadinSession bound to current thread
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:571) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
... 23 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.vaadin.spring.events.EventBus$SessionEventBus MyService.eventBus; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionEventBus': Scope 'vaadin-session' 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 VaadinSession bound to current thread
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:667) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:342) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:273) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:980) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:969) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at cMyApplication.main(VaadinSpringApplication.java:34) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:435) [spring-boot-maven-plugin-1.3.0.M5.jar:1.3.0.M5]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
我猜这个错误的原因是,服务是单例的,而事件总线是会话范围的。
代理是解决此问题的方法吗?如果是这样,我该如何为我的事件总线创建?
更新
使用@EventBusProxy
注释时,我得到一个不同的错误,它表明 eventBus 被代理:
java.lang.IllegalStateException: No VaadinSession bound to current thread
at com.vaadin.spring.internal.VaadinSessionScope$VaadinSessionBeanStoreRetrievalStrategy.getVaadinSession(VaadinSessionScope.java:119) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at com.vaadin.spring.internal.VaadinSessionScope$VaadinSessionBeanStoreRetrievalStrategy.getBeanStore(VaadinSessionScope.java:131) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at com.vaadin.spring.internal.VaadinSessionScope.getBeanStore(VaadinSessionScope.java:96) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at com.vaadin.spring.internal.VaadinSessionScope.get(VaadinSessionScope.java:72) ~[vaadin-spring-1.0.0.beta3.jar:1.0.0.beta3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:339) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
... 36 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.proxiedSessionEventBus': Scope 'vaadin-session' 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 VaadinSession bound to current thread
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:354) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:187) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at com.sun.proxy.$Proxy103.subscribe(Unknown Source) ~[na:na]
at MyService.init(MyService.java:61) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:354) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:305) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
... 24 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.proxiedSessionEventBus': Scope 'vaadin-session' 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 VaadinSession bound to current thread
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:667) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:342) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:273) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:980) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:969) [spring-boot-1.3.0.M5.jar:1.3.0.M5]
at MyApplication.main(MyApplication.java:34) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:435) [spring-boot-maven-plugin-1.3.0.M5.jar:1.3.0.M5]
我需要代理myService
吗?这个 bean 应该仍然是单例的,不是吗?