blob: 7aa7dd282239a26f3cc6d60a1673c4a837e16ecd [file] [log] [blame]
/*
* 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.context;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_STOP_DUBBO_ERROR;
import static org.springframework.util.ObjectUtils.nullSafeEquals;
import java.util.concurrent.Future;
import org.apache.dubbo.common.deploy.DeployListenerAdapter;
import org.apache.dubbo.common.deploy.DeployState;
import org.apache.dubbo.common.deploy.ModuleDeployer;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.spring.context.event.DubboApplicationStateEvent;
import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModelConstants;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
/**
* An ApplicationListener to control Dubbo application.
*/
public class DubboDeployApplicationListener implements ApplicationListener<ApplicationContextEvent>, ApplicationContextAware, Ordered {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DubboDeployApplicationListener.class);
private ApplicationContext applicationContext;
private ApplicationModel applicationModel;
private ModuleModel moduleModel;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
this.applicationModel = DubboBeanUtils.getApplicationModel(applicationContext);
this.moduleModel = DubboBeanUtils.getModuleModel(applicationContext);
// listen deploy events and publish DubboApplicationStateEvent
applicationModel.getDeployer().addDeployListener(new DeployListenerAdapter<ApplicationModel>(){
@Override
public void onStarting(ApplicationModel scopeModel) {
publishEvent(DeployState.STARTING);
}
@Override
public void onStarted(ApplicationModel scopeModel) {
publishEvent(DeployState.STARTED);
}
@Override
public void onStopping(ApplicationModel scopeModel) {
publishEvent(DeployState.STOPPING);
}
@Override
public void onStopped(ApplicationModel scopeModel) {
publishEvent(DeployState.STOPPED);
}
@Override
public void onFailure(ApplicationModel scopeModel, Throwable cause) {
publishEvent(DeployState.FAILED, cause);
}
});
}
private void publishEvent(DeployState state) {
applicationContext.publishEvent(new DubboApplicationStateEvent(applicationModel, state));
}
private void publishEvent(DeployState state, Throwable cause) {
applicationContext.publishEvent(new DubboApplicationStateEvent(applicationModel, state, cause));
}
@Override
public void onApplicationEvent(ApplicationContextEvent event) {
if (nullSafeEquals(applicationContext, event.getSource())) {
if (event instanceof ContextRefreshedEvent) {
onContextRefreshedEvent((ContextRefreshedEvent) event);
} else if (event instanceof ContextClosedEvent) {
onContextClosedEvent((ContextClosedEvent) event);
}
}
}
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
ModuleDeployer deployer = moduleModel.getDeployer();
Assert.notNull(deployer, "Module deployer is null");
// start module
Future future = deployer.start();
// if the module does not start in background, await finish
if (!deployer.isBackground()) {
try {
future.get();
} catch (InterruptedException e) {
logger.warn("Interrupted while waiting for dubbo module start: " + e.getMessage());
} catch (Exception e) {
logger.warn("An error occurred while waiting for dubbo module start: " + e.getMessage(), e);
}
}
}
private void onContextClosedEvent(ContextClosedEvent event) {
try {
Object value = moduleModel.getAttribute(ModelConstants.KEEP_RUNNING_ON_SPRING_CLOSED);
boolean keepRunningOnClosed = Boolean.parseBoolean(String.valueOf(value));
if (!keepRunningOnClosed && !moduleModel.isDestroyed()) {
moduleModel.destroy();
}
} catch (Exception e) {
logger.error(CONFIG_STOP_DUBBO_ERROR, "", "", "Unexpected error occurred when stop dubbo module: " + e.getMessage(), e);
}
// remove context bind cache
DubboSpringInitializer.remove(event.getApplicationContext());
}
@Override
public int getOrder() {
return LOWEST_PRECEDENCE;
}
}