大規模なGrails1.3.7プロジェクトに取り組んでおり、ロギングの目的でフィルターからフロー状態名にアクセスしたいと考えています。私はたくさんグーグルしてきましたが、私が見つけた最も近い答えは次のとおりです。Grails WebFlow State Nameですが、フロー自体の中からのみ機能します。
現在のセッションで実行されているフローの状態名をフローの外部(フィルター)から取得する方法はありますか?
前もって感謝します、
ギレルモ
大規模なGrails1.3.7プロジェクトに取り組んでおり、ロギングの目的でフィルターからフロー状態名にアクセスしたいと考えています。私はたくさんグーグルしてきましたが、私が見つけた最も近い答えは次のとおりです。Grails WebFlow State Nameですが、フロー自体の中からのみ機能します。
現在のセッションで実行されているフローの状態名をフローの外部(フィルター)から取得する方法はありますか?
前もって感謝します、
ギレルモ
たくさんのグーグルとデバッグの後、私はなんとか次のコードを作成することができました。シンプルなアプリケーションで動作します。休日から戻ってきたらメインアプリケーションと統合して、この質問を更新します。
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)}")
}
}
}
}
編集:上記のコードは、特定の時点での現在のフロー状態の名前を判別するのに問題ありませんが、フローの実行が進むにつれて、ロギングフレームワークのマップされた診断コンテキストは更新されません。この目的のために、を実装しorg.springframework.webflow.execution.FlowExecutionListener
て登録する必要がありますconf/spring/resources.groovy
:
beans = {
myLoggingFlowExecutionListener(org.example.MyLoggingFlowExecutionListener)
}
このリスナーBeanとBeanをBeanに登録する必要がありますhibernateConversationListener
がexecutionListenerLoader
、何らかの理由で、この場合、Spring 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
メソッドは、ロギングの目的で使用できる多くのコンテキスト情報を受け取ります(わかりやすくするために、このクラスの実装は省略しています)。
EDIT2 :フローのライフサイクル中にドメインオブジェクトを操作するときにhibernateConversationListener
、結果にBeanを追加しないとHibernate例外が発生します。executionListenerLoader
ただし、この特定のケースではSpring DSLが機能しないため、XML形式を使用して必要なBeanを宣言する必要がありました。http://grails.1312388.n4.nabble.com/Registering-custom-flow-execution-listener-td2279764.htmlを参照してください。上記のコードを最終的な動作中のバージョンに更新しました。