Весенняя сессия, восстановление после «локального класса несовместимо» после развертываний - PullRequest
0 голосов
/ 22 сентября 2018

Spring session хранит сериализованные объекты в моей базе данных.Проблема в том, что иногда мой код меняется.Иногда мои объекты меняются.Это нормально.Однако я получаю такие ошибки:

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [byte[]] to type [java.lang.Object] for value '{-84, ..., 112}'; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: com.mysite.MyClass; local class incompatible: stream classdesc serialVersionUID = 1432849980928799324, local class serialVersionUID = 8454085305026634675

Я получаю эту ошибку, вызывая конечную точку Spring Boot с HttpSession в качестве аргумента, например, такую:

@GetMapping("/stuff")
public @ResponseBody MyClass getStuff(HttpSession session) {
    try {
        Object myObject = session.getAttribute("MyClass");
        if (myObject != null && myObject instanceof MyClass) {
            return (MyClass) myObject;
        } else {
            return null;
        }
    } catch (Exception e) {
        logger.warn("Invalid session data", e);
        return null;
    }
}

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

В качестве обходного пути я вынужден удалять всю таблицу сеанса при каждом развертывании, хотя большинство объектов по-прежнему совместимы!

Для ясности, решение НЕ состоит в добавлении serialVersionUuid.Потому что объекты действительно меняются несовместимыми способами от одного развертывания к другому.Это не вопрос сериализации.Это вопрос восстановления после весенней сессии.

У меня такой вопрос: как я могу излечиться после этих проблем?

1 Ответ

0 голосов
/ 22 сентября 2018

Вы не предоставили подробностей, но я предполагаю, что вы используете реализацию сеанса Spring JDBC, включенную @EnableJdbcHttpSession?

В этом случае вы можете взглянуть на JdbcHttpSessionConfiguration и особенно на setSpringSessionConversionService и setConversionService.Я полагаю, что если вы предоставите свою собственную реализацию (вы можете увидеть пример на createConversionServiceWithBeanClassLoader), то вы сможете уловить ошибку десериализации и вернуть пустую сессию.

Я думаю, все, что вам нужно, это получить MyNotFailingSessionDeserializer из DeserializingConverter, переопределить convert метод, перехватить SerializationFailedException и вернуть нулевой или пустой сеанс (не уверен, работает ли какой-либо из них).

Затем вы создаете службу конвертации, как это делает createConversionServiceWithBeanClassLoader, но используете MyNotFailingSessionDeserializerвместо DeserializingConverter

...