wujimin closed pull request #693: [SCB-548] support gracefully shutdown
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/693
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java 
b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java
index 4952f35f3..365868746 100644
--- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java
+++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java
@@ -17,59 +17,23 @@
 
 package org.apache.servicecomb.core;
 
-import java.util.Collection;
-
-import javax.inject.Inject;
-
-import org.apache.servicecomb.core.BootListener.BootEvent;
-import org.apache.servicecomb.core.BootListener.EventType;
 import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
-import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache;
-import org.apache.servicecomb.core.handler.HandlerConfigUtils;
 import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import org.apache.servicecomb.core.provider.producer.ProducerProviderManager;
 import org.apache.servicecomb.core.transport.TransportManager;
-import org.apache.servicecomb.foundation.common.event.EventManager;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.common.utils.FortifyUtils;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
-import 
org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.ApplicationEvent;
 import org.springframework.context.ApplicationListener;
-import org.springframework.context.event.ContextClosedEvent;
 import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.context.support.AbstractApplicationContext;
 import org.springframework.core.Ordered;
-import org.springframework.util.StringUtils;
-
-import com.google.common.eventbus.Subscribe;
 
 public class CseApplicationListener
     implements ApplicationListener<ApplicationEvent>, Ordered, 
ApplicationContextAware {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(CseApplicationListener.class);
-
-  private static boolean isInit = false;
-
-  @Inject
-  private ProducerProviderManager producerProviderManager;
-
-  @Inject
-  private ConsumerProviderManager consumerProviderManager;
-
-  @Inject
-  private TransportManager transportManager;
-
-  @Inject
-  private SchemaListenerManager schemaListenerManager;
-
-  private Collection<BootListener> bootListenerList;
-
   private Class<?> initEventClass = ContextRefreshedEvent.class;
 
   private ApplicationContext applicationContext;
@@ -91,92 +55,22 @@ public int getOrder() {
     return -1000;
   }
 
-  protected void triggerEvent(EventType eventType) {
-    BootEvent event = new BootEvent();
-    event.setEventType(eventType);
-
-    for (BootListener listener : bootListenerList) {
-      listener.onBootEvent(event);
-    }
-  }
-
   @Override
   public void onApplicationEvent(ApplicationEvent event) {
     if (initEventClass.isInstance(event)) {
-      //TODO to load when webapplication context is used for discovery client, 
need to check if can use the order and undo this change with proper fix.
-      if (!isInit) {
-        try {
-          bootListenerList = 
applicationContext.getBeansOfType(BootListener.class).values();
-
-          AbstractEndpointsCache.init(RegistryUtils.getInstanceCacheManager(), 
transportManager);
-
-          triggerEvent(EventType.BEFORE_HANDLER);
-          HandlerConfigUtils.init();
-          triggerEvent(EventType.AFTER_HANDLER);
-
-          triggerEvent(EventType.BEFORE_PRODUCER_PROVIDER);
-          producerProviderManager.init();
-          triggerEvent(EventType.AFTER_PRODUCER_PROVIDER);
-
-          triggerEvent(EventType.BEFORE_CONSUMER_PROVIDER);
-          consumerProviderManager.init();
-          triggerEvent(EventType.AFTER_CONSUMER_PROVIDER);
-
-          triggerEvent(EventType.BEFORE_TRANSPORT);
-          transportManager.init();
-          triggerEvent(EventType.AFTER_TRANSPORT);
-
-          schemaListenerManager.notifySchemaListener();
-
-          triggerEvent(EventType.BEFORE_REGISTRY);
-
-          triggerAfterRegistryEvent();
-
-          RegistryUtils.run();
-
-          // 当程序退出时,进行相关清理,注意:kill -9 {pid}下无效
-          // 1. 去注册实例信息
-          // TODO 服务优雅退出
-          if (applicationContext instanceof AbstractApplicationContext) {
-            ((AbstractApplicationContext) 
applicationContext).registerShutdownHook();
-          }
-          isInit = true;
-        } catch (Exception e) {
-          LOGGER.error("cse init failed, {}", FortifyUtils.getErrorInfo(e));
-        }
+      if (applicationContext instanceof AbstractApplicationContext) {
+        ((AbstractApplicationContext) 
applicationContext).registerShutdownHook();
       }
-    } else if (event instanceof ContextClosedEvent) {
-      LOGGER.warn("cse is closing now...");
-      triggerEvent(EventType.BEFORE_CLOSE);
-      RegistryUtils.destroy();
-      triggerEvent(EventType.AFTER_CLOSE);
-      isInit = false;
-    }
-  }
 
-  /**
-   * <p>As the process of instance registry is asynchronous, the {@code 
AFTER_REGISTRY}
-   * event should not be sent immediately after {@link RegistryUtils#run()} is 
invoked.
-   * When the instance registry succeeds, {@link 
MicroserviceInstanceRegisterTask} will be posted in {@link EventManager},
-   * register a subscriber to watch this event and send {@code 
AFTER_REGISTRY}.</p>
-   *
-   * <p>This method should be called before {@link RegistryUtils#run()} to 
avoid that the registry process is too quick
-   * that the event is not watched by this subscriber.</p>
-   *
-   * <p>Check if {@code InstanceId} is null to judge whether the instance 
registry has succeeded.</p>
-   */
-  private void triggerAfterRegistryEvent() {
-    EventManager.register(new Object() {
-      @Subscribe
-      public void afterRegistryInstance(MicroserviceInstanceRegisterTask 
microserviceInstanceRegisterTask) {
-        LOGGER.info("receive MicroserviceInstanceRegisterTask event, check 
instance Id...");
-        if 
(!StringUtils.isEmpty(RegistryUtils.getMicroserviceInstance().getInstanceId())) 
{
-          LOGGER.info("instance registry succeeds for the first time, will 
send AFTER_REGISTRY event.");
-          ReferenceConfigUtils.setReady(true);
-          triggerEvent(EventType.AFTER_REGISTRY);
-          EventManager.unregister(this);
-        }
+      if (SCBEngine.getInstance().getBootListenerList() == null) {
+        
SCBEngine.getInstance().setProducerProviderManager(applicationContext.getBean(ProducerProviderManager.class));
+        
SCBEngine.getInstance().setConsumerProviderManager(applicationContext.getBean(ConsumerProviderManager.class));
+        
SCBEngine.getInstance().setTransportManager(applicationContext.getBean(TransportManager.class));
+        
SCBEngine.getInstance().setSchemaListenerManager(applicationContext.getBean(SchemaListenerManager.class));
+        
SCBEngine.getInstance().setBootListenerList(applicationContext.getBeansOfType(BootListener.class).values());
       }
-    });
+
+      SCBEngine.getInstance().init();
+    }
   }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java 
b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
new file mode 100644
index 000000000..e0a17b8b8
--- /dev/null
+++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
@@ -0,0 +1,269 @@
+/*
+ * 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.servicecomb.core;
+
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.servicecomb.core.BootListener.BootEvent;
+import org.apache.servicecomb.core.BootListener.EventType;
+import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
+import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache;
+import org.apache.servicecomb.core.event.InvocationFinishEvent;
+import org.apache.servicecomb.core.event.InvocationStartEvent;
+import org.apache.servicecomb.core.handler.HandlerConfigUtils;
+import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
+import org.apache.servicecomb.core.provider.producer.ProducerProviderManager;
+import org.apache.servicecomb.core.transport.TransportManager;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.vertx.VertxUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import 
org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+import com.google.common.eventbus.AllowConcurrentEvents;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+// TODO: should not depend on spring, that will make integration more flexible
+public class SCBEngine {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(SCBEngine.class);
+
+  private ProducerProviderManager producerProviderManager;
+
+  private ConsumerProviderManager consumerProviderManager;
+
+  private TransportManager transportManager;
+
+  private SchemaListenerManager schemaListenerManager;
+
+  private Collection<BootListener> bootListenerList;
+
+  private final AtomicLong invocationStartedCounter = new AtomicLong();
+
+  private final AtomicLong invocationFinishedCounter = new AtomicLong();
+
+  private volatile SCBStatus status = SCBStatus.DOWN;
+
+  public void setStatus(SCBStatus status) {
+    this.status = status;
+  }
+
+  public SCBStatus getStatus() {
+    return status;
+  }
+
+  private EventBus eventBus = EventManager.getEventBus();
+
+  private static final SCBEngine INSTANCE = new SCBEngine();
+
+  public static SCBEngine getInstance() {
+    return INSTANCE;
+  }
+
+  public void setProducerProviderManager(
+      ProducerProviderManager producerProviderManager) {
+    this.producerProviderManager = producerProviderManager;
+  }
+
+  public void setConsumerProviderManager(
+      ConsumerProviderManager consumerProviderManager) {
+    this.consumerProviderManager = consumerProviderManager;
+  }
+
+  public TransportManager getTransportManager() {
+    return transportManager;
+  }
+
+  public void setTransportManager(TransportManager transportManager) {
+    this.transportManager = transportManager;
+  }
+
+  public void setSchemaListenerManager(
+      SchemaListenerManager schemaListenerManager) {
+    this.schemaListenerManager = schemaListenerManager;
+  }
+
+  public Collection<BootListener> getBootListenerList() {
+    return bootListenerList;
+  }
+
+  public void setBootListenerList(Collection<BootListener> bootListenerList) {
+    this.bootListenerList = bootListenerList;
+  }
+
+  protected void triggerEvent(EventType eventType) {
+    BootEvent event = new BootEvent();
+    event.setEventType(eventType);
+
+    for (BootListener listener : bootListenerList) {
+      listener.onBootEvent(event);
+    }
+  }
+
+  protected void safeTriggerEvent(EventType eventType) {
+    BootEvent event = new BootEvent();
+    event.setEventType(eventType);
+
+    for (BootListener listener : bootListenerList) {
+      try {
+        listener.onBootEvent(event);
+        LOGGER.info("BootListener {} succeed to process {}.", 
listener.getClass().getName(), eventType);
+      } catch (Throwable e) {
+        LOGGER.error("BootListener {} failed to process {}.", 
listener.getClass().getName(), eventType, e);
+      }
+    }
+  }
+
+  /**
+   * <p>As the process of instance registry is asynchronous, the {@code 
AFTER_REGISTRY}
+   * event should not be sent immediately after {@link RegistryUtils#run()} is 
invoked.
+   * When the instance registry succeeds, {@link 
MicroserviceInstanceRegisterTask} will be posted in {@link EventManager},
+   * register a subscriber to watch this event and send {@code 
AFTER_REGISTRY}.</p>
+   *
+   * <p>This method should be called before {@link RegistryUtils#run()} to 
avoid that the registry process is too quick
+   * that the event is not watched by this subscriber.</p>
+   *
+   * <p>Check if {@code InstanceId} is null to judge whether the instance 
registry has succeeded.</p>
+   */
+  private void triggerAfterRegistryEvent() {
+    EventManager.register(new Object() {
+      @Subscribe
+      public void afterRegistryInstance(MicroserviceInstanceRegisterTask 
microserviceInstanceRegisterTask) {
+        LOGGER.info("receive MicroserviceInstanceRegisterTask event, check 
instance Id...");
+        if 
(!StringUtils.isEmpty(RegistryUtils.getMicroserviceInstance().getInstanceId())) 
{
+          LOGGER.info("instance registry succeeds for the first time, will 
send AFTER_REGISTRY event.");
+          status = SCBStatus.UP;
+          triggerEvent(EventType.AFTER_REGISTRY);
+          EventManager.unregister(this);
+        }
+      }
+    });
+  }
+
+  @AllowConcurrentEvents
+  @Subscribe
+  public void onInvocationStart(InvocationStartEvent event) {
+    invocationStartedCounter.incrementAndGet();
+  }
+
+  @AllowConcurrentEvents
+  @Subscribe
+  public void onInvocationFinish(InvocationFinishEvent event) {
+    invocationFinishedCounter.incrementAndGet();
+  }
+
+  public synchronized void init() {
+    if (SCBStatus.DOWN.equals(status)) {
+      try {
+        doInit();
+        status = SCBStatus.UP;
+      } catch (Exception e) {
+        uninit();
+        status = SCBStatus.FAILED;
+        throw new IllegalStateException("ServiceComb init failed.", e);
+      }
+    }
+  }
+
+
+  private void doInit() throws Exception {
+    status = SCBStatus.STARTING;
+
+    eventBus.register(this);
+
+    AbstractEndpointsCache.init(RegistryUtils.getInstanceCacheManager(), 
transportManager);
+
+    triggerEvent(EventType.BEFORE_HANDLER);
+    HandlerConfigUtils.init();
+    triggerEvent(EventType.AFTER_HANDLER);
+
+    triggerEvent(EventType.BEFORE_PRODUCER_PROVIDER);
+    producerProviderManager.init();
+    triggerEvent(EventType.AFTER_PRODUCER_PROVIDER);
+
+    triggerEvent(EventType.BEFORE_CONSUMER_PROVIDER);
+    consumerProviderManager.init();
+    triggerEvent(EventType.AFTER_CONSUMER_PROVIDER);
+
+    triggerEvent(EventType.BEFORE_TRANSPORT);
+    transportManager.init();
+    triggerEvent(EventType.AFTER_TRANSPORT);
+
+    schemaListenerManager.notifySchemaListener();
+
+    triggerEvent(EventType.BEFORE_REGISTRY);
+
+    triggerAfterRegistryEvent();
+
+    RegistryUtils.run();
+
+    Runtime.getRuntime().addShutdownHook(new Thread(this::uninit));
+  }
+
+  /**
+   * not allow throw any exception
+   * even some step throw exception, must catch it and go on, otherwise 
shutdown process will be broken.
+   */
+  public synchronized void uninit() {
+    if (SCBStatus.UP.equals(status)) {
+      LOGGER.info("ServiceComb is closing now...");
+      doUninit();
+      status = SCBStatus.DOWN;
+      LOGGER.info("ServiceComb had closed");
+    }
+  }
+
+  private void doUninit() {
+    //Step 1: notify all component stop invoke via BEFORE_CLOSE Event
+    safeTriggerEvent(EventType.BEFORE_CLOSE);
+
+    //Step 2: forbid create new consumer invocation
+    status = SCBStatus.STOPPING;
+
+    //Step 3: Unregister microservice instance from Service Center and close 
vertx
+    // Forbidden other consumers find me
+    RegistryUtils.destroy();
+    VertxUtils.blockCloseVertxByName("registry");
+
+    //Step 4: wait all invocation finished
+    try {
+      validAllInvocationFinished();
+    } catch (InterruptedException e) {
+      LOGGER.error("wait all invocation finished interrupted", e);
+    }
+
+    //Step 5: Stop vertx to prevent blocking exit
+    VertxUtils.blockCloseVertxByName("config-center");
+    VertxUtils.blockCloseVertxByName("transport");
+
+    //Step 6: notify all component do clean works via AFTER_CLOSE Event
+    safeTriggerEvent(EventType.AFTER_CLOSE);
+  }
+
+  private void validAllInvocationFinished() throws InterruptedException {
+    while (true) {
+      if (invocationFinishedCounter.get() == invocationStartedCounter.get()) {
+        return;
+      }
+      TimeUnit.SECONDS.sleep(1);
+    }
+  }
+}
diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBStatus.java 
b/core/src/main/java/org/apache/servicecomb/core/SCBStatus.java
new file mode 100644
index 000000000..62551eb11
--- /dev/null
+++ b/core/src/main/java/org/apache/servicecomb/core/SCBStatus.java
@@ -0,0 +1,32 @@
+/*
+ * 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.servicecomb.core;
+
+//DOWN -> STARTING -> UP -> STOPPING -> DOWN
+public enum SCBStatus {
+  //Chassis is Down
+  DOWN,
+  //Chassis is Starting (progressing)
+  STARTING,
+  //Chassis is Running
+  UP,
+  //Chassis is Stopping (progressing)
+  STOPPING,
+  //Chassis Init Failed
+  FAILED
+}
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java
 
b/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java
index 3b49bc19d..20c72b489 100644
--- 
a/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java
+++ 
b/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java
@@ -86,8 +86,6 @@ public void init(Config config) {
     List<Class<Handler>> chainClasses = convertToChainClass(chainDef);
 
     List<Handler> handlerList = new ArrayList<>();
-    handlerList.add(ShutdownHookHandler.INSTANCE);
-
     for (Class<Handler> cls : chainClasses) {
       try {
         handlerList.add(cls.newInstance());
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java
 
b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java
deleted file mode 100644
index 8d1318aa3..000000000
--- 
a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.servicecomb.core.handler;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.servicecomb.core.Handler;
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.swagger.invocation.AsyncResponse;
-import org.apache.servicecomb.swagger.invocation.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 实现调用链的优雅停止: 当调用链没有返回的时候,等待返回或者超时
- */
-public final class ShutdownHookHandler implements Handler, Runnable {
-  private static final Logger LOG = 
LoggerFactory.getLogger(ShutdownHookHandler.class);
-
-  public static final ShutdownHookHandler INSTANCE = new ShutdownHookHandler();
-
-  private final AtomicLong requestCounter = new AtomicLong(0);
-
-  private final AtomicLong responseCounter = new AtomicLong(0);
-
-  private final int timeout = 600;
-
-  private final int period = 10;
-
-  private volatile boolean shuttingDown = false;
-
-  private ShutdownHookHandler() {
-    Runtime.getRuntime().addShutdownHook(new Thread(this));
-  }
-
-  public long getActiveCount() {
-    return requestCounter.get() - responseCounter.get();
-  }
-
-  @Override
-  public void handle(Invocation invocation, AsyncResponse asyncResp) throws 
Exception {
-    if (shuttingDown) {
-      asyncResp.handle(Response.createFail(invocation.getInvocationType(),
-          "shutting down in progress"));
-      return;
-    }
-
-    // TODO:统计功能应该独立出来,在链中统计,会有各种bug
-    //      下面的两次catch,可能会导致一次请求,对应2次应答
-    requestCounter.incrementAndGet();
-    try {
-      invocation.next(resp -> {
-        try {
-          asyncResp.handle(resp);
-        } finally {
-          responseCounter.incrementAndGet();
-        }
-      });
-    } catch (Throwable e) {
-      responseCounter.incrementAndGet();
-      throw e;
-    }
-  }
-
-  @Override
-  public void run() {
-    shuttingDown = true;
-    LOG.warn("handler chain is shutting down");
-    int time = 0;
-    while (getActiveCount() != 0 && time <= timeout) {
-      try {
-        TimeUnit.SECONDS.sleep(period);
-      } catch (InterruptedException e) {
-        LOG.warn(e.getMessage());
-      }
-      time = time + period;
-      LOG.warn("waiting invocation to finish in seconds " + time);
-    }
-    LOG.warn("handler chain is shut down");
-  }
-}
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
 
b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
index 7dc01f3a1..d617bd8c0 100644
--- 
a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
+++ 
b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
@@ -17,7 +17,10 @@
 
 package org.apache.servicecomb.core.provider.consumer;
 
+import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
 import org.apache.servicecomb.core.definition.SchemaMeta;
 import org.apache.servicecomb.core.invocation.InvocationFactory;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
@@ -32,31 +35,31 @@
   private static final Logger LOGGER = 
LoggerFactory.getLogger(InvokerUtils.class);
 
   public static Object syncInvoke(String microserviceName, String schemaId, 
String operationName, Object[] args) {
-    ReferenceConfig referenceConfig = 
ReferenceConfigUtils.getForInvoke(microserviceName);
-    SchemaMeta schemaMeta = 
referenceConfig.getMicroserviceMeta().ensureFindSchemaMeta(schemaId);
-    Invocation invocation = InvocationFactory.forConsumer(referenceConfig, 
schemaMeta, operationName, args);
-    return syncInvoke(invocation);
+    checkEngineStatus();
+    ReferenceConfig referenceConfig = 
CseContext.getInstance().getConsumerProviderManager()
+        .getReferenceConfig(microserviceName);
+    return syncInvoke(generateInvocation(schemaId, operationName, args, 
referenceConfig));
   }
 
   public static Object syncInvoke(String microserviceName, String 
microserviceVersion, String transport,
       String schemaId, String operationName, Object[] args) {
-    ReferenceConfig referenceConfig =
-        ReferenceConfigUtils.getForInvoke(microserviceName, 
microserviceVersion, transport);
-    SchemaMeta schemaMeta = 
referenceConfig.getMicroserviceMeta().ensureFindSchemaMeta(schemaId);
-    Invocation invocation = InvocationFactory.forConsumer(referenceConfig, 
schemaMeta, operationName, args);
-    return syncInvoke(invocation);
+    checkEngineStatus();
+    ReferenceConfig referenceConfig = 
CseContext.getInstance().getConsumerProviderManager()
+        .createReferenceConfig(microserviceName, microserviceVersion, 
transport);
+    return syncInvoke(generateInvocation(schemaId, operationName, args, 
referenceConfig));
   }
 
   public static Object syncInvoke(Invocation invocation) throws 
InvocationException {
+    checkEngineStatus();
     Response response = innerSyncInvoke(invocation);
     if (response.isSuccessed()) {
       return response.getResult();
     }
-
     throw ExceptionFactory.convertConsumerException(response.getResult());
   }
 
   public static Response innerSyncInvoke(Invocation invocation) {
+    checkEngineStatus();
     try {
       invocation.onStart();
       SyncResponseExecutor respExecutor = new SyncResponseExecutor();
@@ -79,6 +82,7 @@ public static Response innerSyncInvoke(Invocation invocation) 
{
   }
 
   public static void reactiveInvoke(Invocation invocation, AsyncResponse 
asyncResp) {
+    checkEngineStatus();
     try {
       invocation.onStart();
       invocation.setSync(false);
@@ -104,8 +108,23 @@ public static void reactiveInvoke(Invocation invocation, 
AsyncResponse asyncResp
     }
   }
 
+  private static Invocation generateInvocation(String schemaId, String 
operationName, Object[] args,
+      ReferenceConfig referenceConfig) {
+    SchemaMeta schemaMeta = 
referenceConfig.getMicroserviceMeta().ensureFindSchemaMeta(schemaId);
+    return InvocationFactory.forConsumer(referenceConfig, schemaMeta, 
operationName, args);
+  }
+
+  private static void checkEngineStatus() {
+    if (!SCBStatus.UP.equals(SCBEngine.getInstance().getStatus())) {
+      throw new IllegalStateException(
+          "System is starting and not ready for remote calls or shutting down 
in progress, STATUS = " + String
+              .valueOf(SCBEngine.getInstance().getStatus()));
+    }
+  }
+
   @Deprecated
   public static Object invoke(Invocation invocation) {
+    checkEngineStatus();
     return syncInvoke(invocation);
   }
 }
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java
 
b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java
deleted file mode 100644
index fe8d254b4..000000000
--- 
a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.servicecomb.core.provider.consumer;
-
-import org.apache.servicecomb.core.BootListener;
-import org.apache.servicecomb.core.CseContext;
-import org.springframework.stereotype.Component;
-
-@Component
-public class ReferenceConfigUtils {
-  private static boolean ready;
-
-  public static void setReady(boolean ready) {
-    ReferenceConfigUtils.ready = ready;
-  }
-
-  private static void assertIsReady() {
-    if (!ready) {
-      throw new IllegalStateException("System is not ready for remote calls. "
-          + "When beans are making remote calls in initialization, it's better 
to "
-          + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.");
-    }
-  }
-
-  public static ReferenceConfig getForInvoke(String microserviceName) {
-    assertIsReady();
-
-    return 
CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName);
-  }
-
-  public static ReferenceConfig getForInvoke(String microserviceName, String 
microserviceVersion,
-      String transport) {
-    assertIsReady();
-
-    return 
CseContext.getInstance().getConsumerProviderManager().createReferenceConfig(microserviceName,
-        microserviceVersion,
-        transport);
-  }
-}
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java
 
b/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java
deleted file mode 100644
index e5eaec84a..000000000
--- 
a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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.servicecomb.core;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.ws.Holder;
-
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.servicecomb.core.BootListener.BootEvent;
-import org.apache.servicecomb.core.BootListener.EventType;
-import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
-import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache;
-import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
-import org.apache.servicecomb.core.provider.producer.ProducerProviderManager;
-import org.apache.servicecomb.core.transport.TransportManager;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
-import org.apache.servicecomb.serviceregistry.RegistryUtils;
-import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
-import 
org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask;
-import org.hamcrest.Matchers;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.event.ContextClosedEvent;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.context.support.AbstractApplicationContext;
-
-import mockit.Deencapsulation;
-import mockit.Expectations;
-import mockit.Injectable;
-import mockit.Mock;
-import mockit.MockUp;
-import mockit.Mocked;
-
-public class TestCseApplicationListener {
-  static ApplicationContext orgContext;
-
-  @BeforeClass
-  public static void classSetup() {
-    orgContext = BeanUtils.getContext();
-  }
-
-  @AfterClass
-  public static void teardown() {
-    AbstractEndpointsCache.init(null, null);
-    BeanUtils.setContext(orgContext);
-  }
-
-  @After
-  public void cleanup() {
-    Deencapsulation.setField(ReferenceConfigUtils.class, "ready", false);
-  }
-
-  @Test
-  public void testCseApplicationListenerNormal(@Injectable 
ContextRefreshedEvent event,
-      @Injectable AbstractApplicationContext context,
-      @Injectable ProducerProviderManager producerProviderManager,
-      @Injectable ConsumerProviderManager consumerProviderManager,
-      @Injectable TransportManager transportManager,
-      @Mocked RegistryUtils ru) {
-    Map<String, BootListener> listeners = new HashMap<>();
-    BootListener listener = Mockito.mock(BootListener.class);
-    listeners.put("test", listener);
-
-    SchemaListenerManager schemaListenerManager = 
Mockito.mock(SchemaListenerManager.class);
-    MicroserviceInstance microserviceInstance = 
Mockito.mock(MicroserviceInstance.class);
-
-    new Expectations() {
-      {
-        context.getBeansOfType(BootListener.class);
-        result = listeners;
-      }
-    };
-    new Expectations(RegistryUtils.class) {
-      {
-        RegistryUtils.init();
-        RegistryUtils.getInstanceCacheManager();
-        RegistryUtils.run();
-        RegistryUtils.getMicroserviceInstance();
-        result = microserviceInstance;
-      }
-    };
-    
Mockito.when(microserviceInstance.getInstanceId()).thenReturn("testInstanceId");
-
-    CseApplicationListener cal = new CseApplicationListener();
-    Deencapsulation.setField(cal, "schemaListenerManager", 
schemaListenerManager);
-    cal.setInitEventClass(ContextRefreshedEvent.class);
-    cal.setApplicationContext(context);
-    ReflectUtils.setField(cal, "producerProviderManager", 
producerProviderManager);
-    ReflectUtils.setField(cal, "consumerProviderManager", 
consumerProviderManager);
-    ReflectUtils.setField(cal, "transportManager", transportManager);
-
-    cal.onApplicationEvent(event);
-
-    EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class));
-    verify(schemaListenerManager).notifySchemaListener();
-    verify(listener, times(10)).onBootEvent(Mockito.any(BootEvent.class));
-  }
-
-  @Test
-  public void testCseApplicationListenerThrowException(@Injectable 
ContextRefreshedEvent event,
-      @Injectable AbstractApplicationContext context,
-      @Injectable BootListener listener,
-      @Injectable ProducerProviderManager producerProviderManager,
-      @Mocked RegistryUtils ru) {
-    Map<String, BootListener> listeners = new HashMap<>();
-    listeners.put("test", listener);
-
-    CseApplicationListener cal = new CseApplicationListener();
-    cal.setApplicationContext(context);
-    ReflectUtils.setField(cal, "producerProviderManager", 
producerProviderManager);
-    cal.onApplicationEvent(event);
-  }
-
-  @Test
-  public void testCseApplicationListenerParentNotnull(@Injectable 
ContextRefreshedEvent event,
-      @Injectable AbstractApplicationContext context,
-      @Injectable AbstractApplicationContext pContext,
-      @Mocked RegistryUtils ru) {
-
-    CseApplicationListener cal = new CseApplicationListener();
-    cal.setApplicationContext(context);
-    cal.onApplicationEvent(event);
-  }
-
-  @Test
-  public void testCseApplicationListenerShutdown(@Mocked ApplicationContext 
context) throws IllegalAccessException {
-    Holder<Boolean> destroyHolder = new Holder<>();
-    new MockUp<RegistryUtils>() {
-      @Mock
-      void destroy() {
-        destroyHolder.value = true;
-      }
-    };
-    CseApplicationListener cal = new CseApplicationListener();
-    ContextClosedEvent event = new ContextClosedEvent(context);
-
-    List<EventType> eventTypes = new ArrayList<>();
-    BootListener bootListener = e -> {
-      eventTypes.add(e.getEventType());
-    };
-    FieldUtils.writeField(cal, "bootListenerList", 
Arrays.asList(bootListener), true);
-    cal.onApplicationEvent(event);
-
-    Assert.assertTrue(destroyHolder.value);
-    Assert.assertThat(eventTypes, Matchers.contains(EventType.BEFORE_CLOSE, 
EventType.AFTER_CLOSE));
-  }
-
-  @Test
-  public void testTriggerAfterRegistryEvent() {
-    CseApplicationListener cal = new CseApplicationListener();
-
-    Collection<BootListener> listeners = new ArrayList<>(1);
-    BootListener listener = Mockito.mock(BootListener.class);
-    listeners.add(listener);
-    Deencapsulation.setField(cal, "bootListenerList", listeners);
-
-    MicroserviceInstance microserviceInstance = 
Mockito.mock(MicroserviceInstance.class);
-    new Expectations(RegistryUtils.class) {
-      {
-        RegistryUtils.getMicroserviceInstance();
-        result = microserviceInstance;
-      }
-    };
-    
Mockito.when(microserviceInstance.getInstanceId()).thenReturn("testInstanceId");
-
-    Deencapsulation.invoke(cal, "triggerAfterRegistryEvent");
-
-    EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class));
-
-    Deencapsulation.invoke(ReferenceConfigUtils.class, "assertIsReady");
-
-    // AFTER_REGISTRY event should only be sent at the first time of registry 
success.
-    EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class));
-    verify(listener, times(1)).onBootEvent(Mockito.any(BootEvent.class));
-  }
-
-  @Test
-  public void testTriggerAfterRegistryEventOnInstanceIdIsNull() {
-    CseApplicationListener cal = new CseApplicationListener();
-
-    Collection<BootListener> listeners = new ArrayList<>(1);
-    BootListener listener = Mockito.mock(BootListener.class);
-    listeners.add(listener);
-    Deencapsulation.setField(cal, "bootListenerList", listeners);
-
-    MicroserviceInstance microserviceInstance = 
Mockito.mock(MicroserviceInstance.class);
-    new Expectations(RegistryUtils.class) {
-      {
-        RegistryUtils.getMicroserviceInstance();
-        result = microserviceInstance;
-      }
-    };
-    
Mockito.when(microserviceInstance.getInstanceId()).thenReturn(null).thenReturn("testInstanceId");
-
-    Deencapsulation.invoke(cal, "triggerAfterRegistryEvent");
-
-    EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class));
-
-    try {
-      Deencapsulation.invoke(ReferenceConfigUtils.class, "assertIsReady");
-      fail("an exception is expected.");
-    } catch (Exception e) {
-      Assert.assertEquals(IllegalStateException.class, e.getClass());
-    }
-    verify(listener, times(0)).onBootEvent(Mockito.any(BootEvent.class));
-
-    // AFTER_REGISTRY event should only be sent at the first time of registry 
success.
-    EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class));
-    Deencapsulation.invoke(ReferenceConfigUtils.class, "assertIsReady");
-    verify(listener, times(1)).onBootEvent(Mockito.any(BootEvent.class));
-  }
-}
diff --git a/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java 
b/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java
new file mode 100644
index 000000000..da0a9dbf4
--- /dev/null
+++ b/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java
@@ -0,0 +1,68 @@
+/*
+ * 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.servicecomb.core;
+
+import java.util.ArrayList;
+
+import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
+import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
+import org.apache.servicecomb.core.provider.producer.ProducerProviderManager;
+import org.apache.servicecomb.core.transport.TransportManager;
+import org.apache.servicecomb.foundation.vertx.VertxUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import mockit.Expectations;
+import mockit.Injectable;
+
+public class TestSCBEngine {
+  @Test
+  public void test(@Injectable ProducerProviderManager producerProviderManager,
+      @Injectable ConsumerProviderManager consumerProviderManager,
+      @Injectable TransportManager transportManager) {
+
+    new Expectations(RegistryUtils.class) {
+      {
+        RegistryUtils.getInstanceCacheManager();
+        RegistryUtils.run();
+        RegistryUtils.destroy();
+      }
+    };
+
+    SchemaListenerManager schemaListenerManager = 
Mockito.mock(SchemaListenerManager.class);
+
+    VertxUtils.getOrCreateVertxByName("transport", null);
+
+    SCBEngine engine = new SCBEngine();
+    engine.setBootListenerList(new ArrayList<>());
+    engine.setConsumerProviderManager(consumerProviderManager);
+    engine.setProducerProviderManager(producerProviderManager);
+    engine.setTransportManager(transportManager);
+    engine.setSchemaListenerManager(schemaListenerManager);
+
+    engine.init();
+
+    Assert.assertEquals(SCBStatus.UP, engine.getStatus());
+
+    engine.uninit();
+
+    Assert.assertEquals(SCBStatus.DOWN, engine.getStatus());
+  }
+}
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java
 
b/core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java
deleted file mode 100644
index 00b767a8d..000000000
--- 
a/core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.servicecomb.core.handler;
-
-import java.lang.reflect.Field;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.xml.ws.Holder;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.swagger.invocation.AsyncResponse;
-import org.apache.servicecomb.swagger.invocation.InvocationType;
-import org.apache.servicecomb.swagger.invocation.Response;
-import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
-import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
-import org.junit.Assert;
-import org.junit.Test;
-import org.springframework.util.ReflectionUtils;
-
-import mockit.Deencapsulation;
-import mockit.Mock;
-import mockit.MockUp;
-import mockit.Mocked;
-
-public class TestShutdownHookHandler {
-  static Field requestCountField = 
ReflectionUtils.findField(ShutdownHookHandler.class, "requestCounter");
-
-  static {
-    requestCountField.setAccessible(true);
-  }
-
-  static AtomicLong requestCounter =
-      (AtomicLong) ReflectionUtils.getField(requestCountField, 
ShutdownHookHandler.INSTANCE);
-
-  @Test
-  public void testShutdownHookHandlerCount(@Mocked Response response) throws 
Exception {
-    Deencapsulation.setField(ShutdownHookHandler.INSTANCE, "shuttingDown", 
false);
-
-    ShutdownHookHandler handler = ShutdownHookHandler.INSTANCE;
-    Assert.assertEquals(0, handler.getActiveCount());
-
-    // no reply
-    Invocation invocation = new MockUp<Invocation>() {
-      @Mock
-      public void next(AsyncResponse asyncResp) throws Exception {
-      }
-    }.getMockInstance();
-    handler.handle(invocation, asyncResp -> {
-    });
-    Assert.assertEquals(1, requestCounter.get());
-    Assert.assertEquals(1, handler.getActiveCount());
-
-    // normal
-    invocation = new MockUp<Invocation>() {
-      @Mock
-      public void next(AsyncResponse asyncResp) throws Exception {
-        asyncResp.handle(response);
-      }
-    }.getMockInstance();
-    handler.handle(invocation, asyncResp -> {
-    });
-    Assert.assertEquals(2, requestCounter.get());
-    Assert.assertEquals(1, handler.getActiveCount());
-
-    // next exception
-    invocation = new MockUp<Invocation>() {
-      @Mock
-      public void next(AsyncResponse asyncResp) throws Exception {
-        throw new Error();
-      }
-    }.getMockInstance();
-    try {
-      handler.handle(invocation, asyncResp -> {
-      });
-      Assert.assertFalse(true);
-    } catch (Throwable e) {
-      Assert.assertEquals(3, requestCounter.get());
-      Assert.assertEquals(1, handler.getActiveCount());
-    }
-
-    AtomicLong responseCounter = 
Deencapsulation.getField(ShutdownHookHandler.INSTANCE, "responseCounter");
-    responseCounter.incrementAndGet();
-    Assert.assertEquals(0, handler.getActiveCount());
-
-    // reply exception
-    // TODO: should be fixed
-    //        try {
-    //            handler.handle(invocation, asyncResp -> {
-    //                throw new Error();
-    //            });
-    //
-    //            Assert.assertFalse(true);
-    //        } catch (Throwable e) {
-    //            Assert.assertEquals(3, requestCounter.get());
-    //            Assert.assertEquals(1, handler.getActiveCount());
-    //        }
-  }
-
-  @Test
-  public void testShutdownHookHandlerReject() throws Exception {
-    Deencapsulation.setField(ShutdownHookHandler.INSTANCE, "shuttingDown", 
true);
-    Holder<InvocationType> typeHolder = new Holder<>(InvocationType.PRODUCER);
-    Invocation invocation = new MockUp<Invocation>() {
-      @Mock
-      public InvocationType getInvocationType() {
-        return typeHolder.value;
-      }
-    }.getMockInstance();
-
-    ShutdownHookHandler handler = ShutdownHookHandler.INSTANCE;
-    handler.handle(invocation, asyncResp -> {
-      InvocationException e = asyncResp.getResult();
-      Assert.assertEquals(((CommonExceptionData) 
e.getErrorData()).getMessage(),
-          "shutting down in progress");
-      Assert.assertEquals(e.getStatusCode(), 590);
-    });
-
-    typeHolder.value = InvocationType.CONSUMER;
-    handler.handle(invocation, asyncResp -> {
-      InvocationException e = asyncResp.getResult();
-      Assert.assertEquals(((CommonExceptionData) 
e.getErrorData()).getMessage(),
-          "shutting down in progress");
-      Assert.assertEquals(e.getStatusCode(), 490);
-    });
-  }
-}
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java
 
b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java
index d975e65e9..8bf6cae77 100644
--- 
a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java
+++ 
b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java
@@ -19,9 +19,10 @@
 
 import javax.xml.ws.Holder;
 
-import org.apache.servicecomb.core.BootListener;
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.definition.SchemaMeta;
 import org.apache.servicecomb.core.invocation.InvocationFactory;
@@ -43,13 +44,13 @@
 public class TestInvokerUtils {
 
   @Test
-  public void testSyncInvokeInvocationWithException() throws 
InterruptedException {
+  public void testSyncInvokeInvocationWithException() {
     Invocation invocation = Mockito.mock(Invocation.class);
 
     Response response = Mockito.mock(Response.class);
     new MockUp<SyncResponseExecutor>() {
       @Mock
-      public Response waitResponse() throws InterruptedException {
+      public Response waitResponse() {
         return Mockito.mock(Response.class);
       }
     };
@@ -68,6 +69,9 @@ public Response waitResponse() throws InterruptedException {
   @Test
   public void testReactiveInvoke(@Mocked Invocation invocation, @Mocked 
InvocationContext parentContext,
       @Mocked Response response) {
+
+    SCBEngine.getInstance().setStatus(SCBStatus.UP);
+
     new MockUp<Invocation>(invocation) {
       @Mock
       InvocationContext getParentContext() {
@@ -80,11 +84,8 @@ void next(AsyncResponse asyncResp) {
       }
     };
 
-
     Holder<InvocationContext> holder = new Holder<>();
-    InvokerUtils.reactiveInvoke(invocation, ar -> {
-      holder.value = ContextUtils.getInvocationContext();
-    });
+    InvokerUtils.reactiveInvoke(invocation, ar -> holder.value = 
ContextUtils.getInvocationContext());
 
     Assert.assertNull(ContextUtils.getInvocationContext());
     Assert.assertSame(parentContext, holder.value);
@@ -93,6 +94,9 @@ void next(AsyncResponse asyncResp) {
   @SuppressWarnings("deprecation")
   @Test
   public void invoke() {
+
+    SCBEngine.getInstance().setStatus(SCBStatus.UP);
+
     new MockUp<InvokerUtils>() {
       @Mock
       Object syncInvoke(Invocation invocation) {
@@ -104,34 +108,72 @@ Object syncInvoke(Invocation invocation) {
   }
 
   @Test
-  public void tetSyncInvokeNotReady() {
-    ReferenceConfigUtils.setReady(false);
+  public void testSyncInvokeNotReady(@Mocked Invocation invocation) {
+
+    SCBEngine.getInstance().setStatus(SCBStatus.DOWN);
+
+    try {
+      InvokerUtils.syncInvoke(invocation);
+      Assert.fail("must throw exception");
+    } catch (IllegalStateException e) {
+      Assert
+          .assertEquals("System is starting and not ready for remote calls or 
shutting down in progress, STATUS = DOWN",
+              e.getMessage());
+    }
 
     try {
       InvokerUtils.syncInvoke("ms", "schemaId", "opName", null);
       Assert.fail("must throw exception");
     } catch (IllegalStateException e) {
-      Assert.assertEquals("System is not ready for remote calls. "
-          + "When beans are making remote calls in initialization, it's better 
to "
-          + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.",
-          e.getMessage());
+      Assert
+          .assertEquals("System is starting and not ready for remote calls or 
shutting down in progress, STATUS = DOWN",
+              e.getMessage());
     }
 
     try {
       InvokerUtils.syncInvoke("ms", "latest", "rest", "schemaId", "opName", 
null);
       Assert.fail("must throw exception");
     } catch (IllegalStateException e) {
-      Assert.assertEquals("System is not ready for remote calls. "
-          + "When beans are making remote calls in initialization, it's better 
to "
-          + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.",
-          e.getMessage());
+      Assert
+          .assertEquals("System is starting and not ready for remote calls or 
shutting down in progress, STATUS = DOWN",
+              e.getMessage());
+    }
+  }
+
+  @Test
+  public void testReactiveInvokeNotReady(@Mocked Invocation invocation, 
@Mocked InvocationContext parentContext,
+      @Mocked Response response) {
+
+    SCBEngine.getInstance().setStatus(SCBStatus.DOWN);
+
+    new MockUp<Invocation>(invocation) {
+      @Mock
+      InvocationContext getParentContext() {
+        return parentContext;
+      }
+
+      @Mock
+      void next(AsyncResponse asyncResp) {
+        asyncResp.handle(response);
+      }
+    };
+
+    Holder<InvocationContext> holder = new Holder<>();
+    try {
+      InvokerUtils.reactiveInvoke(invocation, ar -> holder.value = 
ContextUtils.getInvocationContext());
+    } catch (IllegalStateException e) {
+      Assert
+          .assertEquals("System is starting and not ready for remote calls or 
shutting down in progress, STATUS = DOWN",
+              e.getMessage());
     }
   }
 
   @Test
-  public void tetSyncInvokeReady(@Injectable ConsumerProviderManager 
consumerProviderManager,
+  public void testSyncInvokeReady(@Injectable ConsumerProviderManager 
consumerProviderManager,
       @Injectable Invocation invocation) {
-    ReferenceConfigUtils.setReady(true);
+
+    SCBEngine.getInstance().setStatus(SCBStatus.UP);
+
     
CseContext.getInstance().setConsumerProviderManager(consumerProviderManager);
 
     new Expectations(InvocationFactory.class) {
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java
 
b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java
deleted file mode 100644
index fbe664c43..000000000
--- 
a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.servicecomb.core.provider.consumer;
-
-import org.apache.servicecomb.core.BootListener;
-import org.apache.servicecomb.core.CseContext;
-import org.junit.Assert;
-import org.junit.Test;
-
-import mockit.Injectable;
-
-public class TestReferenceConfigUtils {
-  @Test
-  public void testNotReady() {
-    String exceptionMessage = "System is not ready for remote calls. "
-        + "When beans are making remote calls in initialization, it's better 
to "
-        + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.";
-
-    ReferenceConfigUtils.setReady(false);
-    try {
-      ReferenceConfigUtils.getForInvoke("abc");
-      Assert.fail("must throw exception");
-    } catch (IllegalStateException e) {
-      Assert.assertEquals(exceptionMessage, e.getMessage());
-    }
-
-    try {
-      ReferenceConfigUtils.getForInvoke("abc", "v1", "");
-      Assert.fail("must throw exception");
-    } catch (IllegalStateException e) {
-      Assert.assertEquals(exceptionMessage, e.getMessage());
-    }
-  }
-
-  @Test
-  public void testReady(@Injectable ConsumerProviderManager 
consumerProviderManager) {
-    ReferenceConfigUtils.setReady(true);
-    
CseContext.getInstance().setConsumerProviderManager(consumerProviderManager);
-
-    Assert.assertNotNull(ReferenceConfigUtils.getForInvoke("abc"));
-    Assert.assertNotNull(ReferenceConfigUtils.getForInvoke("abc", "v1", ""));
-  }
-}
diff --git a/coverage-reports/pom.xml b/coverage-reports/pom.xml
index 337ae2699..fcdb3e0ac 100644
--- a/coverage-reports/pom.xml
+++ b/coverage-reports/pom.xml
@@ -50,6 +50,10 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>foundation-metrics</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>metrics-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>java-chassis-core</artifactId>
@@ -174,6 +178,14 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>config-apollo</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>config-cc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.servicecomb.demo</groupId>
       <artifactId>pojo-client</artifactId>
@@ -259,6 +271,26 @@
       <artifactId>springmvc-tests</artifactId>
       <version>1.0.0-m2-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>springmvc-tests-general</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>springmvc-tests-general-with-springboot</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>springmvc-tests-simplified-mapping</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      
<artifactId>springmvc-tests-simplified-mapping-with-springboot</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>org.apache.servicecomb.tests</groupId>
       <artifactId>tracing-tests</artifactId>
diff --git a/demo/perf/src/main/resources/microservice.yaml 
b/demo/perf/src/main/resources/microservice.yaml
index e597667c1..254a85be9 100644
--- a/demo/perf/src/main/resources/microservice.yaml
+++ b/demo/perf/src/main/resources/microservice.yaml
@@ -39,10 +39,10 @@ servicecomb:
       thread-count: 8
   references:
     transport: rest
-servicecomb:
   metrics:
     window_time: 1000
-    
+servicecomb.metrics.publisher.defaultLog.enabled: true
+
 sync-count: 10
 async-count: 20
 sync: false
diff --git 
a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java
 
b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java
index 4aba612f2..a3aabd694 100644
--- 
a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java
+++ 
b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java
@@ -21,6 +21,7 @@
 import java.io.InputStream;
 import java.lang.management.ManagementFactory;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 
 import javax.xml.ws.Holder;
@@ -35,7 +36,6 @@
 
 import io.netty.buffer.ByteBuf;
 import io.vertx.core.AbstractVerticle;
-import io.vertx.core.Context;
 import io.vertx.core.DeploymentOptions;
 import io.vertx.core.Verticle;
 import io.vertx.core.Vertx;
@@ -111,9 +111,7 @@ private VertxUtils() {
   }
 
   public static Vertx getOrCreateVertxByName(String name, VertxOptions 
vertxOptions) {
-    return vertxMap.computeIfAbsent(name, vertxName -> {
-      return (VertxImplEx) init(vertxName, vertxOptions);
-    });
+    return vertxMap.computeIfAbsent(name, vertxName -> (VertxImplEx) 
init(vertxName, vertxOptions));
   }
 
   public static Vertx init(VertxOptions vertxOptions) {
@@ -125,7 +123,7 @@ public static Vertx init(String name, VertxOptions 
vertxOptions) {
       vertxOptions = new VertxOptions();
     }
 
-    boolean isDebug = 
ManagementFactory.getRuntimeMXBean().getInputArguments().toString().indexOf("jdwp")
 >= 0;
+    boolean isDebug = 
ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("jdwp");
     if (isDebug) {
       
vertxOptions.setBlockedThreadCheckInterval(BLOCKED_THREAD_CHECK_INTERVAL);
       LOGGER.info("in debug mode, disable blocked thread check.");
@@ -144,36 +142,6 @@ protected static void configureVertxFileCaching() {
     }
   }
 
-  public static Vertx currentVertx() {
-    Context context = Vertx.currentContext();
-    if (context == null) {
-      throw new RuntimeException("get currentVertx error, currentContext is 
null.");
-    }
-
-    return context.owner();
-  }
-
-  public static Vertx getVertxByName(String name) {
-    return vertxMap.get(name);
-  }
-
-  public static <T> void runInContext(Context context, AsyncResultCallback<T> 
callback, T result, Throwable e) {
-    if (context == Vertx.currentContext()) {
-      complete(callback, result, e);
-    } else {
-      context.runOnContext(v -> complete(callback, result, e));
-    }
-  }
-
-  private static <T> void complete(AsyncResultCallback<T> callback, T result, 
Throwable e) {
-    if (e != null) {
-      callback.fail(e.getCause());
-      return;
-    }
-
-    callback.success(result);
-  }
-
   // try to reference byte[]
   // otherwise copy byte[]
   public static byte[] getBytesFast(InputStream inputStream) throws 
IOException {
@@ -198,4 +166,35 @@ public static Vertx getVertxByName(String name) {
     byteBuf.getBytes(0, arr);
     return arr;
   }
+
+  public static CompletableFuture<Void> closeVertxByName(String name) {
+    LOGGER.info("Closing vertx {}.", name);
+    CompletableFuture<Void> future = new CompletableFuture<>();
+    Vertx vertx = vertxMap.remove(name);
+    if (vertx == null) {
+      LOGGER.info("Vertx {} not exist.", name);
+      future.complete(null);
+      return future;
+    }
+
+    vertx.close(ar -> {
+      if (ar.succeeded()) {
+        LOGGER.info("Success to close vertx {}.", name);
+        future.complete(null);
+        return;
+      }
+
+      future.completeExceptionally(ar.cause());
+    });
+    return future;
+  }
+
+  public static void blockCloseVertxByName(String name) {
+    CompletableFuture<Void> future = closeVertxByName(name);
+    try {
+      future.get();
+    } catch (Throwable e) {
+      LOGGER.error("Failed to close vertx {}.", name, e);
+    }
+  }
 }
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 52c37a267..62152e492 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -37,7 +37,6 @@
     <module>test-common</module>
     <module>spring-jaxrs-tests</module>
     <module>pojo-test</module>
-    <module>spring-springmvc-tests</module>
     <module>spring-zuul-tracing-tests</module>
     <module>spring-pojo-tests</module>
     <module>dynamic-config-tests</module>
diff --git 
a/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java
 
b/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java
index 35a82b1de..1402cc237 100644
--- 
a/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java
+++ 
b/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.servicecomb.spring.cloud.zuul.tracing;
 
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
diff --git a/integration-tests/springmvc-tests/pom.xml 
b/integration-tests/springmvc-tests/pom.xml
index ba4f674e3..8b907a256 100644
--- a/integration-tests/springmvc-tests/pom.xml
+++ b/integration-tests/springmvc-tests/pom.xml
@@ -27,7 +27,17 @@
   <modelVersion>4.0.0</modelVersion>
 
   <artifactId>springmvc-tests</artifactId>
-  <name>Java Chassis::Integration Tests::Raw Spring MVC</name>
+  <packaging>pom</packaging>
+  <name>Java Chassis::Integration Tests::Spring MVC</name>
+
+  <modules>
+    <module>springmvc-tests-common</module>
+    <module>springmvc-tests-general</module>
+    <module>springmvc-tests-simplified-mapping</module>
+    <module>springmvc-tests-general-with-springboot</module>
+    <module>springmvc-tests-simplified-mapping-with-springboot</module>
+  </modules>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb.demo</groupId>
diff --git a/integration-tests/springmvc-tests/springmvc-tests-common/pom.xml 
b/integration-tests/springmvc-tests/springmvc-tests-common/pom.xml
new file mode 100644
index 000000000..885d5126e
--- /dev/null
+++ b/integration-tests/springmvc-tests/springmvc-tests-common/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <parent>
+    <artifactId>springmvc-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.0.0-m2-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Java Chassis::Integration Tests::Spring MVC Common</name>
+  <artifactId>springmvc-tests-common</artifactId>
+
+</project>
\ No newline at end of file
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
similarity index 99%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
index 611916c9a..6d3fdf9d1 100644
--- 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
@@ -84,7 +84,7 @@
 
   private final String controllerUrl = baseUrl + "springmvc/controller/";
 
-  static void setUpLocalRegistry() {
+  public static void setUpLocalRegistry() {
     ClassLoader loader = Thread.currentThread().getContextClassLoader();
     URL resource = loader.getResource("registry.yaml");
     assert resource != null;
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java
diff --git a/integration-tests/spring-springmvc-tests/pom.xml 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/pom.xml
similarity index 74%
rename from integration-tests/spring-springmvc-tests/pom.xml
rename to 
integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/pom.xml
index 2840574d5..6832ba807 100644
--- a/integration-tests/spring-springmvc-tests/pom.xml
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/pom.xml
@@ -20,26 +20,21 @@
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
   <parent>
-    <artifactId>integration-tests</artifactId>
+    <artifactId>springmvc-tests</artifactId>
     <groupId>org.apache.servicecomb.tests</groupId>
     <version>1.0.0-m2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
-  <artifactId>spring-springmvc-tests</artifactId>
-  <name>Java Chassis::Integration Tests::Spring MVC</name>
+  <name>Java Chassis::Integration Tests::Spring MVC General With Spring 
Boot</name>
+  <artifactId>springmvc-tests-general-with-springboot</artifactId>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb.tests</groupId>
-      <artifactId>springmvc-tests</artifactId>
+      <artifactId>springmvc-tests-common</artifactId>
       <version>1.0.0-m2-SNAPSHOT</version>
       <type>test-jar</type>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.servicecomb.demo</groupId>
-          <artifactId>demo-signature</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
@@ -59,16 +54,4 @@
     </dependency>
   </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-</project>
+</project>
\ No newline at end of file
diff --git 
a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java
 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java
similarity index 80%
rename from 
integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java
index 75d6693f3..fbbf18137 100644
--- 
a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java
@@ -17,26 +17,24 @@
 
 package org.apache.servicecomb.demo.springmvc.tests;
 
+import org.apache.servicecomb.core.SCBEngine;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
 import org.springframework.boot.SpringApplication;
-import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.test.context.junit4.SpringRunner;
 
 @RunWith(SpringRunner.class)
 public class SpringMvcSpringIntegrationTest extends 
SpringMvcIntegrationTestBase {
-  private static ConfigurableApplicationContext context;
-
   @BeforeClass
-  public static void init() throws Exception {
+  public static void init() {
     System.setProperty("cse.uploads.directory", "/tmp");
     setUpLocalRegistry();
-    context = SpringApplication.run(SpringMvcSpringMain.class);
+    SpringApplication.run(SpringMvcSpringMain.class);
   }
 
   @AfterClass
-  public static void shutdown() throws Exception {
-    context.close();
+  public static void shutdown() {
+    SCBEngine.getInstance().uninit();
   }
 }
diff --git 
a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
similarity index 100%
rename from 
integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
diff --git 
a/integration-tests/spring-springmvc-tests/src/test/resources/log4j.properties 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/log4j.properties
similarity index 100%
rename from 
integration-tests/spring-springmvc-tests/src/test/resources/log4j.properties
rename to 
integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/log4j.properties
diff --git 
a/integration-tests/springmvc-tests/src/test/resources/microservice.yaml 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/microservice.yaml
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/resources/microservice.yaml
rename to 
integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/microservice.yaml
diff --git a/integration-tests/springmvc-tests/src/test/resources/registry.yaml 
b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/registry.yaml
similarity index 100%
rename from integration-tests/springmvc-tests/src/test/resources/registry.yaml
rename to 
integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/registry.yaml
diff --git a/integration-tests/springmvc-tests/springmvc-tests-general/pom.xml 
b/integration-tests/springmvc-tests/springmvc-tests-general/pom.xml
new file mode 100644
index 000000000..6b07517e8
--- /dev/null
+++ b/integration-tests/springmvc-tests/springmvc-tests-general/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <parent>
+    <artifactId>springmvc-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.0.0-m2-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Java Chassis::Integration Tests::Spring MVC General</name>
+  <artifactId>springmvc-tests-general</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>springmvc-tests-common</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java
 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java
similarity index 72%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java
index dd11460e4..7a49b20b6 100644
--- 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java
@@ -17,11 +17,9 @@
 
 package org.apache.servicecomb.demo.springmvc.tests;
 
-import org.apache.servicecomb.core.CseApplicationListener;
-import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.core.SCBEngine;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
-import org.springframework.context.event.ContextClosedEvent;
 
 public class RawSpringMvcIntegrationTest extends SpringMvcIntegrationTestBase {
 
@@ -33,9 +31,7 @@ public static void init() throws Exception {
   }
 
   @AfterClass
-  public static void shutdown() throws Exception {
-    CseApplicationListener cal = 
BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener");
-    ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext());
-    cal.onApplicationEvent(event);
+  public static void shutdown() {
+    SCBEngine.getInstance().uninit();
   }
 }
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
similarity index 100%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml
 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml
new file mode 100644
index 000000000..a5d81f871
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: springmvctest-it
+service_description:
+  name: springmvc-tests
+  version: 0.0.2
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  rest:
+    address: 0.0.0.0:8080
+  handler:
+    chain:
+      Provider:
+        default: bizkeeper-provider
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml
 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml
new file mode 100644
index 000000000..c1ca1e9b3
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+springmvc-tests:
+  - id: "001"
+    version: "0.0.2"
+    appid: springmvctest-it
+    instances:
+      - endpoints:
+        - rest://127.0.0.1:8080
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml
new file mode 100644
index 000000000..a98aea37d
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <parent>
+    <artifactId>springmvc-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.0.0-m2-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Java Chassis::Integration Tests::Spring MVC Simplified Mapping With 
Spring Boot</name>
+  <artifactId>springmvc-tests-simplified-mapping-with-springboot</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>springmvc-tests-common</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>spring-boot-starter-provider</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-test</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-validator</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
new file mode 100644
index 000000000..e149464af
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java
@@ -0,0 +1,26 @@
+/*
+ * 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.servicecomb.demo.springmvc.tests;
+
+import org.apache.servicecomb.springboot.starter.provider.EnableServiceComb;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableServiceComb
+class SpringMvcSpringMain {
+}
diff --git 
a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java
similarity index 81%
rename from 
integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java
index 089d3d021..292f9264d 100644
--- 
a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java
@@ -17,27 +17,25 @@
 
 package org.apache.servicecomb.demo.springmvc.tests;
 
+import org.apache.servicecomb.core.SCBEngine;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
 import org.springframework.boot.SpringApplication;
-import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.test.context.junit4.SpringRunner;
 
 @RunWith(SpringRunner.class)
 public class SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest extends 
SpringMvcIntegrationTestBase {
-  private static ConfigurableApplicationContext context;
-
   @BeforeClass
-  public static void init() throws Exception {
+  public static void init() {
     System.setProperty("spring.profiles.active", "SimplifiedMapping");
     System.setProperty("cse.uploads.directory", "/tmp");
     setUpLocalRegistry();
-    context = SpringApplication.run(SpringMvcSpringMain.class);
+    SpringApplication.run(SpringMvcSpringMain.class);
   }
 
   @AfterClass
-  public static void shutdown() throws Exception {
-    context.close();
+  public static void shutdown() {
+    SCBEngine.getInstance().uninit();
   }
 }
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties
new file mode 100644
index 000000000..bc03e25ce
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+log4j.rootLogger=INFO, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} 
- %m%n
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml
new file mode 100644
index 000000000..a5d81f871
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: springmvctest-it
+service_description:
+  name: springmvc-tests
+  version: 0.0.2
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  rest:
+    address: 0.0.0.0:8080
+  handler:
+    chain:
+      Provider:
+        default: bizkeeper-provider
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml
new file mode 100644
index 000000000..c1ca1e9b3
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+springmvc-tests:
+  - id: "001"
+    version: "0.0.2"
+    appid: springmvctest-it
+    instances:
+      - endpoints:
+        - rest://127.0.0.1:8080
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml
new file mode 100644
index 000000000..1940d9813
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <parent>
+    <artifactId>springmvc-tests</artifactId>
+    <groupId>org.apache.servicecomb.tests</groupId>
+    <version>1.0.0-m2-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Java Chassis::Integration Tests::Spring MVC Simplified Mapping</name>
+  <artifactId>springmvc-tests-simplified-mapping</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.tests</groupId>
+      <artifactId>springmvc-tests-common</artifactId>
+      <version>1.0.0-m2-SNAPSHOT</version>
+      <type>test-jar</type>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java
similarity index 74%
rename from 
integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java
rename to 
integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java
index a4cd05038..35cdbd8c2 100644
--- 
a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java
@@ -17,11 +17,9 @@
 
 package org.apache.servicecomb.demo.springmvc.tests;
 
-import org.apache.servicecomb.core.CseApplicationListener;
-import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.core.SCBEngine;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
-import org.springframework.context.event.ContextClosedEvent;
 
 public class RawSpringMvcSimplifiedMappingAnnotationIntegrationTest extends 
SpringMvcIntegrationTestBase {
 
@@ -34,9 +32,7 @@ public static void init() throws Exception {
   }
 
   @AfterClass
-  public static void shutdown() throws Exception {
-    CseApplicationListener cal = 
BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener");
-    ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext());
-    cal.onApplicationEvent(event);
+  public static void shutdown() {
+    SCBEngine.getInstance().uninit();
   }
 }
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
new file mode 100644
index 000000000..99d937049
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java
@@ -0,0 +1,29 @@
+/*
+ * 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.servicecomb.demo.springmvc.tests;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+
+public class SpringMvcTestMain {
+
+  public static void main(String[] args) throws Exception {
+    Log4jUtils.init();
+    BeanUtils.init();
+  }
+}
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml
new file mode 100644
index 000000000..a5d81f871
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+APPLICATION_ID: springmvctest-it
+service_description:
+  name: springmvc-tests
+  version: 0.0.2
+servicecomb:
+  service:
+    registry:
+      address: http://127.0.0.1:30100
+  rest:
+    address: 0.0.0.0:8080
+  handler:
+    chain:
+      Provider:
+        default: bizkeeper-provider
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml
 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml
new file mode 100644
index 000000000..c1ca1e9b3
--- /dev/null
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+springmvc-tests:
+  - id: "001"
+    version: "0.0.2"
+    appid: springmvctest-it
+    instances:
+      - endpoints:
+        - rest://127.0.0.1:8080
diff --git 
a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
 
b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
index 905d93851..18fd64aec 100644
--- 
a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
+++ 
b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
@@ -29,7 +29,6 @@
 import org.apache.servicecomb.core.invocation.InvocationFactory;
 import org.apache.servicecomb.core.provider.consumer.InvokerUtils;
 import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import org.apache.servicecomb.swagger.engine.SwaggerConsumer;
 import org.apache.servicecomb.swagger.engine.SwaggerConsumerOperation;
 import org.apache.servicecomb.swagger.invocation.Response;
@@ -64,7 +63,7 @@ public Invoker(String microserviceName, String schemaId, 
Class<?> consumerIntf)
   }
 
   protected void prepare() {
-    referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName);
+    referenceConfig = 
CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName);
     MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta();
 
     if (StringUtils.isEmpty(schemaId)) {
@@ -84,7 +83,7 @@ protected void prepare() {
   }
 
   @Override
-  public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+  public Object invoke(Object proxy, Method method, Object[] args) {
     if (swaggerConsumer == null) {
       synchronized (this) {
         if (swaggerConsumer == null) {
@@ -94,9 +93,8 @@ public Object invoke(Object proxy, Method method, Object[] 
args) throws Throwabl
     }
 
     SwaggerConsumerOperation consumerOperation = 
swaggerConsumer.findOperation(method.getName());
-    Invocation invocation =
-        InvocationFactory
-            .forConsumer(referenceConfig, schemaMeta, 
consumerOperation.getSwaggerMethod().getName(), null);
+    Invocation invocation = InvocationFactory
+        .forConsumer(referenceConfig, schemaMeta, 
consumerOperation.getSwaggerMethod().getName(), null);
 
     consumerOperation.getArgumentsMapper().toInvocation(args, invocation);
 
diff --git 
a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
 
b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
index 3264e6655..c0682f9b6 100644
--- 
a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
+++ 
b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
@@ -19,15 +19,15 @@
 
 import java.util.concurrent.CompletableFuture;
 
-import org.apache.servicecomb.core.BootListener;
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory;
 import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
 import org.apache.servicecomb.core.provider.consumer.InvokerUtils;
 import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import org.apache.servicecomb.swagger.engine.SwaggerConsumer;
 import org.apache.servicecomb.swagger.engine.SwaggerConsumerOperation;
 import org.apache.servicecomb.swagger.engine.bootstrap.BootstrapNormal;
@@ -56,29 +56,12 @@
 
   @Before
   public void setup() {
-    ReferenceConfigUtils.setReady(true);
+    SCBEngine.getInstance().setStatus(SCBStatus.UP);
   }
 
   @After
   public void teardown() {
-    ReferenceConfigUtils.setReady(false);
-  }
-
-  @Test
-  public void testNotReady() throws Throwable {
-    String exceptionMessage = "System is not ready for remote calls. "
-        + "When beans are making remote calls in initialization, it's better 
to "
-        + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.";
-
-    ReferenceConfigUtils.setReady(false);
-    Invoker invoker = new Invoker("test", "schemaId", IPerson.class);
-
-    try {
-      invoker.invoke(null, null, null);
-      Assert.fail("must throw exception");
-    } catch (IllegalStateException e) {
-      Assert.assertEquals(exceptionMessage, e.getMessage());
-    }
+    SCBEngine.getInstance().setStatus(SCBStatus.DOWN);
   }
 
   @Test
diff --git 
a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
 
b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
index 947469d3d..1e85f5a39 100644
--- 
a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
+++ 
b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
@@ -29,12 +29,12 @@
 import org.apache.servicecomb.common.rest.definition.RestOperationMeta;
 import org.apache.servicecomb.common.rest.locator.OperationLocator;
 import org.apache.servicecomb.common.rest.locator.ServicePathManager;
+import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.invocation.InvocationFactory;
 import org.apache.servicecomb.core.provider.consumer.InvokerUtils;
 import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
 import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
@@ -146,9 +146,11 @@ public ClientHttpResponse execute() {
     return this.invoke(args);
   }
 
-  protected RequestMeta createRequestMeta(String httpMetod, URI uri) {
+  protected RequestMeta createRequestMeta(String httpMethod, URI uri) {
     String microserviceName = uri.getAuthority();
-    ReferenceConfig referenceConfig = 
ReferenceConfigUtils.getForInvoke(microserviceName);
+
+    ReferenceConfig referenceConfig = 
CseContext.getInstance().getConsumerProviderManager()
+        .getReferenceConfig(microserviceName);
 
     MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta();
     ServicePathManager servicePathManager = 
ServicePathManager.getServicePathManager(microserviceMeta);
@@ -158,7 +160,7 @@ protected RequestMeta createRequestMeta(String httpMetod, 
URI uri) {
           microserviceMeta.getName()));
     }
 
-    OperationLocator locator = 
servicePathManager.consumerLocateOperation(path, httpMetod);
+    OperationLocator locator = 
servicePathManager.consumerLocateOperation(path, httpMethod);
     RestOperationMeta swaggerRestOperation = locator.getOperation();
 
     Map<String, String> pathParams = locator.getPathVarMap();
diff --git 
a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java
 
b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java
index a1d7271ee..7de386016 100644
--- 
a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java
+++ 
b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java
@@ -16,18 +16,17 @@
  */
 package org.apache.servicecomb.provider.springmvc.reference;
 
