Skip to content
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

Spring boot 1.5.13 with cometd 3.0.9 throws can't find servletContext exception #847

Open
Lisa09Liu opened this Issue Mar 14, 2019 · 10 comments

Comments

Projects
None yet
2 participants
@Lisa09Liu
Copy link

Lisa09Liu commented Mar 14, 2019

s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'primeLocateCometDService' defined in file [XXX\PrimeLocateCometDService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bayeux' defined in class path resource [A-context.xml]: Cannot resolve reference to bean 'servletContext' while setting bean property 'options' with key [TypedStringValue: value [javax.servlet.ServletContext], target type [null]]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'servletContext' available


APPLICATION FAILED TO START


Description:

Parameter 0 of constructor in com.citi.pf.realtime.primelocate.PrimeLocateCometDService required a bean named 'servletContext' that could not be found.

Action:

Consider defining a bean named 'servletContext' in your configuration.

Hi I have tried many methods to deal with this problem. I want to know if the spring boot version or cometd version is the reason caused this problem. Or the servlectContext Initialization after spring bean initialization ? Could you give me some advices ?

@sbordet

This comment has been minimized.

Copy link
Member

sbordet commented Mar 14, 2019

The reason of this problem is very likely how you have written your code.

Please attach to this issue a reproducible project that shows the problem.

@Lisa09Liu

This comment has been minimized.

Copy link
Author

Lisa09Liu commented Mar 14, 2019

Follows are the xml file :

<bean id="bayeux" class="XX.InitBayeuxServerImpl" init-method="start" destroy-method="stop">
	<property name="cacheMongo" ref="mongoCacheForCometD" />
	<property name="securityPolicy" ref="securityPolicyCometD" />
	<property name="options">
        <map>
            <entry key="javax.servlet.ServletContext" value-ref="**servletContext**" />
            <entry key="ws.cometdURLMapping" value="/cometd/*" />
            <entry key="maxInterval" value="65000" />
            <entry key="timeout" value="30000" />
            <entry key="interval" value="15000" />
            <entry key="maxSessionsPerBrowser" value="3" />
            <entry key="jsonContext" value="org.cometd.server.Jackson1JSONContextServer" />
        </map>
    </property>
    <property name="transports">
        <list>
            <bean id="websocketTransport" class="org.cometd.websocket.server.WebSocketTransport">
                <constructor-arg ref="bayeux" />
            </bean>
            <bean id="jsonTransport" class="org.cometd.server.transport.JSONTransport">
                <constructor-arg ref="bayeux" />
            </bean>
            <bean id="jsonpTransport" class="org.cometd.server.transport.JSONPTransport">
                <constructor-arg ref="bayeux" />
            </bean>
        </list>
    </property>
</bean>

<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
    <property name="attributes">
        <map>
            <entry key="org.cometd.bayeux" value-ref="bayeux" />
        </map>
    </property>
</bean>
@sbordet

This comment has been minimized.

Copy link
Member

sbordet commented Mar 14, 2019

I'm really confused now.

Aren't you using Spring Boot, which does everything via annotations?

What's the XML for?

@Lisa09Liu

This comment has been minimized.

Copy link
Author

Lisa09Liu commented Mar 14, 2019

Follows is application class , because I'm working on a more complex project, which used to be a CometD integrated spring with beans configured in xml files, now I want to switch to spring boot to use cometd.

@SpringBootApplication
@ImportResource({
				 "classpath:a-context.xml",
				 })
@ServletComponentScan
@ComponentScan
@EnableAutoConfiguration(exclude= { 
		DataSourceAutoConfiguration.class,
		JmsAutoConfiguration.class, 
		MongoAutoConfiguration.class, 
		MongoDataAutoConfiguration.class, 
		MultipartAutoConfiguration.class, 
		SecurityAutoConfiguration.class, 
		SecurityAutoConfiguration.class, 
		FallbackWebSecurityAutoConfiguration.class,
		OAuth2AutoConfiguration.class})
public class Application extends SpringBootServletInitializer{

	private static final Logger logger = LoggerFactory.getLogger(Application.class);
	
	
	public static void main(String[] args) {
		SpringApplication.run(PFRealtimeServicesApplication.class,args);
	}
	
	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(Application.class);
	}
	
	@Override
	public void onStartup(ServletContext servletContext) {
		ServletRegistration.Dynamic cometdServlet = servletContext.addServlet("cometd", AnnotationCometDServlet.class); 
        cometdServlet.addMapping("/cometd/*");
        cometdServlet.setAsyncSupported(true);
        cometdServlet.setLoadOnStartup(1);
        //cometdServlet.setInitParameter("services", MyCometDService.class.getName());
	}
	
	@Bean
	protected ServletContextInitializer servletInitializer() {
		return servletContext -> servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bayeuxServer(servletContext));
	}
	
	@Bean
	@DependsOn("servletInitializer")
	protected BayeuxServer bayeuxServer(ServletContext servletContext) {
		BayeuxServerImpl bean = new BayeuxServerImpl();
		bean.setTransports(new WebSocketTransport(bean),new JSONTransport(bean),new JSONPTransport(bean));
		servletContext.setAttribute(BayeuxServer.ATTRIBUTE,bean);
		bean.setOption(ServletContext.class.getName(), servletContext);
		bean.setOption("ws.cometdURLMapping", "/cometd/*");
		return bean;
	}
@sbordet

This comment has been minimized.

Copy link
Member

sbordet commented Mar 14, 2019

I don't know Spring Boot well enough to help you here; there are a lot of things you are doing in the snippets above that it's difficult to say what is it that breaks things.

I recommend that you start from the super-simple working example that you find in CometD.
Once you have that running, add one at a time of your additional configuration/annotation/xml files/etc. until it breaks.

The problem appears to be that with Spring Boot the XML processing happen before usual and the ServletContext is not available.
Given that the XML is only related to CometD, why don't you convert it to annotations and get rid of it?

@Lisa09Liu

This comment has been minimized.

Copy link
Author

Lisa09Liu commented Mar 15, 2019

@sbordet
Sorry to trouble you so many times , today I found the servletContext is need by Bayeux , however , Spring boot always init the Bayeux before servletcontext , do you have any good idea ?

Thanks,
Lisa.

@sbordet

This comment has been minimized.

Copy link
Member

sbordet commented Mar 15, 2019

@Lisa09Liu it is not always the case that the ServletContext is initialized before the BayeuxServer bean.
The current example in the CometD source code works just fine.

What I recommend is that you strip down your code to the bare minimum, and use exactly the classes and annotations used in the CometD example.

For example, the CometD code uses class CometDApplication implements ServletContextInitializer while your code uses class Application extends SpringBootServletInitializer.
Just that difference could be enough to break your code.

Start from the CometD example. Then work your way to what you need, one step at a time.

When Spring (Boot) works, it's magic; when it does not you have to reverse engineer its magic - and that's hard.

@Lisa09Liu

This comment has been minimized.

Copy link
Author

Lisa09Liu commented Mar 15, 2019

@sbordet OK I will try it , thank you very much !

@Lisa09Liu

This comment has been minimized.

Copy link
Author

Lisa09Liu commented Mar 20, 2019

Hi @sbordet
In my project spring boot with cometd , I have some js files like : cometd-adapter.js .
Do you know I have to make it to war ? May I use it to jar ?

@sbordet

This comment has been minimized.

Copy link
Member

sbordet commented Mar 20, 2019

@Lisa09Liu if you want to add static resources to your Spring Boot application, you should follow the Spring Boot tutorials, for example:
http://www.springboottutorial.com/spring-boot-with-static-content-css-and-javascript-js
https://stackoverflow.com/questions/37581710/spring-boot-static-resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.