范围'请求'对于当前线程 - websocket版本无效

时间:2016-02-14 13:03:28

标签: java spring spring-boot spring-websocket

我正在尝试使用sprint boot和spring messaging创建一个websocket应用程序。但是,当我尝试在我们的一个服务类中调用一个函数时,我得到以下异常:

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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at com.propspace.intl.psauth.service.PsSessionHandler.getCurrentRequest(PsSessionHandler.java:83) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.psauth.service.PsTokenService.getTokenValue(PsTokenService.java:167) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.psauth.service.PsTokenService.getCurrentToken(PsTokenService.java:66) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.psauth.service.AuthPersistenceService.getCurrentUser(AuthPersistenceService.java:124) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.psauth.service.AuthPersistenceService$$FastClassBySpringCGLIB$$b662e141.invoke(<generated>) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:121) ~[spring-retry-1.1.1.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at com.propspace.intl.psauth.service.AuthPersistenceService$$EnhancerBySpringCGLIB$$d5176572.getCurrentUser(<generated>) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.psauth.service.AuthorizationService.getCurrentLoggedInUser(AuthorizationService.java:115) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.common.service.PsNotificationHandler.refindUserId(PsNotificationHandler.java:196) ~[propspace-common-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.common.service.PsNotificationHandler.getAllNotificationsOfUser(PsNotificationHandler.java:68) ~[propspace-common-0.1.6-SNAPSHOT.jar:na]
    at com.propspace.intl.pushnotifications.controller.NotificationController.greeting(NotificationController.java:47) ~[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.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:198) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:497) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:87) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]

在对它进行了一些阅读之后,事实证明我需要使这个服务(bean)成为一个范围内的bean,所以我这样做了:

@Scope(value= "request", proxyMode=org.springframework.context.annotation.ScopedProxyMode.TARGET_CLASS)

在我的bean类中,在我的控制器中我做到了这一点:

@Scope(value = "request",  proxyMode = ScopedProxyMode.TARGET_CLASS)

执行这些更改后,异常将更改为以下内容:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.notificationController': 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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:355) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.getTarget(CglibAopProxy.java:685) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:636) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at com.propspace.intl.pushnotifications.controller.NotificationController$$EnhancerBySpringCGLIB$$d92fa60c.greeting(<generated>) ~[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.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:198) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:497) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:87) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ... 20 common frames omitted

这是我的配置类:

@Configuration

@EnableWebSocketMessageBroker
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/topic");
    config.setApplicationDestinationPrefixes("/app");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/hello").withSockJS();
}

@Bean()
public NotificationHandler notificationHandler( ) {
    return new PsNotificationHandler();
}

@Bean
@ConditionalOnMissingBean
public RequestContextFilter requestContextFilter() {
    RequestContextFilter rcf = new RequestContextFilter();
    rcf.setThreadContextInheritable(true);
    return rcf;
}

@Bean
@ConditionalOnMissingBean
public RequestContextListener RequestContextListener() {
    return new RequestContextListener();
}

@Bean
public HttpSessionIdHandshakeInterceptor httpSessionIdHandshakeInterceptor() {
    return new HttpSessionIdHandshakeInterceptor();
}

}

我的代码主要基于使用spring boot运行websockets的示例代码,但这部分除外:

Object nots = notificationHandler.getAllNotificationsOfUser(null, false, false);

我收到通知,帮助赞赏

这是代码的精简版本 http://www.4shared.com/file/BinrToCqce/pushnotifications.html

1 个答案:

答案 0 :(得分:1)

似乎是Message broker有自己的线程。所以Message broker和DispathcherServlet在不同的线程中工作。但是你不能从另一个线程使用HttpServletRequest。因为,当异步作业将尝试处理HttpServletRequest时,请求(或会话)可能不是实际的或不再存在。这意味着您不能在DispatcherServlet的线程之外使用请求范围的bean以及会话范围的bean。

因为,您无法直接从另一个线程访问请求或会话数据,您必须手动传递此数据。