Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Spring Session auto-configuration fails in a war deployment as ServerProperties is not available #48493

Closed
Closed
Spring Session auto-configuration fails in a war deployment as ServerProperties is not available#48493
Assignees
Labels
type: regressionA regression from a previous release
Milestone

Description

We have just upgraded to the Spring Boot 4 and started getting a problem with Redis Auto configuration and war deployment to Tomcat.
The idea is to use Spring Session Data Redis instead of Tomcat's in-memory sessions.

It seems like SessionDataRedisAutoConfiguration depends on ServerProperties class, which is related to embedded Tomcat and not available in Tomcat's classpath.

The exception we get is

2025-12-10T17:03:03.315+01:00 ERROR 98276 --- [redis-demo] [on(4)-127.0.0.1] o.s.boot.SpringApplication : Application run failed

java.lang.IllegalStateException: Failed to generate bean name for imported class 'org.springframework.boot.session.data.redis.autoconfigure.SessionDataRedisAutoConfiguration'
at org.springframework.context.annotation.ConfigurationClassBea nDefinitionReader.registerBeanDefinitionForImportedConfigura tionClass(ConfigurationClassBeanDefinitionReader.java:172) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.ConfigurationClassBea nDefinitionReader.loadBeanDefinitionsForConfigurationClass(C onfigurationClassBeanDefinitionReader.java:145) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.ConfigurationClassBea nDefinitionReader.loadBeanDefinitions(ConfigurationClassBean DefinitionReader.java:124) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.ConfigurationClassPos tProcessor.processConfigBeanDefinitions(ConfigurationClassPo stProcessor.java:454) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.ConfigurationClassPos tProcessor.postProcessBeanDefinitionRegistry(ConfigurationCl assPostProcessor.java:306) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.support.PostProcessorRegistratio nDelegate.invokeBeanDefinitionRegistryPostProcessors(PostPro cessorRegistrationDelegate.java:349) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.support.PostProcessorRegistratio nDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegis trationDelegate.java:118) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.support.AbstractApplicationConte xt.invokeBeanFactoryPostProcessors(AbstractApplicationContex t.java:784) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.support.AbstractApplicationConte xt.refresh(AbstractApplicationContext.java:602) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.boot.SpringApplication.refresh(SpringApp lication.java:765) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.refreshContext(Sp ringApplication.java:454) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplica tion.java:321) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.web.servlet.support.SpringBootServl etInitializer.run(SpringBootServletInitializer.java:204) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.web.servlet.support.SpringBootServl etInitializer.createRootApplicationContext(SpringBootServlet Initializer.java:180) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.web.servlet.support.SpringBootServl etInitializer.onStartup(SpringBootServletInitializer.java:10 8) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.web.SpringServletContainerInitializer.on Startup(SpringServletContainerInitializer.java:171) ~[spring-web-7.0.1.jar:7.0.1]
at org.apache.catalina.core.StandardContext.startInternal(Stand ardContext.java:4416) ~[catalina.jar:11.0.15]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.j ava:164) ~[catalina.jar:11.0.15]
at org.apache.catalina.core.ContainerBase.addChild(ContainerBas e.java:564) ~[catalina.jar:11.0.15]
at org.apache.catalina.core.StandardHost.addChild(StandardHost. java:663) ~[catalina.jar:11.0.15]
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig. java:1746) ~[catalina.jar:11.0.15]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.in voke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[na:na]
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseMod elMBean.java:249) ~[tomcat-coyote.jar:11.0.15]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerIn terceptor.invoke(DefaultMBeanServerInterceptor.java:628) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invok e(JmxMBeanServer.java:790) ~[na:na]
at org.apache.catalina.mbeans.MBeanFactory.createStandardContex t(MBeanFactory.java:414) ~[catalina.jar:11.0.15]
at org.apache.catalina.mbeans.MBeanFactory.createStandardContex t(MBeanFactory.java:368) ~[catalina.jar:11.0.15]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.in voke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[na:na]
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseMod elMBean.java:249) ~[tomcat-coyote.jar:11.0.15]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerIn terceptor.invoke(DefaultMBeanServerInterceptor.java:628) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invok e(JmxMBeanServer.java:790) ~[na:na]
at java.management/com.sun.jmx.remote.security.MBeanServerAcces sController.invoke(MBeanServerAccessController.java:437) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectio nImpl.doOperationInner(RMIConnectionImpl.java:1401) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectio nImpl.lambda$doOperation$0(RMIConnectionImpl.java:1330) ~[na:na]
at java.base/jdk.internal.vm.ScopedValueContainer.callWithoutSc ope(ScopedValueContainer.java:162) ~[na:na]
at java.base/jdk.internal.vm.ScopedValueContainer.call(ScopedVa lueContainer.java:147) ~[na:na]
at java.base/java.lang.ScopedValue$Carrier.call(ScopedValue.jav a:419) ~[na:na]
at java.base/javax.security.auth.Subject.callAs(Subject.java:33 1) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectio nImpl.doOperation(RMIConnectionImpl.java:1330) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectio nImpl.invoke(RMIConnectionImpl.java:790) ~[na:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.in voke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[na:na]
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastSer verRef.java:351) ~[na:na]
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.j ava:166) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(T CPTransport.java:543) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandle r.run0(TCPTransport.java:744) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandle r.run(TCPTransport.java:623) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1090) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:614) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1474) ~[na:na]
Caused by: java.lang.IllegalArgumentException: Could not find class [org.springframework.boot.web.server.autoconfigure.ServerProperties]
at org.springframework.util.ClassUtils.resolveClassName(ClassUt ils.java:353) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.core.annotation.TypeMappedAnnotation.ada pt(TypeMappedAnnotation.java:451) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.core.annotation.TypeMappedAnnotation.get Value(TypeMappedAnnotation.java:384) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.core.annotation.TypeMappedAnnotation.asM ap(TypeMappedAnnotation.java:273) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.core.annotation.AbstractMergedAnnotation .asAnnotationAttributes(AbstractMergedAnnotation.java:191) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.AnnotationBeanNameGen erator.determineBeanNameFromAnnotation(AnnotationBeanNameGen erator.java:143) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.AnnotationBeanNameGen erator.generateBeanName(AnnotationBeanNameGenerator.java:110 ) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.context.annotation.ConfigurationClassBea nDefinitionReader.registerBeanDefinitionForImportedConfigura tionClass(ConfigurationClassBeanDefinitionReader.java:168) ~[spring-context-7.0.1.jar:7.0.1]
... 51 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.web.server.autoconfigure.ServerProperties
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(W ebappClassLoaderBase.java:1225) ~[catalina.jar:11.0.15]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(W ebappClassLoaderBase.java:1056) ~[catalina.jar:11.0.15]
at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
at java.base/java.lang.Class.forName(Class.java:547) ~[na:na]
at org.springframework.util.ClassUtils.forName(ClassUtils.java: 302) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.util.ClassUtils.resolveClassName(ClassUt ils.java:343) ~[spring-core-7.0.1.jar:7.0.1]
... 58 common frames omitted

I believe we can overcome this problem if define our own bean of type SessionRepositoryCustomizer, but for now I would like to understand if what we have is correct in terms of approach, or maybe some library/dependency is missing, that would prevent the issue from happening.

See this snippet, that allows application to run (at least):

@SpringBootApplication(exclude = {SessionDataRedisAutoConfiguration.class, SessionAutoConfiguration.class})
@EnableConfigurationProperties({SessionDataRedisProperties.class, SessionProperties.class })
public class RedisDemoApplication {

public static void main(String[] args) {
SpringApplication.run(RedisDemoApplication.class, args);
}

@Bean
@Primary
@Order(Ordered.HIGHEST_PRECEDENCE)
SessionRepositoryCustomizer<RedisSessionRepository> springBootSessionRepositoryCustomizer(
SessionProperties sessionProperties, SessionDataRedisProperties sessionDataRedisProperties) {
String cleanupCron = sessionDataRedisProperties.getCleanupCron();
if (cleanupCron != null) {
throw new InvalidConfigurationPropertyValueException("spring.session.data.redis.cleanup-cron",
cleanupCron, "Cron-based cleanup is only supported when "
+ "spring.session.data.redis.repository-type is set to indexed.");
}
return (sessionRepository) -> {
PropertyMapper map = PropertyMapper.get();
map.from(sessionProperties.determineTimeout(() -> Duration.ofMinutes(1)))
.to(sessionRepository::setDefaultMaxInactiveInterval);
map.from(sessionDataRedisProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
map.from(sessionDataRedisProperties::getFlushMode).to(sessionRepository::setFlushMode);
map.from(sessionDataRedisProperties::getSaveMode).to(sessionRepository::setSaveMode);
};
}

}

Example project can be found here https://github.com/rand0m86/redis-demo

Metadata

Metadata

Assignees

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions