springSecurityService имеет значение null в базовом контроллере

#grails #spring-security

#grails #spring-безопасность

Вопрос:

Это довольно странная проблема, и я занимался этим некоторое время, поэтому я схожу с ума.

У меня есть контроллер, расширяющий другой контроллер, поэтому я могу иметь несколько контроллеров, наследующих метод, и они выглядят примерно так:

 class EventController extends EventAwareController {

    def springSecurityService

    def edit = {
        // this line prints out principal id
        println springSecurityService.principal.id
        def eventInstance = getAuthorizedEventById(params.id)
        if (!eventInstance) {
            flash.message = "${message(code: 'event.not.found.message')}"
            redirect(action: "list", controller: "event")
            return false
        }
}

class EventAwareController {
    def eventService
    def springSecurityService

    def getAuthorizedEventById(def eventId) {
        def event
        if (eventId) {
            // this springSecurityService is null and throws an error
            event = eventService.findAuthorizedEvent(eventId, springSecurityService.principal.id)
            if (event) {
                session.eventId = eventId
            }
        }
        return event
    }

}
  

EventAwareController выдает:

java.lang.Исключение NullPointerException: не удается получить свойство ‘principal’ для нулевого объекта в com.ticketbranch.EventAwareController.getAuthorizedEventById(EventAwareController.groovy:14)

но мой оператор prinln в EventController печатает основной идентификатор без каких-либо проблем ?!? Итак, springSecurityService вводится как null в EventAwareController?

Есть идеи? предложения? Спасибо.

Ответ №1:

У вас есть поле в обоих классах, и это проблема при использовании Groovy. Внедрение зависимостей в Grails обычно выполняется так, как вы делаете, с def <beanname> помощью . Это общедоступное поле, поэтому Groovy создает для него общедоступный метод получения и установки и делает поле закрытым. Средство получения не используется, но Spring видит средство установки, и поскольку компоненты настроены для подключения по имени (в отличие от типа), компонент вводится, поскольку есть совпадение между именем установщика ( setSpringSecurityService ) и именем компонента.

Поскольку у вас это происходит дважды, у вас есть два сеттера и один выигрыш, поэтому у вас будет нулевое значение для частного поля в одном классе.

Но, как и любое общедоступное (или защищенное) свойство, внедрение зависимостей наследуется, поэтому просто удалите его из всех ваших подклассов и оставьте в базовом классе.

Комментарии:

1. очень классный ответ, я потратил час, пытаясь понять, что происходит… спасибо, что помогли мне понять, что происходит 🙂