-import java.io.IOException;
 import java.net.URI;
-import java.util.Arrays;
+import java.util.Collections;
 
 import javax.xml.ws.Holder;
 
 import org.apache.servicecomb.common.rest.RestEngineSchemaListener;
-import org.apache.servicecomb.core.BootListener;
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
 import org.apache.servicecomb.core.definition.SchemaMeta;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import org.apache.servicecomb.core.unittest.UnitTestMeta;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.ServiceRegistry;
@@ -45,12 +44,12 @@
 public class TestCseClientHttpRequest {
   @Before
   public void setup() {
-    ReferenceConfigUtils.setReady(true);
+    SCBEngine.getInstance().setStatus(SCBStatus.UP);
   }
 
   @After
   public void teardown() {
-    ReferenceConfigUtils.setReady(false);
+    SCBEngine.getInstance().setStatus(SCBStatus.DOWN);
   }
 
   @RequestMapping(path = "SpringmvcImpl")
@@ -63,25 +62,7 @@ public void teardown() {
   }
 
   @Test
-  public void testNotReady() throws IOException {
-    String exceptionMessage = "System is not ready for remote calls. "
-        + "When beans are making remote calls in initialization, it's better 
to "
-        + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.";
-
-    ReferenceConfigUtils.setReady(false);
-    CseClientHttpRequest client =
-        new CseClientHttpRequest(URI.create("cse://app:test/"), 
HttpMethod.POST);
-
-    try {
-      client.execute();
-      Assert.fail("must throw exception");
-    } catch (IllegalStateException e) {
-      Assert.assertEquals(exceptionMessage, e.getMessage());
-    }
-  }
-
-  @Test
-  public void testNormal() throws IOException {
+  public void testNormal() {
     ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal();
     serviceRegistry.init();
     RegistryUtils.setServiceRegistry(serviceRegistry);
@@ -90,7 +71,7 @@ public void testNormal() throws IOException {
 
     CseContext.getInstance()
         .getSchemaListenerManager()
-        .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener()));
+        .setSchemaListenerList(Collections.singletonList(new 
RestEngineSchemaListener()));
 
     SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(SpringmvcImpl.class);
     
CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta);
diff --git 
a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java
 
b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java
index 35388cc7a..fcab92086 100644
--- 
a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java
+++ 
b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java
@@ -18,17 +18,17 @@
 package org.apache.servicecomb.provider.springmvc.reference.async;
 
 import java.net.URI;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.concurrent.CompletableFuture;
 
 import javax.xml.ws.Holder;
 
 import org.apache.servicecomb.common.rest.RestEngineSchemaListener;
-import org.apache.servicecomb.core.BootListener;
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
 import org.apache.servicecomb.core.definition.SchemaMeta;
-import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import org.apache.servicecomb.core.unittest.UnitTestMeta;
 import 
org.apache.servicecomb.provider.springmvc.reference.CseClientHttpResponse;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
@@ -51,12 +51,12 @@
 
   @Before
   public void setup() {
-    ReferenceConfigUtils.setReady(true);
+    SCBEngine.getInstance().setStatus(SCBStatus.UP);
   }
 
   @After
   public void teardown() {
-    ReferenceConfigUtils.setReady(false);
+    SCBEngine.getInstance().setStatus(SCBStatus.DOWN);
   }
 
   @RequestMapping(path = "CseAsyncClientHttpRequestTestSchema")
@@ -68,21 +68,6 @@ public void teardown() {
     }
   }
 
