2015-04-02 71 views
1

我正在尝试向控制器注入会话作用域服务。这里是我的控制器类ActionController.groovy:Grails无法为控制器注入会话作用域服务

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 
    } 

} 

这里是我的会话范围的服务TweetingService.groovy: 包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 
     } 

    } 

但在运行上述应用,我得到以下错误:

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. 

所以我不允许简单地注入一个会话范围的服务控制器?或者我做错了什么?

编辑:

我已经看到this链接,并尝试设置静态代理=真。但它不起作用,同样的错误。

回答

0

我认为错误表明您的解决方案

'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; 

定义

static proxy=true服务它应该工作

进一步ref

+0

我已经试过了。在发布这个问题之前,我已经看到了链接 – rahulserver 2015-04-02 12:04:59

0

尝试改变在配置控制器的默认范围.groovy

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