简体   繁体   English

Grails 3.1.16-计划服务的会话范围服务的调用方法

[英]Grails 3.1.16 - Call method of session scope service from scheduled service

I created a test basic application on Grails 3.1.16 that has two services , a first async and scheduled service (ex. FirstService) calling a second session scoped service (ex. SessionScopeService), as below: 我在Grails 3.1.16上创建了一个测试基本应用程序,该应用程序具有两个服务 ,一个是第一异步和计划服务(例如FirstService),它调用了第二个会话范围服务(例如SessionScopeService),如下所示:

" FirstService.groovy ": FirstService.groovy ”:

import org.springframework.scheduling.annotation.Async
import org.springframework.scheduling.annotation.Scheduled

class FirstService {

   def sessionScopeService
   boolean lazyInit = false

   @Async
   @Scheduled(cron="*/10 * * * * MON-FRI") 
   void firstServiceMethod() {
       sessionScopeService.serviceMethod()
   }
}

" SessionScopeService.groovy ": SessionScopeService.groovy ”:

class SessionScopeService {

   static scope = "session"
   static proxy = "true"

   def serviceMethod() {
       log.info("test OK")
   }
}

The application fails to start, reporting scope session error: 应用程序无法启动,报告作用域会话错误:

ERROR org.springframework.boot.SpringApplication - Application startup 
failed
org.springframework.beans.factory.BeanCreationException: Error creating bean 

with name 'firstService': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionScopeService ': Scope '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 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.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:778)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:760)
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:306)
at grails.boot.GrailsApp.run(GrailsApp.groovy:55)
at grails.boot.GrailsApp.run(GrailsApp.groovy:375)
at grails.boot.GrailsApp.run(GrailsApp.groovy:364)
at grails.boot.GrailsApp$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
at testservice.Application.main(Application.groovy:8)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionScopeService': Scope '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 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)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1248)
at org.grails.spring.beans.factory.OptimizedAutowireCapableBeanFactory.autowireByName(OptimizedAutowireCapableBeanFactory.java:160)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1198)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
... 20 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/DispatcherPortlet: 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.SessionScope.get(SessionScope.java:91)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340)
... 25 common frames omitted

I also tried to create manually scoped proxy on ' resources.groovy ' : 我还尝试在' resources.groovy '上创建手动作用域代理:

  beans = {

     sessionScopeServiceProxy(ScopedProxyFactoryBean) {
        targetBeanName = 'sessionScopeService'
        proxyTargetClass = true
    }
  }

and then in the FirstService injected this proxy: 然后在FirstService中注入此代理:

  def sessionScopeServiceProxy

but without success (the method of "sessionScopeServiceProxy" is not even recognized by the "FirstService"). 但没有成功(“ FirstService”甚至无法识别“ sessionScopeServiceProxy”的方法)。

How can I solve this? 我该如何解决? Thanks for your time 谢谢你的时间

I guess you want to use a new SessionScopeService instance each time your 'job' runs, so you should be using 'prototype' as the scope and manually get the bean in the firstServiceMethod execution : grailsApplication.mainContext.getBean(SessionScopeService) . 我猜您想在每次“作业”运行时都使用一个新的SessionScopeService实例,因此您应该使用“原型”作为范围,并在firstServiceMethod执行中手动获取bean: grailsApplication.mainContext.getBean(SessionScopeService) This way, each time your 'job' kicks in, a new 'SessionScopeService' will be created for that execution. 这样,每次您的“工作”开始时,都会为该执行创建一个新的“ SessionScopeService”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM