Hi everyone, I'm a spring boot newbie and I'd like to get more familiar with security, mvc, etc.
I created a very basic app with jpa rpos (user, role, article), login & register views with spring security and everything works fine. I noticed that by default, spring boot doesn't store session in my default jpa repository but it stores it in memory as after each server restart I'm getting logged off.
I'd like to store session in redis (or any other storage, redis seems to be the easiest to use with spring)
I followed this tutorial https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html (I'm using spring boot 5, the newest toys)
I added
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
configured my application.yml file:
spring:
session:
store-type: redis
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
jpa:
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
server:
port: 8000
---
spring:
profiles: development
datasource:
url: jdbc:postgresql://localhost:5432/blog
username: postgres
jpa:
hibernate:
ddl-auto: update
generate-ddl: true
thymeleaf:
cache: false
prefix: file:src/main/resources/templates/
resources:
static-locations: file:src/main/resources/static/
cache:
period: "0"
---
(...) prod config is here
and configuration
@Configuration
@EnableRedisHttpSession
public class RedisHttpSessionConfig {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
}
and once I'm getting logged (successfully) I see that something gets stored in redis but I'm getting this:
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: com.kgregorczyk.library.model.Role
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96) ~[spring-data-redis-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:184) ~[spring-data-redis-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:133) ~[spring-data-redis-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:136) ~[spring-data-redis-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:776) ~[spring-session-data-redis-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:649) ~[spring-session-data-redis-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:384) ~[spring-session-data-redis-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245) ~[spring-session-data-redis-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.saveSession(SessionRepositoryFilter.java:377) ~[spring-session-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:233) ~[spring-session-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:197) ~[spring-session-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:150) ~[spring-session-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81) ~[spring-session-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.31.jar:8.5.31]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.31.jar:8.5.31]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: com.kgregorczyk.library.model.Role
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:94) ~[spring-data-redis-2.0.7.RELEASE.jar:2.0.7.RELEASE]
... 34 common frames omitted
Caused by: java.io.NotSerializableException: com.kgregorczyk.library.model.Role
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) ~[na:1.8.0_161]
at java.util.HashMap.internalWriteEntries(HashMap.java:1789) ~[na:1.8.0_161]
at java.util.HashMap.writeObject(HashMap.java:1363) ~[na:1.8.0_161]
at sun.reflect.GeneratedMethodAccessor64.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1128) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) ~[na:1.8.0_161]
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) ~[na:1.8.0_161]
at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:46) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:63) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
... 36 common frames omitted
I see that spring-session-data-redis adds spring-data-redis package, I had to also exclude redis repo autoconfig:
@SpringBootApplication(exclude = {RedisRepositoriesAutoConfiguration.class})
Because I was getting warnings from redis data saying that I have multiple repository engines. (Even thougth i'm using JpaRepository, not CrudRepository interface)
Ok, I fixed it by doing "Role implements Serializable" and adding serialVersionUID field to every class. + Spring boot doesn't require any config (RedisHttpSessionConfig is useless). I don't know where docs are, please maybe add info about this requirement.
Most helpful comment
Ok, I fixed it by doing "Role implements Serializable" and adding serialVersionUID field to every class. + Spring boot doesn't require any config (RedisHttpSessionConfig is useless). I don't know where docs are, please maybe add info about this requirement.