-
Notifications
You must be signed in to change notification settings - Fork 38.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Propagate fully capable ServletContext in AbstractContextLoaderInitializer (for SessionCookieConfig access) #22319
Comments
Interesting... when the Servlet container is initialized via the infrastructure in
That implementation always throws an |
Thus, it would appear that |
Specifically, the following code from Tomcat's for (Object lifecycleListener: getApplicationLifecycleListeners()) {
lifecycleListeners.add(lifecycleListener);
if (lifecycleListener instanceof ServletContextListener) {
noPluggabilityListeners.add(lifecycleListener);
}
} |
I'm not yet sure what we can do here to make this work, but I've tentatively slated this for 5.2 for further investigation. |
In the interim -- not that I'd really recommend it -- you could introduce a hack that works on that particular version of Tomcat by using reflection to access the underlying private static class NoPluggabilityServletContext
implements ServletContext {
private final ServletContext sc; |
Thanks for the feedback @sbrannen. Unfortunately, since we're hitting this limitation in Spring Session configuration infrastructure, any workaround that involves specific Servlet Container classes is not viable. I should have probably mentioned that the code involved also works in a Spring Boot app - I didn't include that in the sample repo though. |
Sure. That was actually intended to be more of a joke, which I should have stated explicitly. 😉 You'd obviously need a solution that works across containers and according to the Servlet spec.
Interesting. In the sample you provided it appears that Tomcat is behaving according to the spec, so it might well be that the Spring Boot embedded Servlet container support registers the Spring We'll have to take a look at what Spring Boot does in order to better understand the issue at hand. Thanks for the feedback! |
I have unassigned the milestone and returned the status to "waiting for triage" in order for the team to assess the possibility of a such an enhancement. |
I've updated the minimal sample app repo with Spring Boot based sample and readme with relevant information on how to start each sample. |
+1 :) |
Any update on this , when the fix will be available?? Appropriate your help.. |
I don't know why a In the current situation, To make this work the |
Anyone with Java Configuration will encounter this who uses Spring Session. I'm converting a non-Spring boot XML application to Java Configuration because of OAuth2Login configuration with XML namespace #4557 and ran into this issue. So, either way I can't use both until I go to Spring Boot. |
Can't initialize redis session because of some crap in the servlet spec. See spring-projects/spring-framework#22319 I'm too tired to keep up with this crap, so I herewith officially retire this project.
Seems manually creating a @Bean
public CookieSerializer cookieSerializer(ServletContext ctx) {
logger.debug("Creating cookie serializer");
DefaultCookieSerializer cs = new DefaultCookieSerializer();
try {
SessionCookieConfig cfg = ctx.getSessionCookieConfig();
cs.setCookieName(cfg.getName());
cs.setDomainName(cfg.getDomain());
cs.setCookiePath(cfg.getPath());
cs.setCookieMaxAge(cfg.getMaxAge());
} catch (UnsupportedOperationException e) {
cs.setCookieName("MY_SESSIONID");
cs.setCookiePath(ctx.getContextPath());
}
return cs;
} This is because |
Any kind updates here? I encountered the same error with spring 6.0.10 and tomcat 10.1.12, and I also tried @joerx 's method, but the things just doesn't work, resulting my app cannot serialize sessions to redis. Here is my code: @Configuration
@EnableRedisHttpSession
public class SessionConfig {
@Bean
public CookieSerializer cookieSerializer(ServletContext ctx) {
logger.debug("Creating cookie serializer");
DefaultCookieSerializer cs=new DefaultCookieSerializer();
try {
SessionCookieConfig cfg=ctx.getSessionCookieConfig();
cs.setCookieName(cfg.getName());
cs.setDomainName(cfg.getDomain());
cs.setCookiePath(cfg.getPath());
cs.setCookieMaxAge(cfg.getMaxAge());
} catch(UnsupportedOperationException e) {
logger.debug("print the exception", e);
cs.setCookieName("MY_SESSIONID");
cs.setCookiePath(ctx.getContextPath());
}
return cs;
}
@Bean
public JedisConnectionFactory connectionFactory() throws IOException {
RedisStandaloneConfiguration config=new RedisStandaloneConfiguration(/*...*/);
config.setPassword(/*...*/);
JedisPoolConfig poolConfig=new JedisPoolConfig();
poolConfig.setMaxTotal(/*...*/);
poolConfig.setMaxIdle(/*...*/);
poolConfig.setMaxWait(/*...*/);
JedisClientConfiguration clientConfiguration=JedisClientConfiguration.builder()
.connectTimeout(/*...*/)
.readTimeout(/*...*/)
.usePooling()
.poolConfig(poolConfig)
.build();
return new JedisConnectionFactory(config, clientConfiguration);
}
}
public class MyInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class, SessionConfig.class};
}
//...
} I also tried to put If I didn't misremember, the code worked fine (without cookieSerializer Bean) on spring 5.3.6 and tomcat 9.0.52. |
I found an alternative config code instead of using That is just construct the public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Filter[] getServletFilters() {
RedisTemplate<String, Object> redisTemplate=new RedisTemplate<>();
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
JedisConnectionFactory connectionFactory=SessionConfig.connectionFactory(); // construct your redis connection factory anywhere else
connectionFactory.afterPropertiesSet();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.afterPropertiesSet();
SessionRepositoryFilter<?> sessionRepositoryFilter=new SessionRepositoryFilter<>(new RedisSessionRepository(redisTemplate));
// config other filters
return new Filter[]{sessionRepositoryFilter/*, otherFilters*/};
}
//...
} This works fine for me, but as I am using |
It looks like |
Affects: 5.1.4.RELEASE
In Spring Session, we try to provide convenience of configuring our default
CookieSerializer
using Servlet API'sSessionCookieConfig
. The code involved can be seen here.In a plain Spring app, without Spring Boot involved, this fails with Java based config due to inability to obtain
SessionCookieConfig
off injectedServletContext
. However, the same action succeeds with XML based config.I've put together a minimal sample app that exhibits this behavior.
Running XML config based sample using
./gradlew :sample-xml:tomcatRun
will yield the following log output:While running Java config based sample using
./gradlew :sample-java:tomcatRun
will result in the following error logged:This was originally reported against Spring Session in spring-projects/spring-session#1040.
The text was updated successfully, but these errors were encountered: