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
Document how to rely on ServletContext with an embedded container setup #24561
Comments
Having a |
Thank you for your quick response! We are migrating our Spring (5.2) Jetty Servlet (9.4) application to spring boot. The same configuration class used to work in the previous setup for us hence I decided to create an issue. We are actually following a recommended way to configure CometD library with Spring. I will try to figure out if I can use your suggestion to achieve the same. |
Unfortunately, that doesn't change the fact that this is unusual and should be avoided. I've created an issue to ask them to consider reviewing this part of the code and doc. |
Sadly, I am a bit of at loss in here. My problem is that my class implementing Could you share more info regarding:
I don't think I fully understand how to utilize that to solve my problem. |
@zaynetro thanks for the update. When you start a web application with the Spring Framework, the server is already started by the time the That said, this is mixing two different phase of the application. A
Going forward, could you please move that to an actual GitHub repository? This is what I had to do to reproduce the problem and can be a good base for discussion. I've pushed your change and then an additional commit that describes what we were discussing here. Please note in particular that the access to Can you please give that |
How can you express a dependency on I need for a I have tried to express my problem here: snicoll-scratches/spring-boot-issue-24561#1 |
That is a good point. Rather, you should get a callback once the server has started (and the servlet context is set). You could do so via
With an embedded server support, I don't see a way for a bean to reliably depend on the
Great. Let's continue the brainstorm over there. |
Alright, I think I have found a workaround solution that works for me. I create my bean that depends on servlet context and create post processor as a static bean. AnotherConfig.java@Configuration
public class AnotherConfig implements ServletContextAware {
private static final Logger LOG = LoggerFactory.getLogger( AnotherConfig.class );
private ServletContext servletContext;
@Override
public void setServletContext( ServletContext servletContext ) {
this.servletContext = servletContext;
}
@Bean
public Hello hello() {
return new Hello(servletContext);
}
@Bean
public static DemoPostProcessor demoPostProcessor() {
return new DemoPostProcessor();
}
} And then in my post processor I try to get a bean after it has been initialized. DemoPostProcessor.javapublic class DemoPostProcessor implements DestructionAwareBeanPostProcessor, ApplicationContextAware {
private static final Logger LOG = LoggerFactory.getLogger( DemoPostProcessor.class );
private WebApplicationContext applicationContext;
Optional<Hello> getHello() {
if( applicationContext.getServletContext() != null ) {
// Once we have servletContext I want to instantiate my Hello bean. This could fail with:
//
// > Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException:
// > Error creating bean with name 'hello':
// > Requested bean is currently in creation: Is there an unresolvable circular reference?
try {
return Optional.of( applicationContext.getBean( Hello.class ) );
} catch( BeanCurrentlyInCreationException e ) {
// Ignore
}
}
return Optional.empty();
}
@Override
public Object postProcessBeforeInitialization( Object bean, String name ) throws BeansException {
Optional<Hello> found = getHello();
if( found.isPresent() ) {
found.get().process( bean, name );
}
return bean;
}
@Override
public void postProcessBeforeDestruction( Object bean, String name ) throws BeansException {
LOG.warn("Destruction of {} with servletContext {}", name, getHello().get().servletContext);
}
@Override
public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
this.applicationContext = (WebApplicationContext) applicationContext;
}
} Note that I don't particularly like this solution but it works for my use case. There is an option to use CometD library without processing the annotations so I might switch to that if this solution becomes unreliable. As a final note it would be nice for a bean to be able to depend on a servlet context but I understand that it might be undesirable with post processor beans. Feel free to close this issue. UPD: this solution is ugly and not recommended. I have switched to post processing beans manually instead. |
If Configuration class implements both
ServletContextAware
andDestructionAwareBeanPostProcessor
thensetServletContext
will not be called.Steps to reproduce:
spring-boot-starter-web
dependencyDemoConfig
AnotherConfig
Logs:
setServletContext
is called correctly forAnotherConfig
but never called forDemoConfig
.The text was updated successfully, but these errors were encountered: