Grails无法将会话作用域服务注入到控制器 [英] Grails unable to inject session scoped service to controller

查看:158
本文介绍了Grails无法将会话作用域服务注入到控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向控制器注入会话范围的服务。这里是我的控制器类ActionController.groovy:

 包rafonline 

导入grails.converters.JSON
import grails.plugin.springsecurity.annotation.Secured

@Secured(ROLE_ADMIN)
class ActionController {
def tweetingService
def index(){


$ b def retweetUsers(){
String message =done
boolean success = true
try {
最后def句柄= String.valueOf(params.handles).trim()。split(\\\

最终def口令= String.valueOf(params.passwords).trim()。split(\\ \\ n)
final def numRTs = String.valueOf(params.numRTs).trim()。split(\\\

final def statusIdsString = String.valueOf(params.tweetURLs)。 trim()。split(\\\

if(!tweetingService.isRunning){
new Thread(new Runnable(){

@Override
void r un(){
tweetingService.retweetUsers(statusIdsString,句柄,密码,numRTs);
}
})。start();
}
} catch(Exception e){
message = e.getMessage()
success = false
}
render contentType:'text / json ',text:[success:success,message:$ {message}] as JSON
}
def getUpdateProgress(){
render contentType:'text / json',text:[运行:tweetingService.isRunning,message:tweetingService.messsage] as JSON
}

}

以下是我的会话scoped service TweetingService.groovy:
包rafonline

 导入grails。 transaction.Transactional 
import org.jsoup.Connection
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements

@Transactional $ b $ class TweetingService {
private final String PARAM1 =some1;
private final String PARAM2 =some2;
private final String PARAM3 =some3;
private final String USER_AGENT =some4;
private final Long TIMEOUT = 60000
static scope =session
def messsage =Waiting
def isRunning = false
def stopit = false
def retweetUsers(String [] statusIds,String [] username,String [] password,String [] numRTs){
if(isRunning){
return
} else {
try {
int count = 1;
isRunning = true
statusIds = convertStatusURLArrayToStatusIDArray(statusIds)
def totalLength = statusIds.length

for(int i = 0; i< statusIds.length; i ++ ){
def statusId = statusIds [i]
def numRT = username.length
try {
numRT = Integer.parseInt(numRTs [i])
} catch (例外e){
numRT =用户名。长度
}
shuffleArray(用户名,密码)
messsage =处理$ {totalLength}的$ {i + 1}
for(int j = 0; j if(stop){
stop = false
break;


try {
//做某事

} catch(Exception e){
e.printStackTrace();
}
messsage =已处理总额:$ {totalLength}失败:$ {totalLength - count}成功:$ {count}
}
}
} catch (例外e){

}最后{
isRunning = false
}
}
}

def Map< String ,String> getFormParams(String html,String username,String password)
抛出UnsupportedEncodingException {

System.out.println(Extracting form's data ...);

Document doc = Jsoup.parse(html);

// Google form id
元素loginform = doc.getElementsByTag(form)。get(2);
元素inputElements = loginform.getElementsByTag(input);
列表< String> paramList = new ArrayList< String>();
Map< String,String> map = new HashMap< String,String>(); (Element inputElement:inputElements)
{
String key = inputElement.attr(name);
String value = inputElement.attr(value);

if(key.equals(session [username_or_email]))
value = username;
else if(key.equals(session [password]))
value = password;

map.put(key,value);
}

//建立参数列表

return map;
}
def convertStatusURLArrayToStatusIDArray(String [] statusIdArray){
String [] outputArray = new String [statusIdArray.length]
for(int i = 0; i< statusIdArray.length ; i ++){
outputArray [i] = getStatusIdFromTweetURL(statusIdArray [i]);

return outputArray
$ b $ def getStatusIdFromTweetURL(String tweetURL){
def tokens = tweetURL.split(/)
for(String s :tokens){
try {
Long.parseLong(s)
return s
} catch(Exception e){

}
}
return null

static void shuffleArray(String [] usernames,String [] passwords){
Random rnd = new Random();
for(int i = usernames.length - 1; i> 0; i--){
int index = rnd.nextInt(i + 1);
//简单交换
字符串a =用户名[index];
usernames [index] = usernames [i];
用户名[i] = a;

字符串b =密码[index];
密码[index] =密码[i];
密码[i] = b;


def stop(){
stopit = Boolean.TRUE
}
}


def retweetUsers(){
String message =done
boolean success = true
try {
final def handles = String.valueOf(params.handles).trim()。 split(\ n)
final def passwords = String.valueOf(params.passwords).trim()。split(\\\

final def numRTs = String.valueOf(params .nu​​mRTs).trim()。split(\\\

final def statusIdsString = String.valueOf(params.tweetURLs).trim().split(\\\

if (!tweetingService.isRunning){
new Thread(new Runnable(){
$ b @Override
void run(){
tweetingService.retweetUsers(statusIdsString,handles,密码,numRTs);
}
})。start();
}
} catch(Exception e){
message = e.getMessage()
success = false
}
render contentType:'text / json ',text:[success:success,message:$ {message}] as JSON
}
def getUpdateProgress(){
render contentType:'text / json',text:[运行:tweetingService.isRunning,message:tweetingService.messsage] as JSON
}

}

但在运行上述应用程序时,出现以下错误:

  2015-04-02 16 :47:22,552 [localhost-startStop-1] ERROR context.GrailsContextLoader  - 初始化应用程序时出错:创建名为'rafonline.ActionController'的bean时出错:Bean初始化失败;嵌套异常是org.springframework.beans.factory.BeanCreationException:创建名为'tweetingService'的bean时出错:范围'会话'对当前线程无效;考虑为这个bean定义一个范围代理,如果你打算从一个单例中引用它;嵌套异常是java.lang.IllegalStateException:找不到线程绑定的请求:您是否在实际Web请求之外引用请求属性,或者在原始接收线程之外处理请求?如果实际上在Web请求中运行并仍然收到此消息,则代码可能在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter来公开当前请求。 
消息:创建名为'rafonline.ActionController'的bean时出错:bean初始化失败;嵌套异常是org.springframework.beans.factory.BeanCreationException:创建名为'tweetingService'的bean时出错:范围'会话'对当前线程无效;考虑为这个bean定义一个范围代理,如果你打算从一个单例中引用它;嵌套异常是java.lang.IllegalStateException:找不到线程绑定的请求:您是否在实际Web请求之外引用请求属性,或者在原始接收线程之外处理请求?如果实际上在Web请求中运行并仍然收到此消息,则代码可能在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter来公开当前请求。
Line |方法
- >> 529 | doCreateBean in org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 127 | doCreateBean in org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory
| 458 | createBean。 。 。 。 。 。 。 。 。 。 in org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
| 296 | getObject in org.springframework.beans.factory.support.AbstractBeanFactory $ 1
| 223 | getSingleton。 。 。 。 。 。 。 。 。 in org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
| 293 | doGetBean in org.springframework.beans.factory.support.AbstractBeanFactory
| 194 | getBean。 。 。 。 。 。 。 。 。 。 。 。在''
|中628 | preInstantiateSingletons in org.springframework.beans.factory.support.DefaultListableBeanFactory
| 932 | finishBeanFactoryInitialization in org.springframework.context.support.AbstractApplicationContext
| 479 |刷新''
| 156 | getApplicationContext。 。 。 。 。 in org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration
| 169 |在org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator中进行配置
| 127 |配置 。 。 。 。 。 。 。 。 。 。 。在''
|中122 | org.codehaus.groovy.grails.web.context.GrailsConfigUtils中的configureWebApplicationContext
| 108 | initWebApplicationContext。 。 。 in org.codehaus.groovy.grails.web.context.GrailsContextLoader
| 112 | contextInitialized in org.springframework.web.context.ContextLoaderListener
| 4973 | listenerStart。 。 。 。 。 。 。 。 。在org.apache.catalina.core.StandardContext
|中5467 | ''
|中的startInternal 150 |开始。 。 。 。 。 。 。 。 。 。 。 。 。在org.apache.catalina.util.LifecycleBase
|中1559 |调用org.apache.catalina.core.ContainerBase $ StartChild
| 1549 |打电话。 。 。 。 。 。 。 。 。 。 。 。 。在''
|中262 |在java.util.concurrent.FutureTask
|运行1145 | runWorker。 。 。 。 。 。 。 。 。 。 。在java.util.concurrent.ThreadPoolExecutor
|中615 |在java.util.concurrent.ThreadPoolExecutor $ Worker
^ 745 |中运行跑 。 。 。 。 。 。 。 。 。 。 。 。 。 。在java.lang.Thread中
由BeanCreationException引发:创建名为'tweetingService'的bean时出错:作用域'session'对当前线程无效;考虑为这个bean定义一个范围代理,如果你打算从一个单例中引用它;嵌套异常是java.lang.IllegalStateException:找不到线程绑定的请求:您是否在实际Web请求之外引用请求属性,或者在原始接收线程之外处理请求?如果实际上在Web请求中运行并仍然收到此消息,则代码可能在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter来公开当前请求。

那么我不允许简单地将一个会话作用域服务注入到控制器中?或者我做错了什么?



编辑:



我已经看过这个链接并尝试设置static proxy = true。然而,它不起作用,同样的错误。试图改变Config.groovy控制器的默认范围



  //控制器的默认范围。可能是原型,会话或单身。 
//如果未指定,控制器是原型范围。
grails.controllers.defaultScope ='session'


I am trying to inject a session scoped service to controller. Here is my controller class ActionController.groovy:

    package rafonline

import grails.converters.JSON
import grails.plugin.springsecurity.annotation.Secured

@Secured("ROLE_ADMIN")
class ActionController {
    def tweetingService
    def index() {
    }


    def retweetUsers(){
        String message="done"
        boolean success=true
        try {
            final def handles=String.valueOf(params.handles).trim().split("\n")
            final def passwords=String.valueOf(params.passwords).trim().split("\n")
            final def numRTs=String.valueOf(params.numRTs).trim().split("\n")
            final def statusIdsString=String.valueOf(params.tweetURLs).trim().split("\n")
            if(!tweetingService.isRunning){
                new Thread(new Runnable(){

                    @Override
                    void run() {
                        tweetingService.retweetUsers(statusIdsString,handles,passwords,numRTs);
                    }
                }).start();
            }
        } catch (Exception e) {
            message=e.getMessage()
            success=false
        }
        render contentType: 'text/json', text: [success: success, message: "${message}"] as JSON
    }
    def getUpdateProgress(){
       render contentType: 'text/json',text:[running:tweetingService.isRunning,message: tweetingService.messsage] as JSON
    }

}

Here is my session scoped service TweetingService.groovy: package rafonline

import grails.transaction.Transactional
import org.jsoup.Connection
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements

@Transactional
class TweetingService {
    private final String PARAM1 = "some1";
    private final String PARAM2 = "some2";
    private final String PARAM3 = "some3";
    private final String USER_AGENT = "some4";
    private final Long TIMEOUT = 60000
    static scope = "session"
    def messsage = "Waiting"
    def isRunning = false
    def stopit=false
    def retweetUsers(String[] statusIds, String[] username, String[] password, String[] numRTs) {
        if (isRunning) {
            return
        } else {
            try {
                int count = 1;
                isRunning = true
                statusIds=convertStatusURLArrayToStatusIDArray(statusIds)
                def totalLength = statusIds.length

                for (int i = 0; i < statusIds.length; i++) {
                    def statusId = statusIds[i]
                    def numRT = username.length
                    try{
                        numRT=Integer.parseInt(numRTs[i])
                    }catch(Exception e){
                        numRT=username.length
                    }
                    shuffleArray(username, password)
                    messsage = "Processing ${i + 1} of ${totalLength}"
                    for (int j = 0; j < numRT; j++) {
                        if(stop){
                            stop=false
                            break;
                        }

                        try {
                            //Do something

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        messsage = "Total Processed: ${totalLength}    Failed: ${totalLength - count}   Success:${count}"
                    }
                }
            } catch (Exception e) {

            } finally {
                isRunning=false
            }
        }
    }

    def Map<String, String> getFormParams(String html, String username, String password)
    throws UnsupportedEncodingException {

        System.out.println("Extracting form's data...");

        Document doc = Jsoup.parse(html);

        // Google form id
        Element loginform = doc.getElementsByTag("form").get(2);
        Elements inputElements = loginform.getElementsByTag("input");
        List<String> paramList = new ArrayList<String>();
        Map<String, String> map = new HashMap<String, String>();
        for (Element inputElement : inputElements) {
            String key = inputElement.attr("name");
            String value = inputElement.attr("value");

            if (key.equals("session[username_or_email]"))
                value = username;
            else if (key.equals("session[password]"))
                value = password;

            map.put(key, value);
        }

        // build parameters list

        return map;
    }
    def convertStatusURLArrayToStatusIDArray(String[]statusIdArray){
        String[]outputArray=new String[statusIdArray.length]
        for(int i=0;i<statusIdArray.length;i++){
            outputArray[i]=getStatusIdFromTweetURL(statusIdArray[i]);
        }
        return outputArray
    }
    def getStatusIdFromTweetURL(String tweetURL){
        def tokens=tweetURL.split("/")
        for(String s:tokens){
            try{
                Long.parseLong(s)
                return s
            }catch (Exception e){

            }
        }
        return null
    }
    static void shuffleArray(String[] usernames, String[] passwords) {
        Random rnd = new Random();
        for (int i = usernames.length - 1; i > 0; i--) {
            int index = rnd.nextInt(i + 1);
            // Simple swap
            String a = usernames[index];
            usernames[index] = usernames[i];
            usernames[i] = a;

            String b = passwords[index];
            passwords[index] = passwords[i];
            passwords[i] = b;
        }
    }
    def stop(){
        stopit=Boolean.TRUE
    }
}


        def retweetUsers(){
            String message="done"
            boolean success=true
            try {
                final def handles=String.valueOf(params.handles).trim().split("\n")
                final def passwords=String.valueOf(params.passwords).trim().split("\n")
                final def numRTs=String.valueOf(params.numRTs).trim().split("\n")
                final def statusIdsString=String.valueOf(params.tweetURLs).trim().split("\n")
                if(!tweetingService.isRunning){
                    new Thread(new Runnable(){

                        @Override
                        void run() {
                            tweetingService.retweetUsers(statusIdsString,handles,passwords,numRTs);
                        }
                    }).start();
                }
            } catch (Exception e) {
                message=e.getMessage()
                success=false
            }
            render contentType: 'text/json', text: [success: success, message: "${message}"] as JSON
        }
        def getUpdateProgress(){
           render contentType: 'text/json',text:[running:tweetingService.isRunning,message: tweetingService.messsage] as JSON
        }

    }

But on running the above app, I get the following error:

2015-04-02 16:47:22,552 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: Error creating bean with name 'rafonline.ActionController': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tweetingService': 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.
Message: Error creating bean with name 'rafonline.ActionController': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tweetingService': 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.
    Line | Method
->>  529 | doCreateBean                    in org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    127 | doCreateBean                    in org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory
|    458 | createBean . . . . . . . . . .  in org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
|    296 | getObject                       in org.springframework.beans.factory.support.AbstractBeanFactory$1
|    223 | getSingleton . . . . . . . . .  in org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
|    293 | doGetBean                       in org.springframework.beans.factory.support.AbstractBeanFactory
|    194 | getBean . . . . . . . . . . . . in     ''
|    628 | preInstantiateSingletons        in org.springframework.beans.factory.support.DefaultListableBeanFactory
|    932 | finishBeanFactoryInitialization in org.springframework.context.support.AbstractApplicationContext
|    479 | refresh                         in     ''
|    156 | getApplicationContext . . . . . in org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration
|    169 | configure                       in org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator
|    127 | configure . . . . . . . . . . . in     ''
|    122 | configureWebApplicationContext  in org.codehaus.groovy.grails.web.context.GrailsConfigUtils
|    108 | initWebApplicationContext . . . in org.codehaus.groovy.grails.web.context.GrailsContextLoader
|    112 | contextInitialized              in org.springframework.web.context.ContextLoaderListener
|   4973 | listenerStart . . . . . . . . . in org.apache.catalina.core.StandardContext
|   5467 | startInternal                   in     ''
|    150 | start . . . . . . . . . . . . . in org.apache.catalina.util.LifecycleBase
|   1559 | call                            in org.apache.catalina.core.ContainerBase$StartChild
|   1549 | call . . . . . . . . . . . . .  in     ''
|    262 | run                             in java.util.concurrent.FutureTask
|   1145 | runWorker . . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor
|    615 | run                             in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run . . . . . . . . . . . . . . in java.lang.Thread
Caused by BeanCreationException: Error creating bean with name 'tweetingService': 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.

So am I not allowed simply inject a session scoped service to a controller? Or what am I doing wrong?

EDIT:

I have already seen this link and tried setting static proxy=true. Yet it does not work and same error.

解决方案

Try to change the default scope for controllers in Config.groovy

// The default scope for controllers. May be prototype, session or singleton.
// If unspecified, controllers are prototype scoped.
grails.controllers.defaultScope = 'session'

这篇关于Grails无法将会话作用域服务注入到控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