Skip to content

Commit 393ffce

Browse files
beiwei30jerrick-zhu
authored andcommitted
prototype for issue2570 (#2640)
* #2570: dubbo all in one fail to start from a tomcat server when spring framework is absent * add comments and fix unit test * add license header * update comments in unit tests
1 parent 1ef1220 commit 393ffce

File tree

4 files changed

+80
-7
lines changed

4 files changed

+80
-7
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.dubbo.config.spring.initializer;
19+
20+
import org.apache.commons.logging.Log;
21+
import org.apache.commons.logging.LogFactory;
22+
23+
import javax.servlet.ServletContext;
24+
import javax.servlet.ServletContextEvent;
25+
import javax.servlet.ServletContextListener;
26+
27+
/**
28+
* A Dubbo context listener is a delegation to org.springframework.web.context.ContextLoaderListener. This is necessary,
29+
* because Dubbo is packaged into all-in-one jar, therefore it contains a web-fragment.xml from this sub module which's
30+
* used for helping to assemble spring context listener automatically when it's not configured explicitly by user in
31+
* web.xml. It works fine with spring, but it will lead to ClassNotFound exception and fail tomcat's bootup when user
32+
* doesn't depend on spring framework.
33+
*/
34+
public class DubboContextListener implements ServletContextListener {
35+
private static final Log logger = LogFactory.getLog(DubboContextListener.class);
36+
37+
private static final String SPRING_CONTEXT_LISTENER = "org.springframework.web.context.ContextLoaderListener";
38+
private static final String SPRING_CONTEXT_ROOT = "org.springframework.web.context.WebApplicationContext.ROOT";
39+
40+
private ServletContextListener springContextListener;
41+
private boolean executed = false;
42+
43+
public DubboContextListener() {
44+
try {
45+
Class c = Class.forName(SPRING_CONTEXT_LISTENER);
46+
springContextListener = (ServletContextListener) c.newInstance();
47+
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
48+
logger.warn("Servlet container detects dubbo's web fragment configuration, and tries to load " +
49+
"org.springframework.web.context.ContextLoaderListener but fails to find the class. " +
50+
"If the application don't rely on Spring framework, pls. simply ignore");
51+
}
52+
}
53+
54+
@Override
55+
public void contextInitialized(ServletContextEvent servletContextEvent) {
56+
if (springContextListener != null) {
57+
// if spring context listener has already been registered, then do nothing
58+
ServletContext context = servletContextEvent.getServletContext();
59+
if (context.getAttribute(SPRING_CONTEXT_ROOT) == null) {
60+
executed = true;
61+
springContextListener.contextInitialized(servletContextEvent);
62+
}
63+
}
64+
}
65+
66+
@Override
67+
public void contextDestroyed(ServletContextEvent servletContextEvent) {
68+
if (springContextListener != null && executed) {
69+
springContextListener.contextDestroyed(servletContextEvent);
70+
}
71+
}
72+
}

dubbo-config/dubbo-config-spring/src/main/resources/META-INF/web-fragment.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</context-param>
1717

1818
<listener>
19-
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
19+
<listener-class>org.apache.dubbo.config.spring.initializer.DubboContextListener</listener-class>
2020
</listener>
2121

22-
</web-fragment>
22+
</web-fragment>

dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializerTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ public void testSpringContextLoaderListenerInWebXml() throws Exception {
3838
context.addLifecycleListener(new ContextConfig());
3939
tomcat.getHost().addChild(context);
4040
tomcat.start();
41-
// there should be 1 application listener
42-
Assert.assertEquals(1, context.getApplicationLifecycleListeners().length);
41+
// there should be 2 application listeners, one is spring context listener,
42+
// the other is its wrapper dubbo introduces.
43+
Assert.assertEquals(2, context.getApplicationLifecycleListeners().length);
4344
// the first one should be Spring's built in ContextLoaderListener.
4445
Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof ContextLoaderListener);
4546
tomcat.stop();
@@ -58,10 +59,10 @@ public void testNoListenerInWebXml() throws Exception {
5859
context.addLifecycleListener(new ContextConfig());
5960
tomcat.getHost().addChild(context);
6061
tomcat.start();
61-
// there should be 1 application listener
62+
// there should be 1 application listener, which is spring context listener's wrapper introduced by dubbo
6263
Assert.assertEquals(1, context.getApplicationLifecycleListeners().length);
6364
// the first one should be Spring's built in ContextLoaderListener.
64-
Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof ContextLoaderListener);
65+
Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof DubboContextListener);
6566
tomcat.stop();
6667
tomcat.destroy();
6768
}

dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/DataSourceStatusCheckerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ public class DataSourceStatusCheckerTest {
4949

5050
@Before
5151
public void setUp() throws Exception {
52+
SpringExtensionFactory.clearContexts();
5253
initMocks(this);
5354
this.dataSourceStatusChecker = new DataSourceStatusChecker();
5455
new ServiceBean<Object>().setApplicationContext(applicationContext);
5556
}
5657

5758
@After
5859
public void tearDown() throws Exception {
59-
SpringExtensionFactory.clearContexts();
6060
Mockito.reset(applicationContext);
6161
}
6262

0 commit comments

Comments
 (0)