From d5daa283f79646e08d70d35dfd45f004d7d8bf39 Mon Sep 17 00:00:00 2001 From: Marcus Hert Da Coregio Date: Tue, 4 Jun 2024 15:47:54 -0300 Subject: [PATCH] Add instructions if object is not deserialized into the right type Closes gh-3009 --- .../modules/ROOT/pages/configuration/jdbc.adoc | 8 +++++++- .../src/main/java/sample/config/SessionConfig.java | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc b/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc index b8420e0d..07b72eac 100644 --- a/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc +++ b/spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc @@ -294,7 +294,7 @@ You can create a new one if you prefer. You might need to do the same for other objects that are persisted in the session. <4> Add the `JsonSerializer`/`JsonDeserializer` that we created into the `ConversionService`. -Now that we configured how Spring Session JDBC converts our attributes values into `byte[]`, we must customize the query that insert the session attributes. +Now that we configured how Spring Session JDBC converts our attributes values into `byte[]`, we must customize the query that inserts and updates the session attributes. The customization is necessary because Spring Session JDBC sets content as bytes in the SQL statement, however, `bytea` is not compatible with `jsonb`, therefore we need to encode the `bytea` value to text and then convert it to `jsonb`. [tabs] @@ -336,6 +336,12 @@ public class SessionConfig { And that's it, you should now be able to see the session attributes saved as JSON in the database. There is a https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute[sample available] where you can see the whole implementation and run the tests. +[NOTE] +==== +If your https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/user-details.html#page-title[`UserDetails` implementation] extends Spring Security's `org.springframework.security.core.userdetails.User` class, it is important that you register a custom deserializer for it. +Otherwise, Jackson will use the existing `org.springframework.security.jackson2.UserDeserializer` which won't result in the expected `UserDetails` implementation. See https://github.com/spring-projects/spring-session/issues/3009[gh-3009] for more details. +==== + [[specifying-datasource]] == Specifying an alternative `DataSource` diff --git a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java index ee2f4e50..817d17a0 100644 --- a/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java +++ b/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java @@ -26,11 +26,21 @@ public class SessionConfig implements BeanClassLoaderAware { VALUES (?, ?, encode(?, 'escape')::jsonb) """; + private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """ + UPDATE %TABLE_NAME%_ATTRIBUTES + SET ATTRIBUTE_BYTES = encode(?, 'escape')::jsonb + WHERE SESSION_PRIMARY_ID = ? + AND ATTRIBUTE_NAME = ? + """; + private ClassLoader classLoader; @Bean SessionRepositoryCustomizer customizer() { - return (sessionRepository) -> sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY); + return (sessionRepository) -> { + sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY); + sessionRepository.setUpdateSessionAttributeQuery(UPDATE_SESSION_ATTRIBUTE_QUERY); + }; } @Bean("springSessionConversionService")