Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I inject a service into a filter in Grails?

Tags:

grails

I have a service to get and set the user in the session. I would like to pass in some user information to each view if there is a logged in user and thought a filter would be the best way so I don't have to duplicate that in every controller/action. When I run the app, it get this error:

Error creating bean with name 'userService': Scope 'session' is not active for the current thread

My filter looks like this:

class SecurityFilters {
    def userService

    def filters = {
        setUser(controller:'*', action:'*') {
            before = {
                if (userService.isLoggedIn()) {
                    request.user = userService.getUser()
                } else {
                    request.user = null
                }
            }
        }
    }   
}

I know I can just ultimately access the user through session.user, but I want to be able to call userService.isLoggedIn() which I can't easily through the view. So is there a way to inject the service into the filter, or should I just create a taglib to wrap userService.isLoggedIn()?

like image 741
varikin Avatar asked Sep 29 '10 22:09

varikin


1 Answers

It looks like the problem is your userService is scoped to the session, and there is not necessarily a session at the time the attempt to inject the service into the filter happens.

If your userService is necessarily session-scoped then you need to use a scoped proxy in your spring config. E.g. in grails-app/conf/spring/resources.groovy:

import com.your.service.UserService
...
userServiceSession(UserService)
{ bean ->
    bean.scope = 'session'
}
userServiceSessionProxy(org.springframework.aop.scope.ScopedProxyFactoryBean)
{
    targetBeanName = 'userServiceSession'
    proxyTargetClass = true
}

Then rename your injected variable in your SecurityFilter:

def userServiceSessionProxy

(and obviously rename where you use it elsewhere in the class).

What this should do is inject the proxy at injection time, but only go to the actual service at the time the filter is executed (when there is a session).

Note: not sure whether doing this still lets other places where there will be a session (e.g. controllers) still reference the service as 'userService', if not you might be able to rename userServiceSession to userService in resources.groovy (and update targetBeanName accordingly).

like image 169
Chris Avatar answered Sep 28 '22 09:09

Chris