2013-03-07 52 views
0

我正在處理一個大的Grails 1.3.7項目,我想從過濾器訪問流狀態名稱以進行日誌記錄。我一直在使用谷歌搜索,我能找到的最接近的答案是:Grails WebFlow State Name,但它只能在流程內部工作。從過濾器訪問流狀態名稱

有什麼方法可以從流程(過濾器)外部獲取當前會話中正在執行的流程的狀態名稱?

由於提前,

吉列爾莫

+0

我發現了一些與此問題相關的鏈接:[從Spring Web Flow外部訪問流執行](http://www.ervacon.com/products/swf/tips/tip1.html)和[ webflow - 列出所有活動流程](http://grails.1312388.n4.nabble.com/webflow-list-all-active-flows-td1376853.html)。我需要從FlowExecutionRepository中獲得'FlowExecution'(我想我可以通過'session.webflowConversationContainer'中的流鍵獲得它),但是我無法弄清楚如何在Grails中獲取任何控制器過濾。 – 2013-03-08 10:40:27

回答

3

很多使用Google和調試後,我設法生產出下面的代碼。它適用於一個簡單的應用程序。當我從假期回來時,我會將它與主應用程序集成,然後我會更新此問題。

package org.glalejos 

import org.springframework.context.ApplicationContext 
import org.springframework.webflow.context.ExternalContext 
import org.springframework.webflow.context.ExternalContextHolder 
import org.springframework.webflow.context.servlet.ServletExternalContext 
import org.springframework.webflow.execution.FlowExecution 
import org.springframework.webflow.execution.FlowExecutionKey 
import org.springframework.webflow.execution.repository.FlowExecutionRepository 

class LoggingFilters { 

    def grailsApplication 

    String getFlowStateName(def grailsApplication, def servletContext, def request, def response) { 
     String stateName 

     if (grailsApplication && servletContext && request && request.queryString && response) { 
      try { 
       String strKey = null 
       String[] keys = request.queryString.split("&") 
       keys.each{ if (it.startsWith("execution=")) strKey = it.substring(10)} 

       if (strKey != null) { 
        ApplicationContext ctx = grailsApplication.mainContext 
        FlowExecutionRepository fer = ctx.getBean("flowExecutionRepository") 

        FlowExecutionKey fek = fer.parseFlowExecutionKey(strKey) 

        ExternalContext previousContext = ExternalContextHolder.getExternalContext() 

        try { 
         // You have to set an external context before invoking "fer.getFlowExecution()" or it'll throw a NPE 
         ExternalContextHolder.setExternalContext(new ServletExternalContext(servletContext, request, response)); 
         FlowExecution fe = fer.getFlowExecution(fek) 

         stateName = fe.getActiveSession().getState().getId() 
        } finally { 
         ExternalContextHolder.setExternalContext(previousContext); 
        } 
       } else { 
        stateName = null 
       } 
      } catch(Exception e) { 
       stateName = null 
      } 
     } else { 
      stateName = null 
     } 

     return stateName 
    } 

    def filters = { 
     logData(controller:"*", action:"*") { 
      before = { 
       println("Incoming request. Current flow state name is: ${getFlowStateName(grailsApplication, servletContext, request, response)}") 
      } 

      after = { 
       println("Dispatched request. Current flow state name is: ${getFlowStateName(grailsApplication, servletContext, request, response)}") 
      } 
     } 
    } 
} 

EDIT:上面的代碼行,以確定在給定時間點的電流流動狀態的名稱,但它不會更新日誌框架的映射診斷上下文作爲流執行演變。爲此,有必要實施org.springframework.webflow.execution.FlowExecutionListenerconf/spring/resources.groovy註冊它:

beans = { 
    myLoggingFlowExecutionListener(org.example.MyLoggingFlowExecutionListener) 
} 

您必須先註冊這個監聽器bean和hibernateConversationListener豆在executionListenerLoader豆,但是,出於某種原因,春季DSL不在這種情況下工作(見下面的EDIT2)。因此,這裏是resources.xml,你可以在同一個文件夾中放置的resources.groovy爲了正確聲明你的資源:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 

    <bean id="executionListenerLoader" class="org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader"> 
    <constructor-arg> 
     <list> 
     <ref bean="hibernateConversationListener" /> 
     <ref bean="myLoggingFlowExecutionListener" /> 
     </list> 
    </constructor-arg> 
    </bean> 
</beans> 

每個FlowExecutionListener方法受到了很多的,可以用來進行日誌記錄上下文信息(我ommiting爲了清晰起見,這個類的實現)。

EDIT2:失敗流生命週期中的操作域對象時hibernateConversationListener豆添加到executionListenerLoader導致休眠異常。但是,Spring DSL在這種情況下不起作用,所以我不得不使用XML格式聲明所需的bean。見http://grails.1312388.n4.nabble.com/Registering-custom-flow-execution-listener-td2279764.html。我已經將上面的代碼更新爲最終的工作版本。