2010-09-29 11 views
8

Tengo un servicio para obtener y configurar al usuario en la sesión. Me gustaría pasar algo de información del usuario a cada vista si hay un usuario conectado y pensé que un filtro sería la mejor manera para que no tenga que duplicar eso en cada controlador/acción. Cuando ejecuto la aplicación, que sale este error:¿Puedo inyectar un servicio en un filtro en Grails?

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

Mi filtro se ve así:

class SecurityFilters { 
    def userService 

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

Sé que puedo solo en última instancia, acceder al usuario a través session.user, pero yo quiero estar capaz de llamar a userService.isLoggedIn() que no puedo acceder fácilmente a través de la vista. Entonces, ¿hay alguna manera de inyectar el servicio en el filtro, o debería simplemente crear un taglib para ajustar userService.isLoggedIn()?

+0

Bueno, la respuesta fue no, no puedo. Agregué un comentario que aparentemente fue borrado diciendo que no podía y proporcioné un enfoque diferente. – varikin

Respuesta

9

Parece que el problema es que su userService tiene un alcance para la sesión, y no hay necesariamente una sesión en el momento en que ocurre la tentativa de inyectar el servicio en el filtro.

Si su userService es necesariamente un ámbito de sesión, entonces necesita utilizar un proxy de ámbito en su configuración de primavera. P.ej. en griales-app/conf/primavera/resources.groovy:

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

A continuación, cambiar el nombre de la variable se inyecta en su SecurityFilter:

def userServiceSessionProxy 

(y, obviamente, cambiar el nombre de donde vaya a utilizarlo en otra parte de la clase).

Lo que debe hacer es inyectar el proxy en el momento de la inyección, pero solo ir al servicio real en el momento en que se ejecuta el filtro (cuando hay una sesión).

Nota: no estoy seguro de si esto todavía permite que otros lugares donde habrá una sesión (por ejemplo, controladores) sigan haciendo referencia al servicio como 'userService'; si no, puede cambiar el nombre de userServiceSession a userService en resources.groovy (y actualice targetBeanName en consecuencia).

+0

Esto suena como una solución válida, pero opté por cambiar a un taglib en su lugar. Parecía más simple. – varikin

0
import org.codehaus.groovy.grails.web.context.ServletContextHolder 
import org.springframework.context.ApplicationContext 
import org.springframework.web.context.support.WebApplicationContextUtils 
class SecurityFilters { 
    def userService 

    def filters = { 
     setUser(controller:'*', action:'*') { 
      before = { 
       def servletCtx = ServletContextHolder.getServletContext() 
       ApplicationContext applicationContext = WebApplicationContextUtils. 
        getRequiredWebApplicationContext(servletCtx) 
       userService =applicationContext.getBean('userService') 
       if (userService.isLoggedIn()) { 
        request.user = userService.getUser() 
       } else { 
        request.user = null 
       } 
      } 
     } 
    } 
} 
Cuestiones relacionadas