Skip to content

Commit

Permalink
prototype for issue2570 (apache#2640)
Browse files Browse the repository at this point in the history
* apache#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
  • Loading branch information
beiwei30 authored and CrazyHZM committed Dec 6, 2018
1 parent 0860868 commit d1e9db5
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.dubbo.config.spring.initializer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
* A Dubbo context listener is a delegation to org.springframework.web.context.ContextLoaderListener. This is necessary,
* because Dubbo is packaged into all-in-one jar, therefore it contains a web-fragment.xml from this sub module which's
* used for helping to assemble spring context listener automatically when it's not configured explicitly by user in
* web.xml. It works fine with spring, but it will lead to ClassNotFound exception and fail tomcat's bootup when user
* doesn't depend on spring framework.
*/
public class DubboContextListener implements ServletContextListener {
private static final Log logger = LogFactory.getLog(DubboContextListener.class);

private static final String SPRING_CONTEXT_LISTENER = "org.springframework.web.context.ContextLoaderListener";
private static final String SPRING_CONTEXT_ROOT = "org.springframework.web.context.WebApplicationContext.ROOT";

private ServletContextListener springContextListener;
private boolean executed = false;

public DubboContextListener() {
try {
Class c = Class.forName(SPRING_CONTEXT_LISTENER);
springContextListener = (ServletContextListener) c.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
logger.warn("Servlet container detects dubbo's web fragment configuration, and tries to load " +
"org.springframework.web.context.ContextLoaderListener but fails to find the class. " +
"If the application don't rely on Spring framework, pls. simply ignore");
}
}

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
if (springContextListener != null) {
// if spring context listener has already been registered, then do nothing
ServletContext context = servletContextEvent.getServletContext();
if (context.getAttribute(SPRING_CONTEXT_ROOT) == null) {
executed = true;
springContextListener.contextInitialized(servletContextEvent);
}
}
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if (springContextListener != null && executed) {
springContextListener.contextDestroyed(servletContextEvent);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
<listener-class>org.apache.dubbo.config.spring.initializer.DubboContextListener</listener-class>
</listener>

</web-fragment>
</web-fragment>
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ public void testSpringContextLoaderListenerInWebXml() throws Exception {
context.addLifecycleListener(new ContextConfig());
tomcat.getHost().addChild(context);
tomcat.start();
// there should be 1 application listener
Assert.assertEquals(1, context.getApplicationLifecycleListeners().length);
// there should be 2 application listeners, one is spring context listener,
// the other is its wrapper dubbo introduces.
Assert.assertEquals(2, context.getApplicationLifecycleListeners().length);
// the first one should be Spring's built in ContextLoaderListener.
Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof ContextLoaderListener);
tomcat.stop();
Expand All @@ -58,10 +59,10 @@ public void testNoListenerInWebXml() throws Exception {
context.addLifecycleListener(new ContextConfig());
tomcat.getHost().addChild(context);
tomcat.start();
// there should be 1 application listener
// there should be 1 application listener, which is spring context listener's wrapper introduced by dubbo
Assert.assertEquals(1, context.getApplicationLifecycleListeners().length);
// the first one should be Spring's built in ContextLoaderListener.
Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof ContextLoaderListener);
Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof DubboContextListener);
tomcat.stop();
tomcat.destroy();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ public class DataSourceStatusCheckerTest {

@Before
public void setUp() throws Exception {
SpringExtensionFactory.clearContexts();
initMocks(this);
this.dataSourceStatusChecker = new DataSourceStatusChecker();
new ServiceBean<Object>().setApplicationContext(applicationContext);
}

@After
public void tearDown() throws Exception {
SpringExtensionFactory.clearContexts();
Mockito.reset(applicationContext);
}

Expand Down

0 comments on commit d1e9db5

Please sign in to comment.