-  @Test
-  public void testNotReady() {
-    String exceptionMessage = "System is not ready for remote calls. "
-        + "When beans are making remote calls in initialization, it's better 
to "
-        + "implement " + BootListener.class.getName() + " and do it after 
EventType.AFTER_REGISTRY.";
-    ReferenceConfigUtils.setReady(false);
-    CseAsyncClientHttpRequest clientHttpRequest = new 
CseAsyncClientHttpRequest(URI.create("cse://app:test/"),
-        HttpMethod.POST);
-    try {
-      clientHttpRequest.executeAsync();
-    } catch (IllegalStateException e) {
-      Assert.assertEquals(exceptionMessage, e.getMessage());
-    }
-  }
-
   @Test
   public void testNormal() {
     ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal();
@@ -92,15 +77,17 @@ public void testNormal() {
 
     CseContext.getInstance()
         .getSchemaListenerManager()
-        .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener()));
+        .setSchemaListenerList(Collections.singletonList(new 
RestEngineSchemaListener()));
 
-    SchemaMeta schemaMeta = 
meta.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class);
+    SchemaMeta schemaMeta = meta
+        
.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class);
     
CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta);
 
     Holder<Invocation> holder = new Holder<>();
     CseAsyncClientHttpRequest client =
         new CseAsyncClientHttpRequest(URI.create(
-            "cse://app:test/" + 
CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName()
 + "/testbytes"),
+            "cse://app:test/" + 
CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName()
+                + "/testbytes"),
             HttpMethod.POST) {
           @Override
           protected CompletableFuture<ClientHttpResponse> 
doAsyncInvoke(Invocation invocation) {
@@ -124,8 +111,9 @@ public void testFail() {
     UnitTestMeta meta = new UnitTestMeta();
     CseContext.getInstance()
         .getSchemaListenerManager()
-        .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener()));
-    SchemaMeta schemaMeta = 
meta.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class);
+        .setSchemaListenerList(Collections.singletonList(new 
RestEngineSchemaListener()));
+    SchemaMeta schemaMeta = meta
+        
.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class);
     
CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta);
 
     Throwable error = new Error("failed");
@@ -133,7 +121,8 @@ public void testFail() {
 
     CseAsyncClientHttpRequest client =
         new CseAsyncClientHttpRequest(URI.create(
-            "cse://app:test/" + 
CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName()
 + "/testbytes"),
+            "cse://app:test/" + 
CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName()
+                + "/testbytes"),
             HttpMethod.POST) {
           @Override
           protected CompletableFuture<ClientHttpResponse> 
doAsyncInvoke(Invocation invocation) {
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java
index e262d8cc4..70625dad2 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java
@@ -59,11 +59,6 @@ public static void open(IpPort ipPort, String url, 
Handler<Void> onOpen, Handler
             });
             ws.closeHandler(v -> {
               onClose.handle(v);
-              try {
-                ws.close();
-              } catch (Exception err) {
-                LOGGER.error("ws close error.", err);
-              }
             });
             ws.handler(onMessage);
           },


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to