Дата последнего входа в grails с spring security

#grails #spring-security #grails-plugin

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

Вопрос:

Я сталкиваюсь с этой ошибкой, когда пытаюсь установить lastLogin дату с помощью прослушивателя событий в Config.groovy :

2011-05-12 00:30:16 501 [события с ошибкой «ajp-bio-8009»-exec-6].Исправленный defaultflusheventlistener — Не удалось синхронизировать состояние базы данных с сессией org.hibernate.Исключение StaleObjectStateException: строка была обновлена или удалена другой транзакцией (или неверно отображено несохраненное значение): [spl.User#110]

Мой код:

 grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
    User.withTransaction {
        def user = appCtx.springSecurityService.currentUser
        user.lastLogin = new Date()
        user.save(flush: true)
    }
}
  

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

РЕДАКТИРОВАТЬ: я смог повторить ошибку в своей тестовой среде, выполнив одновременный вход в систему от имени одного и того же пользователя. Для дальнейшей отладки я добавил несколько инструкций print внутри обработчика событий и начал работать с ним. Оказывается, что когда я подписываюсь или кто-либо регистрируется на моем сайте, обработчик событий вызывается НЕСКОЛЬКО раз, следовательно, исключение устаревшего объекта. Почему onInteractiveAuthenticationSuccessEvent вызывается более одного раза при входе в систему?

Спасибо, Рикардо

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

1. Я бы исследовал — в какие другие пользовательские поля можно записать во время входа в систему (может быть, это какая-то фоновая работа?).

Ответ №1:

Сначала вы захотите получить новую копию пользователя в сеансе:

 grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
    User.withTransaction {
        def user = User.get(appCtx.springSecurityService.currentUser.id)
        user.lastLogin = new Date()
        user.save(flush: true)
    }
} 
  

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

1. Итак, я смог повторить сбой в моей тестовой среде, выполнив одновременный вход с одним и тем же пользователем. Я попробовал ваше исправление, чтобы получить новую копию пользователя, и оно по-прежнему выдает исключение.