我正在研究Grails 2.3.4应用程序。我正在将Audit-Trail Plugin v2.0.3添加到我们的项目中,因为我们需要跟踪所有创建和修改时间以及用户以帮助调试可能出现的问题。我已经成功安装了插件,除了我们无法再在开发环境中引导数据之外,一切都有效。
这是我们的Config.groovy:
plugin {
audittrail {
createdBy.field = "createUser"
createdBy.type = "java.lang.String"
createdDate.field = "createDate"
editedBy.field = "updateUser"
editedBy.type = "java.lang.String"
editedDate.field = "updateDate"
/*
This closure returns the value of the user for the plugin.
*/
currentUserClosure = { ctx ->
ctx.userServiceProxy.getUserToken()
}
}
这是UserService 包com.perceptivecloud.frg.datadefinition
/**
* Service class to help the Audit-Trail plugin get userId information.
*
* TODO:This will need to be revisited when real Authorization is implemented.
*/
class UserService {
/*
force a new instance of the service per session.
see http://grails.org/doc/latest/guide/services.html#scopedServices for details
*/
static scope = "session"
String userToken
void setUserToken(String userId) {
userToken = userId
}
String getUserToken() {
userToken
}
}
代理服务在resources.groovy中定义:
userServiceProxy(ScopedProxyFactoryBean) {
targetBeanName = 'userService'
proxyTargetClass = true
}
我们的Domain类看起来像:
@AuditStamp
class MyDomainClass {
String name
static constraints = {
name nullable: false
}
}
我们的BootStrap.groovy看起来像:
def userServiceProxy
...
development {
userServiceProxy.setUserToken("bootstrap")
def claims = new MyDomainClass(name: 'Submit claim')
claims.save(flush: true)
}
当我启动应用程序时,我得到的堆栈跟踪如下:
| Error 2014-03-13 13:10:48,963 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application: Error creating bean with name 'userService': 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 'userService': 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
->> 41 | doCall in BootStrap$_closure1_closure2_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 321 | execute in grails.util.Environment$EnvironmentBlockEvaluator
| 302 | executeForEnvironment . . . in grails.util.Environment
| 277 | executeForCurrentEnvironment in ''
| 262 | run . . . . . . . . . . . . in java.util.concurrent.FutureTask
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 744 | run in java.lang.Thread
当我尝试在bootstrap中创建会话时,如下所示:
development {
WebUtils.storeGrailsWebRequest(new GrailsWebRequest(new GrailsMockHttpServletRequest(),
new GrailsMockHttpServletResponse(), (ServletContext)servletContext))
WebUtils.retrieveGrailsWebRequest().applicationContext.getBean('userServiceProxy')
.setUserToken("userToken")
def claims = new MyDomainClass(name: 'Submit claim')
claims.save(flush: true)
}
我收到了以下错误。
| Error 2014-03-13 12:50:34,179 [localhost-startStop-1] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
Message: null id in MyDomainClass entry (don't flush the Session after an exception occurs)
Line | Method
->> 112 | doCall in Config$_run_closure2_closure7_closure11_closure12
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 67 | currentUserId in grails.plugin.audittrail.AuditTrailHelper
| 45 | doCall . . . . . . . . . . . in grails.plugin.audittrail.AuditTrailInterceptor$_onSave_closure1
| 37 | onSave in grails.plugin.audittrail.AuditTrailInterceptor
| 46 | doCall . . . . . . . . . . . in BootStrap$_closure1_closure2_closure4
| 321 | execute in grails.util.Environment$EnvironmentBlockEvaluator
| 302 | executeForEnvironment . . . in grails.util.Environment
| 277 | executeForCurrentEnvironment in ''
| 262 | run . . . . . . . . . . . . in java.util.concurrent.FutureTask
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 744 | run in java.lang.Thread
从这些消息告诉我,不知何故,我需要能够在请求或会话上下文中保存对象,我不知道如何做到这一点。
绝对最低限度,我试图解决的问题是确保每次使用Audit-Trail插件时启动开发环境时数据库中都存在一致的数据。