PostgreSqlJdbcIndexedSessionRepositoryCustomizer makes the JdbcIndexedSessionRepository use a modified SQL query for creating session attributes which handles conflicting inserts better than the original query. In Spring Boot 2.7 all you had to do was adding a PostgreSqlJdbcIndexedSessionRepositoryCustomizer bean to the application context. In Spring Boot 3.0 that no longer seems to work.
Steps to Reproduce
I have pushed a minimal reproducible example to GitHub.
The example contains 2 versions of the same test application, one based on Spring Boot 2.7.6, the other one based on Spring Boot 3.0.0. Both share this configuration:
package org.devopsix.boot.session;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.jdbc.PostgreSqlJdbcIndexedSessionRepositoryCustomizer;
@Configuration
public class SessionConfig {
@Bean
public PostgreSqlJdbcIndexedSessionRepositoryCustomizer postgreSqlJdbcIndexedSessionRepositoryCustomizer() {
return new PostgreSqlJdbcIndexedSessionRepositoryCustomizer();
}
}
- Check out the example.
- Run
mvn -f spring-boot-2.7/pom.xml verify - Run
mvn -f spring-boot-3.0/pom.xml verify
The first command will print something like this:
2022-12-05 15:08:07.234 DEBUG 6284 --- [o-auto-1-exec-1] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) VALUES
(?, ?, ?) ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME) DO UPDATE SET ATTRIBUTE_BYTES = EXCLUDED.ATTRIBUTE_BYTES]
The presence of ON CONFLICT ... means the modified SQL query is being used.
The second command will print something like this:
2022-12-05T15:08:52.170+01:00 DEBUG 13560 --- [o-auto-1-exec-1] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES)
VALUES (?, ?, ?)
]
The absence of ON CONFLICT ... means the modified SQL query is not being used.
Suspected Cause and Potential Work-Arounds
JdbcSessionConfiguration.springBootSessionRepositoryCustomizer adds another customizer to the application context.
JdbcHttpSessionConfiguration.sessionRepository happens to apply PostgreSqlJdbcIndexedSessionRepositoryCustomizer before the other customizer. Unfortunately, the other customizer seems to cause JdbcIndexedSessionRepository#prepareQueries to be invoked again which overrides the customized query.
Adding @Order(Ordered.LOWEST_PRECEDENCE) to the PostgreSqlJdbcIndexedSessionRepositoryCustomizer bean has not helped. As far as I understand, the other customizer (implicitly) also has LOWEST_PRECEDENCE and hence that does not change the order of application.
I ended up adding an InitializingBean bean to the application context which in its afterPropertiesSet method applies PostgreSqlJdbcIndexedSessionRepositoryCustomizer to the repository bean again.
Comment From: philwebb
Closing in favor of PR #33514.
Comment From: izeye
The above comment seems to reference a wrong issue. It seems to need to be https://github.com/spring-projects/spring-boot/pull/33514, not https://github.com/spring-projects/spring-boot/pull/33663.
Comment From: wilkinsona
Thanks, @izeye. I've updated Phil's comment.