This is an automated email from the ASF dual-hosted git repository.

zhangliang pushed a commit to branch restful-api
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob.git


The following commit(s) were added to refs/heads/restful-api by this push:
     new 04aadb3  Refactor cloud-scheduler with elasticjob-restful. (#1395)
04aadb3 is described below

commit 04aadb39bee3920c6d26df615b48f612b935f0a5
Author: 吴伟杰 <[email protected]>
AuthorDate: Sat Aug 22 14:33:01 2020 +0800

    Refactor cloud-scheduler with elasticjob-restful. (#1395)
---
 .../elasticjob-cloud-scheduler/pom.xml             |  38 +-----
 .../elasticjob/cloud/console/ConsoleBootstrap.java |  52 ++------
 .../cloud/console/config/FilterRegisterConfig.java |  59 ---------
 .../ConsoleExceptionHandler.java}                  |  25 ++--
 .../config/advice/ConsoleRestControllerAdvice.java |  66 ---------
 .../JsonResponseBodySerializer.java}               |  35 +++--
 .../console/controller/CloudAppController.java     |  65 +++++----
 .../console/controller/CloudJobController.java     | 147 ++++++++++++---------
 .../controller/CloudOperationController.java       |  39 +++---
 .../console/security/AuthenticationResult.java     |  35 -----
 .../security/UserAuthenticationService.java        |  57 --------
 .../cloud/console/security/WwwAuthFilter.java      |  89 -------------
 ...cjob.restful.serializer.ResponseBodySerializer} |   4 +-
 .../cloud/console/AbstractCloudControllerTest.java |  32 +++--
 .../console/controller/CloudJobControllerTest.java |   5 +-
 .../fixture/master/MesosMasterServerMock.java      |  15 +--
 .../master/MesosMasterServerMockConfiguration.java |  38 ------
 .../mesos/fixture/slave/MesosSlaveServerMock.java  |  15 +--
 .../slave/MesosSlaveServerMockConfiguration.java   |  38 ------
 19 files changed, 227 insertions(+), 627 deletions(-)

diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/pom.xml 
b/elasticjob-cloud/elasticjob-cloud-scheduler/pom.xml
index 1cdf6e8..fdad952 100755
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/pom.xml
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/pom.xml
@@ -57,41 +57,9 @@
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
-            <version>${springframework.version}</version>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-            <version>${springframework.version}</version>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-webmvc</artifactId>
-            <version>${springframework.version}</version>
-            <scope>compile</scope>
-            <exclusions>
-                <exclusion>
-                    <artifactId>spring-web</artifactId>
-                    <groupId>org.springframework</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>spring-context</artifactId>
-                    <groupId>org.springframework</groupId>
-                </exclusion>
-            </exclusions>
+            <groupId>org.apache.shardingsphere.elasticjob</groupId>
+            <artifactId>elasticjob-restful</artifactId>
+            <version>${project.parent.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
index 9c8af86..663ce34 100644
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
@@ -17,8 +17,7 @@
 
 package org.apache.shardingsphere.elasticjob.cloud.console;
 
-import lombok.Setter;
-import org.apache.commons.lang3.ArrayUtils;
+import 
org.apache.shardingsphere.elasticjob.cloud.console.config.advice.ConsoleExceptionHandler;
 import 
org.apache.shardingsphere.elasticjob.cloud.console.controller.CloudAppController;
 import 
org.apache.shardingsphere.elasticjob.cloud.console.controller.CloudJobController;
 import 
org.apache.shardingsphere.elasticjob.cloud.console.controller.CloudOperationController;
@@ -26,67 +25,38 @@ import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.env.RestfulServerCon
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.ReconcileService;
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerManager;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.server.WebServerFactoryCustomizer;
-import 
org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
-import org.springframework.context.ConfigurableApplicationContext;
+import org.apache.shardingsphere.elasticjob.restful.NettyRestfulService;
+import 
org.apache.shardingsphere.elasticjob.restful.NettyRestfulServiceConfiguration;
+import org.apache.shardingsphere.elasticjob.restful.RestfulService;
 
 /**
  * Console bootstrap for Cloud.
  */
 public class ConsoleBootstrap {
     
-    private ConfigurableApplicationContext context;
+    private final RestfulService restfulService;
     
     public ConsoleBootstrap(final CoordinatorRegistryCenter regCenter, final 
RestfulServerConfiguration config, final ProducerManager producerManager, final 
ReconcileService reconcileService) {
-        ConsoleApplication.port = config.getPort();
         CloudJobController.init(regCenter, producerManager);
         CloudAppController.init(regCenter, producerManager);
         CloudOperationController.init(regCenter, reconcileService);
+        NettyRestfulServiceConfiguration restfulServiceConfiguration = new 
NettyRestfulServiceConfiguration(config.getPort());
+        restfulServiceConfiguration.addControllerInstance(new 
CloudJobController(), new CloudAppController(), new CloudOperationController());
+        restfulServiceConfiguration.addExceptionHandler(Exception.class, new 
ConsoleExceptionHandler());
+        restfulService = new NettyRestfulService(restfulServiceConfiguration);
     }
     
     /**
      * Startup RESTful server.
      */
     public void start() {
-        context = ConsoleApplication.start();
+        restfulService.startup();
     }
     
     /**
      * Stop RESTful server.
      */
     public void stop() {
-        context.close();
-    }
-    
-    @SpringBootApplication
-    public static class ConsoleApplication implements 
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
-        
-        @Setter
-        private static int port;
-        
-        @Setter
-        private static Class<?>[] extraSources;
-        
-        /**
-         * Startup RESTful server.
-         * @return ConfigurableApplicationContext
-         */
-        public static ConfigurableApplicationContext start() {
-            SpringApplicationBuilder applicationBuilder = new 
SpringApplicationBuilder(ConsoleApplication.class);
-            if (ArrayUtils.isNotEmpty(extraSources)) {
-                applicationBuilder.sources(extraSources);
-            }
-            return applicationBuilder.build().run();
-        }
-        
-        @Override
-        public void customize(final ConfigurableServletWebServerFactory 
factory) {
-            if (port <= 0) {
-                return;
-            }
-            factory.setPort(port);
-        }
+        restfulService.shutdown();
     }
 }
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/FilterRegisterConfig.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/FilterRegisterConfig.java
deleted file mode 100644
index e1b1229..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/FilterRegisterConfig.java
+++ /dev/null
@@ -1,59 +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.shardingsphere.elasticjob.cloud.console.config;
-
-import 
org.apache.shardingsphere.elasticjob.cloud.console.security.UserAuthenticationService;
-import 
org.apache.shardingsphere.elasticjob.cloud.console.security.WwwAuthFilter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.servlet.DispatcherType;
-import java.util.EnumSet;
-
-/**
- * Filter register config.
- **/
-@Configuration
-public class FilterRegisterConfig {
-    
-    private final UserAuthenticationService userAuthenticationService;
-    
-    @Autowired
-    public FilterRegisterConfig(final UserAuthenticationService 
userAuthenticationService) {
-        this.userAuthenticationService = userAuthenticationService;
-    }
-    
-    /**
-     * register www auth filter.
-     *
-     * @return www auth filter bean
-     */
-    @Bean
-    public FilterRegistrationBean<WwwAuthFilter> wwwAuthFilter() {
-        WwwAuthFilter wwwAuthFilter = new WwwAuthFilter();
-        wwwAuthFilter.setUserAuthenticationService(userAuthenticationService);
-        FilterRegistrationBean<WwwAuthFilter> registration = new 
FilterRegistrationBean<>();
-        registration.setFilter(wwwAuthFilter);
-        registration.addUrlPatterns("/");
-        registration.addUrlPatterns("*.html");
-        registration.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));
-        return registration;
-    }
-}
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/WebMvcConfig.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/advice/ConsoleExceptionHandler.java
similarity index 57%
copy from 
elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/WebMvcConfig.java
copy to 
elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/advice/ConsoleExceptionHandler.java
index 0a595e0..6055c31 100644
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/WebMvcConfig.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/advice/ConsoleExceptionHandler.java
@@ -15,23 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.cloud.console.config;
+package org.apache.shardingsphere.elasticjob.cloud.console.config.advice;
 
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.method.HandlerTypePredicate;
-import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import lombok.extern.slf4j.Slf4j;
+import 
org.apache.shardingsphere.elasticjob.restful.handler.ExceptionHandleResult;
+import org.apache.shardingsphere.elasticjob.restful.handler.ExceptionHandler;
 
 /**
- * Web mvc config.
+ * A default exception handler for restful service.
  **/
-@Configuration
-public class WebMvcConfig implements WebMvcConfigurer {
+@Slf4j
+public final class ConsoleExceptionHandler implements 
ExceptionHandler<Exception> {
     
     @Override
-    public void configurePathMatch(final PathMatchConfigurer configurer) {
-        HandlerTypePredicate handlerTypePredicate = 
HandlerTypePredicate.forAnnotation(RestController.class);
-        configurer.addPathPrefix("/api", handlerTypePredicate);
+    public ExceptionHandleResult handleException(final Exception ex) {
+        return ExceptionHandleResult.builder()
+                .statusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code())
+                .result(ex.getLocalizedMessage())
+                .build();
     }
 }
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/advice/ConsoleRestControllerAdvice.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/advice/ConsoleRestControllerAdvice.java
deleted file mode 100644
index 8015ab1..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/advice/ConsoleRestControllerAdvice.java
+++ /dev/null
@@ -1,66 +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.shardingsphere.elasticjob.cloud.console.config.advice;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.shardingsphere.elasticjob.infra.exception.ExceptionUtils;
-import org.springframework.core.MethodParameter;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.server.ServerHttpRequest;
-import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-import 
org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
-
-/**
- * Console rest controller advice.
- **/
-@RestControllerAdvice
-@Slf4j
-public final class ConsoleRestControllerAdvice implements 
ResponseBodyAdvice<Object> {
-    
-    @Override
-    public boolean supports(final MethodParameter returnType, final Class<? 
extends HttpMessageConverter<?>> converterType) {
-        //only advice return void method.
-        if (null == returnType.getMethod()) {
-            return false;
-        }
-        return 
void.class.isAssignableFrom(returnType.getMethod().getReturnType());
-    }
-    
-    @Override
-    public Object beforeBodyWrite(final Object body, final MethodParameter 
returnType, final MediaType selectedContentType,
-                                  final Class<? extends 
HttpMessageConverter<?>> selectedConverterType, final ServerHttpRequest 
request, final ServerHttpResponse response) {
-        //if the method return void, then the value is true and returns.
-        return null == body ? true : body;
-    }
-    
-    /**
-     * Handle exception.
-     *
-     * @param ex exception
-     * @return response result
-     */
-    @ExceptionHandler(Exception.class)
-    public ResponseEntity<String> toResponse(final Exception ex) {
-        return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ExceptionUtils.transform(ex));
-    }
-}
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/WebMvcConfig.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/serializer/JsonResponseBodySerializer.java
similarity index 50%
rename from 
elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/WebMvcConfig.java
rename to 
elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/serializer/JsonResponseBodySerializer.java
index 0a595e0..26d48ee 100644
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/WebMvcConfig.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/config/serializer/JsonResponseBodySerializer.java
@@ -15,23 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.cloud.console.config;
+package org.apache.shardingsphere.elasticjob.cloud.console.config.serializer;
 
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.method.HandlerTypePredicate;
-import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import io.netty.handler.codec.http.HttpHeaderValues;
+import 
org.apache.shardingsphere.elasticjob.restful.serializer.ResponseBodySerializer;
+
+import java.nio.charset.StandardCharsets;
 
 /**
- * Web mvc config.
- **/
-@Configuration
-public class WebMvcConfig implements WebMvcConfigurer {
+ * Json response body serializer. Serialize object to json byte except String.
+ */
+public class JsonResponseBodySerializer implements ResponseBodySerializer {
+    
+    private final Gson gson = new GsonBuilder().serializeNulls().create();
+    
+    @Override
+    public String mimeType() {
+        return HttpHeaderValues.APPLICATION_JSON.toString();
+    }
     
     @Override
-    public void configurePathMatch(final PathMatchConfigurer configurer) {
-        HandlerTypePredicate handlerTypePredicate = 
HandlerTypePredicate.forAnnotation(RestController.class);
-        configurer.addPathPrefix("/api", handlerTypePredicate);
+    public byte[] serialize(final Object responseBody) {
+        if (responseBody instanceof String) {
+            return ((String) responseBody).getBytes(StandardCharsets.UTF_8);
+        }
+        return gson.toJson(responseBody).getBytes(StandardCharsets.UTF_8);
     }
 }
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudAppController.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudAppController.java
index 0c3d5b0..8c15369 100755
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudAppController.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudAppController.java
@@ -18,8 +18,6 @@
 package org.apache.shardingsphere.elasticjob.cloud.console.controller;
 
 import com.google.gson.JsonParseException;
-import java.util.Collection;
-import java.util.Optional;
 import org.apache.mesos.Protos.ExecutorID;
 import org.apache.mesos.Protos.SlaveID;
 import 
org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
@@ -33,21 +31,22 @@ import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerMan
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.state.disable.app.DisableAppService;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.apache.shardingsphere.elasticjob.restful.Http;
+import org.apache.shardingsphere.elasticjob.restful.RestfulController;
+import org.apache.shardingsphere.elasticjob.restful.annotation.ContextPath;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Mapping;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Param;
+import org.apache.shardingsphere.elasticjob.restful.annotation.ParamSource;
+import org.apache.shardingsphere.elasticjob.restful.annotation.RequestBody;
+
+import java.util.Collection;
+import java.util.Optional;
 
 /**
  * Cloud app controller.
  */
-@RestController
-@RequestMapping("/app")
-public final class CloudAppController {
+@ContextPath("/api/app")
+public final class CloudAppController implements RestfulController {
     
     private static CoordinatorRegistryCenter regCenter;
     
@@ -83,24 +82,28 @@ public final class CloudAppController {
      * Register app config.
      *
      * @param appConfig cloud app config
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping
-    public void register(@RequestBody final CloudAppConfigurationPOJO 
appConfig) {
+    @Mapping(method = Http.POST)
+    public boolean register(@RequestBody final CloudAppConfigurationPOJO 
appConfig) {
         Optional<CloudAppConfigurationPOJO> appConfigFromZk = 
appConfigService.load(appConfig.getAppName());
         if (appConfigFromZk.isPresent()) {
             throw new AppConfigurationException("app '%s' already existed.", 
appConfig.getAppName());
         }
         appConfigService.add(appConfig);
+        return true;
     }
     
     /**
      * Update app config.
      *
      * @param appConfig cloud app config
+     * @return <tt>true</tt> for operation finished.
      */
-    @PutMapping
-    public void update(@RequestBody final CloudAppConfigurationPOJO appConfig) 
{
+    @Mapping(method = Http.PUT)
+    public boolean update(@RequestBody final CloudAppConfigurationPOJO 
appConfig) {
         appConfigService.update(appConfig);
+        return true;
     }
     
     /**
@@ -109,8 +112,8 @@ public final class CloudAppController {
      * @param appName app name
      * @return cloud app config
      */
-    @GetMapping("/{appName}")
-    public CloudAppConfigurationPOJO detail(@PathVariable("appName") final 
String appName) {
+    @Mapping(method = Http.GET, path = "/{appName}")
+    public CloudAppConfigurationPOJO detail(@Param(name = "appName", source = 
ParamSource.PATH) final String appName) {
         Optional<CloudAppConfigurationPOJO> appConfig = 
appConfigService.load(appName);
         return appConfig.orElse(null);
     }
@@ -120,7 +123,7 @@ public final class CloudAppController {
      *
      * @return collection of registered app configs
      */
-    @GetMapping("/list")
+    @Mapping(method = Http.GET, path = "/list")
     public Collection<CloudAppConfigurationPOJO> findAllApps() {
         return appConfigService.loadAll();
     }
@@ -131,8 +134,8 @@ public final class CloudAppController {
      * @param appName app name
      * @return true is disabled, otherwise not
      */
-    @GetMapping("/{appName}/disable")
-    public boolean isDisabled(@PathVariable("appName") final String appName) {
+    @Mapping(method = Http.GET, path = "/{appName}/disable")
+    public boolean isDisabled(@Param(name = "appName", source = 
ParamSource.PATH) final String appName) {
         return disableAppService.isDisabled(appName);
     }
     
@@ -140,9 +143,10 @@ public final class CloudAppController {
      * Disable app config.
      *
      * @param appName app name
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/{appName}/disable")
-    public void disable(@PathVariable("appName") final String appName) {
+    @Mapping(method = Http.POST, path = "/{appName}/disable")
+    public boolean disable(@Param(name = "appName", source = ParamSource.PATH) 
final String appName) {
         if (appConfigService.load(appName).isPresent()) {
             disableAppService.add(appName);
             for (CloudJobConfigurationPOJO each : jobConfigService.loadAll()) {
@@ -151,15 +155,17 @@ public final class CloudAppController {
                 }
             }
         }
+        return true;
     }
     
     /**
      * Enable app.
      *
      * @param appName app name
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/{appName}/enable")
-    public void enable(@PathVariable("appName") final String appName) {
+    @Mapping(method = Http.POST, path = "/{appName}/enable")
+    public boolean enable(@Param(name = "appName", source = ParamSource.PATH) 
final String appName) {
         if (appConfigService.load(appName).isPresent()) {
             disableAppService.remove(appName);
             for (CloudJobConfigurationPOJO each : jobConfigService.loadAll()) {
@@ -168,19 +174,22 @@ public final class CloudAppController {
                 }
             }
         }
+        return true;
     }
     
     /**
      * Deregister app.
      *
      * @param appName app name
+     * @return <tt>true</tt> for operation finished.
      */
-    @DeleteMapping("/{appName}")
-    public void deregister(@PathVariable("appName") final String appName) {
+    @Mapping(method = Http.DELETE, path = "/{appName}")
+    public boolean deregister(@Param(name = "appName", source = 
ParamSource.PATH) final String appName) {
         if (appConfigService.load(appName).isPresent()) {
             removeAppAndJobConfigurations(appName);
             stopExecutors(appName);
         }
+        return true;
     }
     
     private void removeAppAndJobConfigurations(final String appName) {
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobController.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobController.java
index ce357b1..f5919aa 100755
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobController.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobController.java
@@ -38,19 +38,17 @@ import 
org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskRunni
 import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.apache.shardingsphere.elasticjob.restful.Http;
+import org.apache.shardingsphere.elasticjob.restful.wrapper.QueryParameterMap;
+import org.apache.shardingsphere.elasticjob.restful.annotation.ParamSource;
+import org.apache.shardingsphere.elasticjob.restful.RestfulController;
+import org.apache.shardingsphere.elasticjob.restful.annotation.ContextPath;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Mapping;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Param;
+import org.apache.shardingsphere.elasticjob.restful.annotation.RequestBody;
 import org.apache.shardingsphere.elasticjob.tracing.api.TracingConfiguration;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
 
 import javax.sql.DataSource;
 import java.text.ParseException;
@@ -71,9 +69,8 @@ import java.util.Set;
  * Cloud job restful api.
  */
 @Slf4j
-@RestController
-@RequestMapping("/job")
-public final class CloudJobController {
+@ContextPath("/api/job")
+public final class CloudJobController implements RestfulController {
     
     private static CoordinatorRegistryCenter regCenter;
     
@@ -108,86 +105,106 @@ public final class CloudJobController {
     
     /**
      * Register cloud job.
+     *
      * @param cloudJobConfig cloud job configuration
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/register")
-    public void register(@RequestBody final CloudJobConfigurationPOJO 
cloudJobConfig) {
+    @Mapping(method = Http.POST, path = "/register")
+    public boolean register(@RequestBody final CloudJobConfigurationPOJO 
cloudJobConfig) {
         producerManager.register(cloudJobConfig);
+        return true;
     }
     
     /**
      * Update cloud job.
+     *
      * @param cloudJobConfig cloud job configuration
+     * @return <tt>true</tt> for operation finished.
      */
-    @PutMapping("/update")
-    public void update(@RequestBody final CloudJobConfigurationPOJO 
cloudJobConfig) {
+    @Mapping(method = Http.PUT, path = "/update")
+    public boolean update(@RequestBody final CloudJobConfigurationPOJO 
cloudJobConfig) {
         producerManager.update(cloudJobConfig);
+        return true;
     }
     
     /**
      * Deregister cloud job.
+     *
      * @param jobName job name
+     * @return <tt>true</tt> for operation finished.
      */
-    @DeleteMapping("/{jobName}/deregister")
-    public void deregister(@PathVariable final String jobName) {
+    @Mapping(method = Http.DELETE, path = "/{jobName}/deregister")
+    public boolean deregister(@Param(name = "jobName", source = 
ParamSource.PATH) final String jobName) {
         producerManager.deregister(jobName);
+        return true;
     }
     
     /**
      * Check whether the cloud job is disabled or not.
+     *
      * @param jobName job name
      * @return true is disabled, otherwise not
      */
-    @GetMapping("/{jobName}/disable")
-    public boolean isDisabled(@PathVariable("jobName") final String jobName) {
+    @Mapping(method = Http.GET, path = "/{jobName}/disable")
+    public boolean isDisabled(@Param(name = "jobName", source = 
ParamSource.PATH) final String jobName) {
         return facadeService.isJobDisabled(jobName);
     }
     
     /**
      * Enable cloud job.
+     *
      * @param jobName job name
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/{jobName}/enable")
-    public void enable(@PathVariable("jobName") final String jobName) {
+    @Mapping(method = Http.POST, path = "/{jobName}/enable")
+    public boolean enable(@Param(name = "jobName", source = ParamSource.PATH) 
final String jobName) {
         Optional<CloudJobConfigurationPOJO> configOptional = 
configService.load(jobName);
         if (configOptional.isPresent()) {
             facadeService.enableJob(jobName);
             producerManager.reschedule(jobName);
         }
+        return true;
     }
     
     /**
      * Disable cloud job.
+     *
      * @param jobName job name
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/{jobName}/disable")
-    public void disable(@PathVariable("jobName") final String jobName) {
+    @Mapping(method = Http.POST, path = "/{jobName}/disable")
+    public boolean disable(@Param(name = "jobName", source = ParamSource.PATH) 
final String jobName) {
         if (configService.load(jobName).isPresent()) {
             facadeService.disableJob(jobName);
             producerManager.unschedule(jobName);
         }
+        return true;
     }
     
     /**
      * Trigger job once.
+     *
      * @param jobName job name
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/trigger")
-    public void trigger(@RequestBody final String jobName) {
+    @Mapping(method = Http.POST, path = "/trigger")
+    public boolean trigger(@RequestBody final String jobName) {
         Optional<CloudJobConfigurationPOJO> config = 
configService.load(jobName);
         if (config.isPresent() && CloudJobExecutionType.DAEMON == 
config.get().getJobExecutionType()) {
             throw new JobSystemException("Daemon job '%s' cannot support 
trigger.", jobName);
         }
         facadeService.addTransient(jobName);
+        return true;
     }
     
     /**
      * Query job detail.
+     *
      * @param jobName job name
      * @return the job detail
      */
-    @GetMapping("/jobs/{jobName}")
-    public CloudJobConfigurationPOJO detail(@PathVariable("jobName") final 
String jobName) {
+    @Mapping(method = Http.GET, path = "/jobs/{jobName}")
+    public CloudJobConfigurationPOJO detail(@Param(name = "jobName", source = 
ParamSource.PATH) final String jobName) {
         Optional<CloudJobConfigurationPOJO> cloudJobConfig = 
configService.load(jobName);
         return cloudJobConfig.orElse(null);
     }
@@ -196,7 +213,7 @@ public final class CloudJobController {
      * Find all jobs.
      * @return all jobs
      */
-    @GetMapping("/jobs")
+    @Mapping(method = Http.GET, path = "/jobs")
     public Collection<CloudJobConfigurationPOJO> findAllJobs() {
         return configService.loadAll();
     }
@@ -205,7 +222,7 @@ public final class CloudJobController {
      * Find all running tasks.
      * @return all running tasks
      */
-    @GetMapping("tasks/running")
+    @Mapping(method = Http.GET, path = "/tasks/running")
     public Collection<TaskContext> findAllRunningTasks() {
         List<TaskContext> result = new LinkedList<>();
         for (Set<TaskContext> each : 
facadeService.getAllRunningTasks().values()) {
@@ -218,7 +235,7 @@ public final class CloudJobController {
      * Find all ready tasks.
      * @return collection of all ready tasks
      */
-    @GetMapping("tasks/ready")
+    @Mapping(method = Http.GET, path = "/tasks/ready")
     public Collection<Map<String, String>> findAllReadyTasks() {
         Map<String, Integer> readyTasks = facadeService.getAllReadyTasks();
         List<Map<String, String>> result = new ArrayList<>(readyTasks.size());
@@ -235,7 +252,7 @@ public final class CloudJobController {
      * Find all failover tasks.
      * @return collection of all the failover tasks
      */
-    @GetMapping("tasks/failover")
+    @Mapping(method = Http.GET, path = "/tasks/failover")
     public Collection<FailoverTaskInfo> findAllFailoverTasks() {
         List<FailoverTaskInfo> result = new LinkedList<>();
         for (Collection<FailoverTaskInfo> each : 
facadeService.getAllFailoverTasks().values()) {
@@ -250,12 +267,12 @@ public final class CloudJobController {
      * @return job execution event
      * @throws ParseException parse exception
      */
-    @GetMapping("events/executions")
-    public JobEventRdbSearch.Result<JobExecutionEvent> 
findJobExecutionEvents(@RequestParam final MultiValueMap<String, String> 
requestParams) throws ParseException {
+    @Mapping(method = Http.GET, path = "/events/executions")
+    public JobEventRdbSearch.Result<JobExecutionEvent> 
findJobExecutionEvents(final QueryParameterMap requestParams) throws 
ParseException {
         if (!isRdbConfigured()) {
             return new JobEventRdbSearch.Result<>(0, Collections.emptyList());
         }
-        return 
jobEventRdbSearch.findJobExecutionEvents(buildCondition(requestParams, new 
String[]{"jobName", "taskId", "ip", "isSuccess"}));
+        return 
jobEventRdbSearch.findJobExecutionEvents(buildCondition(requestParams.toSingleValueMap(),
 new String[]{"jobName", "taskId", "ip", "isSuccess"}));
     }
     
     /**
@@ -264,47 +281,47 @@ public final class CloudJobController {
      * @return job status trace event
      * @throws ParseException parse exception
      */
-    @GetMapping("events/statusTraces")
-    public JobEventRdbSearch.Result<JobStatusTraceEvent> 
findJobStatusTraceEvents(@RequestParam final MultiValueMap<String, String> 
requestParams) throws ParseException {
+    @Mapping(method = Http.GET, path = "/events/statusTraces")
+    public JobEventRdbSearch.Result<JobStatusTraceEvent> 
findJobStatusTraceEvents(final QueryParameterMap requestParams) throws 
ParseException {
         if (!isRdbConfigured()) {
             return new JobEventRdbSearch.Result<>(0, Collections.emptyList());
         }
-        return 
jobEventRdbSearch.findJobStatusTraceEvents(buildCondition(requestParams, new 
String[]{"jobName", "taskId", "slaveId", "source", "executionType", "state"}));
+        return 
jobEventRdbSearch.findJobStatusTraceEvents(buildCondition(requestParams.toSingleValueMap(),
 new String[]{"jobName", "taskId", "slaveId", "source", "executionType", 
"state"}));
     }
     
     private boolean isRdbConfigured() {
         return null != jobEventRdbSearch;
     }
     
-    private JobEventRdbSearch.Condition buildCondition(final 
MultiValueMap<String, String> requestParams, final String[] params) throws 
ParseException {
+    private JobEventRdbSearch.Condition buildCondition(final Map<String, 
String> requestParams, final String[] params) throws ParseException {
         int perPage = 10;
         int page = 1;
-        if (!Strings.isNullOrEmpty(requestParams.getFirst("per_page"))) {
-            perPage = Integer.parseInt(requestParams.getFirst("per_page"));
+        if (!Strings.isNullOrEmpty(requestParams.get("per_page"))) {
+            perPage = Integer.parseInt(requestParams.get("per_page"));
         }
-        if (!Strings.isNullOrEmpty(requestParams.getFirst("page"))) {
-            page = Integer.parseInt(requestParams.getFirst("page"));
+        if (!Strings.isNullOrEmpty(requestParams.get("page"))) {
+            page = Integer.parseInt(requestParams.get("page"));
         }
-        String sort = requestParams.getFirst("sort");
-        String order = requestParams.getFirst("order");
+        String sort = requestParams.get("sort");
+        String order = requestParams.get("order");
         Date startTime = null;
         Date endTime = null;
         Map<String, Object> fields = getQueryParameters(requestParams, params);
         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss");
-        if (!Strings.isNullOrEmpty(requestParams.getFirst("startTime"))) {
-            startTime = 
simpleDateFormat.parse(requestParams.getFirst("startTime"));
+        if (!Strings.isNullOrEmpty(requestParams.get("startTime"))) {
+            startTime = simpleDateFormat.parse(requestParams.get("startTime"));
         }
-        if (!Strings.isNullOrEmpty(requestParams.getFirst("endTime"))) {
-            endTime = 
simpleDateFormat.parse(requestParams.getFirst("endTime"));
+        if (!Strings.isNullOrEmpty(requestParams.get("endTime"))) {
+            endTime = simpleDateFormat.parse(requestParams.get("endTime"));
         }
         return new JobEventRdbSearch.Condition(perPage, page, sort, order, 
startTime, endTime, fields);
     }
     
-    private Map<String, Object> getQueryParameters(final MultiValueMap<String, 
String> requestParams, final String[] params) {
+    private Map<String, Object> getQueryParameters(final Map<String, String> 
requestParams, final String[] params) {
         final Map<String, Object> result = new HashMap<>();
         for (String each : params) {
-            if (!Strings.isNullOrEmpty(requestParams.getFirst(each))) {
-                result.put(each, requestParams.getFirst(each));
+            if (!Strings.isNullOrEmpty(requestParams.get(each))) {
+                result.put(each, requestParams.get(each));
             }
         }
         return result;
@@ -312,11 +329,12 @@ public final class CloudJobController {
     
     /**
      * Find task result statistics.
+     *
      * @param since time span
      * @return task result statistics
      */
-    @GetMapping("/statistics/tasks/results")
-    public List<TaskResultStatistics> 
findTaskResultStatistics(@RequestParam(value = "since", required = false) final 
String since) {
+    @Mapping(method = Http.GET, path = "/statistics/tasks/results")
+    public List<TaskResultStatistics> findTaskResultStatistics(@Param(name = 
"since", source = ParamSource.QUERY, required = false) final String since) {
         if ("last24hours".equals(since)) {
             return statisticManager.findTaskResultStatisticsDaily();
         } else {
@@ -326,11 +344,12 @@ public final class CloudJobController {
     
     /**
      * Get task result statistics.
+     *
      * @param period time period
      * @return task result statistics
      */
-    @GetMapping("/statistics/tasks/results/{period}")
-    public TaskResultStatistics getTaskResultStatistics(@PathVariable(value = 
"period", required = false) final String period) {
+    @Mapping(method = Http.GET, path = "/statistics/tasks/results/{period}")
+    public TaskResultStatistics getTaskResultStatistics(@Param(name = 
"period", source = ParamSource.PATH, required = false) final String period) {
         switch (period) {
             case "online":
                 return statisticManager.getTaskResultStatisticsSinceOnline();
@@ -347,11 +366,12 @@ public final class CloudJobController {
     
     /**
      * Find task running statistics.
+     *
      * @param since time span
      * @return task result statistics
      */
-    @GetMapping("/statistics/tasks/running")
-    public List<TaskRunningStatistics> 
findTaskRunningStatistics(@RequestParam(value = "since", required = false) 
final String since) {
+    @Mapping(method = Http.GET, path = "/statistics/tasks/running")
+    public List<TaskRunningStatistics> findTaskRunningStatistics(@Param(name = 
"since", source = ParamSource.QUERY, required = false) final String since) {
         if ("lastWeek".equals(since)) {
             return statisticManager.findTaskRunningStatisticsWeekly();
         } else {
@@ -363,18 +383,19 @@ public final class CloudJobController {
      * Get job execution type statistics.
      * @return job execution statistics
      */
-    @GetMapping("/statistics/jobs/executionType")
+    @Mapping(method = Http.GET, path = "/statistics/jobs/executionType")
     public JobExecutionTypeStatistics getJobExecutionTypeStatistics() {
         return statisticManager.getJobExecutionTypeStatistics();
     }
     
     /**
      * Find job running statistics in the recent week.
+     *
      * @param since time span
      * @return collection of job running statistics in the recent week
      */
-    @GetMapping("/statistics/jobs/running")
-    public List<JobRunningStatistics> 
findJobRunningStatistics(@RequestParam(value = "since", required = false) final 
String since) {
+    @Mapping(method = Http.GET, path = "/statistics/jobs/running")
+    public List<JobRunningStatistics> findJobRunningStatistics(@Param(name = 
"since", source = ParamSource.QUERY, required = false) final String since) {
         if ("lastWeek".equals(since)) {
             return statisticManager.findJobRunningStatisticsWeekly();
         } else {
@@ -386,7 +407,7 @@ public final class CloudJobController {
      * Find job register statistics.
      * @return collection of job register statistics since online
      */
-    @GetMapping("/statistics/jobs/register")
+    @Mapping(method = Http.GET, path = "/statistics/jobs/register")
     public List<JobRegisterStatistics> findJobRegisterStatistics() {
         return statisticManager.findJobRegisterStatisticsSinceOnline();
     }
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudOperationController.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudOperationController.java
index a638a8a..85f4837 100755
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudOperationController.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudOperationController.java
@@ -20,25 +20,26 @@ package 
org.apache.shardingsphere.elasticjob.cloud.console.controller;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.gson.JsonParseException;
-import java.util.Collection;
-import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.MesosStateService;
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.ReconcileService;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.apache.shardingsphere.elasticjob.restful.Http;
+import org.apache.shardingsphere.elasticjob.restful.RestfulController;
+import org.apache.shardingsphere.elasticjob.restful.annotation.ContextPath;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Mapping;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Param;
+import org.apache.shardingsphere.elasticjob.restful.annotation.ParamSource;
+
+import java.util.Collection;
+import java.util.Map;
 
 /**
  * Cloud operation restful api.
  */
 @Slf4j
-@RestController
-@RequestMapping("/operate")
-public final class CloudOperationController {
+@ContextPath("/api/operate")
+public final class CloudOperationController implements RestfulController {
     
     private static ReconcileService reconcileService;
     
@@ -61,20 +62,26 @@ public final class CloudOperationController {
     
     /**
      * Explicit reconcile service.
+     *
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/reconcile/explicit")
-    public void explicitReconcile() {
+    @Mapping(method = Http.POST, path = "/reconcile/explicit")
+    public boolean explicitReconcile() {
         validReconcileInterval();
         reconcileService.explicitReconcile();
+        return true;
     }
     
     /**
      * Implicit reconcile service.
+     *
+     * @return <tt>true</tt> for operation finished.
      */
-    @PostMapping("/reconcile/implicit")
-    public void implicitReconcile() {
+    @Mapping(method = Http.POST, path = "/reconcile/implicit")
+    public boolean implicitReconcile() {
         validReconcileInterval();
         reconcileService.implicitReconcile();
+        return true;
     }
     
     private void validReconcileInterval() {
@@ -91,8 +98,8 @@ public final class CloudOperationController {
      * @return sandbox info
      * @throws JsonParseException parse json exception
      */
-    @GetMapping("/sandbox")
-    public Collection<Map<String, String>> sandbox(@RequestParam("appName") 
final String appName) throws JsonParseException {
+    @Mapping(method = Http.GET, path = "/sandbox")
+    public Collection<Map<String, String>> sandbox(@Param(name = "appName", 
source = ParamSource.QUERY) final String appName) throws JsonParseException {
         Preconditions.checkArgument(!Strings.isNullOrEmpty(appName), "Lack 
param 'appName'");
         return mesosStateService.sandbox(appName);
     }
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationResult.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationResult.java
deleted file mode 100644
index 6467a5a..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationResult.java
+++ /dev/null
@@ -1,35 +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.shardingsphere.elasticjob.cloud.console.security;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-
-/**
- * Authentication result.
- **/
-@Getter
-@Setter
-@RequiredArgsConstructor
-public final class AuthenticationResult {
-    
-    private final boolean success;
-    
-    private final boolean isGuest;
-}
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/UserAuthenticationService.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/UserAuthenticationService.java
deleted file mode 100644
index c9132db..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/UserAuthenticationService.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.shardingsphere.elasticjob.cloud.console.security;
-
-import lombok.Getter;
-import lombok.Setter;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * User authentication service.
- **/
-@Component
-@ConfigurationProperties(prefix = "auth")
-@Getter
-@Setter
-public class UserAuthenticationService {
-    
-    private String rootUsername;
-    
-    private String rootPassword;
-    
-    private String guestUsername;
-    
-    private String guestPassword;
-    
-    /**
-     * Check user.
-     *
-     * @param authorization authorization
-     * @return authorization result
-     */
-    public AuthenticationResult checkUser(final String authorization) {
-        if ((rootUsername + ":" + rootPassword).equals(authorization)) {
-            return new AuthenticationResult(true, false);
-        } else if ((guestUsername + ":" + 
guestPassword).equals(authorization)) {
-            return new AuthenticationResult(true, true);
-        } else {
-            return new AuthenticationResult(false, false);
-        }
-    }
-}
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/WwwAuthFilter.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/WwwAuthFilter.java
deleted file mode 100755
index a7a4a59..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/WwwAuthFilter.java
+++ /dev/null
@@ -1,89 +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.shardingsphere.elasticjob.cloud.console.security;
-
-import java.io.IOException;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.binary.Base64;
-
-/**
- * WWW auth filter.
- */
-@Slf4j
-public final class WwwAuthFilter implements Filter {
-    
-    private static final String AUTH_PREFIX = "Basic ";
-    
-    private static final String ROOT_IDENTIFY = "root";
-    
-    private static final String GUEST_IDENTIFY = "guest";
-    
-    @Setter
-    private UserAuthenticationService userAuthenticationService;
-    
-    @Override
-    public void init(final FilterConfig filterConfig) {
-    }
-    
-    @Override
-    public void doFilter(final ServletRequest request, final ServletResponse 
response, final FilterChain chain) throws IOException, ServletException {
-        HttpServletRequest httpRequest = (HttpServletRequest) request;
-        HttpServletResponse httpResponse = (HttpServletResponse) response;
-        String authorization = httpRequest.getHeader("authorization");
-        if (null != authorization && authorization.length() > 
AUTH_PREFIX.length()) {
-            authorization = new 
String(Base64.decodeBase64(authorization.substring(AUTH_PREFIX.length())));
-            AuthenticationResult authenticationResult = 
userAuthenticationService.checkUser(authorization);
-            if (authenticationResult.isSuccess()) {
-                authenticateSuccess(httpResponse, 
authenticationResult.isGuest());
-                chain.doFilter(httpRequest, httpResponse);
-            } else {
-                needAuthenticate(httpResponse);
-            }
-        } else {
-            needAuthenticate(httpResponse);
-        }
-    }
-    
-    private void authenticateSuccess(final HttpServletResponse response, final 
boolean isGuest) {
-        response.setStatus(200);
-        response.setHeader("Pragma", "No-cache");
-        response.setHeader("Cache-Control", "no-store");
-        response.setDateHeader("Expires", 0);
-        response.setHeader("identify", isGuest ? GUEST_IDENTIFY : 
ROOT_IDENTIFY);
-    }
-    
-    private void needAuthenticate(final HttpServletResponse response) {
-        response.setStatus(401);
-        response.setHeader("Cache-Control", "no-store");
-        response.setDateHeader("Expires", 0);
-        response.setHeader("WWW-authenticate", AUTH_PREFIX + "Realm=\"Elastic 
Job Console Auth\"");
-    }
-    
-    @Override
-    public void destroy() {
-    }
-}
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/application.properties
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/META-INF/services/org.apache.shardingsphere.elasticjob.restful.serializer.ResponseBodySerializer
similarity index 89%
rename from 
elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/application.properties
rename to 
elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/META-INF/services/org.apache.shardingsphere.elasticjob.restful.serializer.ResponseBodySerializer
index b750ea0..d640130 100644
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/application.properties
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/META-INF/services/org.apache.shardingsphere.elasticjob.restful.serializer.ResponseBodySerializer
@@ -14,5 +14,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# Default web server port
-server.port=8899
+
+org.apache.shardingsphere.elasticjob.cloud.console.config.serializer.JsonResponseBodySerializer
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/AbstractCloudControllerTest.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/AbstractCloudControllerTest.java
index 28cfd78..882867c 100644
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/AbstractCloudControllerTest.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/AbstractCloudControllerTest.java
@@ -25,16 +25,18 @@ import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.env.RestfulServerCon
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.FacadeService;
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.MesosStateService;
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.ReconcileService;
-import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.master.MesosMasterServerMockConfiguration;
-import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.slave.MesosSlaveServerMockConfiguration;
+import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.master.MesosMasterServerMock;
+import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.slave.MesosSlaveServerMock;
 import 
org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerManager;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.apache.shardingsphere.elasticjob.restful.NettyRestfulService;
+import 
org.apache.shardingsphere.elasticjob.restful.NettyRestfulServiceConfiguration;
+import org.apache.shardingsphere.elasticjob.restful.RestfulService;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
-import org.springframework.context.ConfigurableApplicationContext;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -50,12 +52,12 @@ public abstract class AbstractCloudControllerTest {
     
     private static ConsoleBootstrap consoleBootstrap;
     
-    private static ConfigurableApplicationContext masterServer;
+    private static RestfulService masterServer;
     
-    private static ConfigurableApplicationContext slaveServer;
+    private static RestfulService slaveServer;
     
     @BeforeClass
-    public static void setUpClass() throws Exception {
+    public static void setUpClass() {
         initRestfulServer();
         initMesosServer();
     }
@@ -73,19 +75,21 @@ public abstract class AbstractCloudControllerTest {
     
     private static void initMesosServer() {
         MesosStateService.register("127.0.0.1", 9050);
-        ConsoleBootstrap.ConsoleApplication.setPort(9050);
-        ConsoleBootstrap.ConsoleApplication.setExtraSources(new 
Class[]{MesosMasterServerMockConfiguration.class});
-        masterServer = ConsoleBootstrap.ConsoleApplication.start();
-        ConsoleBootstrap.ConsoleApplication.setPort(9051);
-        ConsoleBootstrap.ConsoleApplication.setExtraSources(new 
Class[]{MesosSlaveServerMockConfiguration.class});
-        slaveServer = ConsoleBootstrap.ConsoleApplication.start();
+        NettyRestfulServiceConfiguration masterServerConfiguration = new 
NettyRestfulServiceConfiguration(9050);
+        masterServerConfiguration.addControllerInstance(new 
MesosMasterServerMock());
+        masterServer = new NettyRestfulService(masterServerConfiguration);
+        masterServer.startup();
+        NettyRestfulServiceConfiguration slaveServerConfiguration = new 
NettyRestfulServiceConfiguration(9051);
+        slaveServerConfiguration.addControllerInstance(new 
MesosSlaveServerMock());
+        slaveServer = new NettyRestfulService(slaveServerConfiguration);
+        slaveServer.startup();
     }
     
     @AfterClass
     public static void tearDown() {
         consoleBootstrap.stop();
-        masterServer.stop();
-        slaveServer.stop();
+        masterServer.shutdown();
+        slaveServer.shutdown();
         MesosStateService.deregister();
     }
     
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobControllerTest.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobControllerTest.java
index d635240..ba5ad70 100644
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobControllerTest.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudJobControllerTest.java
@@ -189,7 +189,10 @@ public class CloudJobControllerTest extends 
AbstractCloudControllerTest {
     @Test
     public void assertFindJobExecutionEventsWhenNotConfigRDB() {
         ReflectionUtils.setStaticFieldValue(CloudJobController.class, 
"jobEventRdbSearch", null);
-        
assertThat(HttpTestUtil.get("http://127.0.0.1:19000/api/job/events/executions";),
 is(GsonFactory.getGson().toJson(new JobEventRdbSearch.Result<>(0,
+        Map<String, String> query = new HashMap<>();
+        query.put("per_page", "10");
+        query.put("page", "1");
+        
assertThat(HttpTestUtil.get("http://127.0.0.1:19000/api/job/events/executions";, 
query), is(GsonFactory.getGson().toJson(new JobEventRdbSearch.Result<>(0,
                 Collections.<JobExecutionEvent>emptyList()))));
     }
     
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMock.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMock.java
index c9a53fc..f794e65 100755
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMock.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMock.java
@@ -17,23 +17,18 @@
 
 package 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.master;
 
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.apache.shardingsphere.elasticjob.restful.Http;
+import org.apache.shardingsphere.elasticjob.restful.RestfulController;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Mapping;
 
-@Controller
-@RequestMapping("/")
-public class MesosMasterServerMock {
+public class MesosMasterServerMock implements RestfulController {
     
     /**
      * Check master server state.
      *
      * @return json object
      */
-    @ResponseBody
-    @GetMapping(value = "/state", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Mapping(method = Http.GET, path = "/state")
     public String state() {
         return "{\"version\":\"1.1.0\",\"build_date\":\"2017-02-27 
10:51:31\",\"build_time\":1488163891.0,\"build_user\":\"user\",\"start_time\""
                 + 
":1488179758.62289,\"elected_time\":1488179758.69795,\"id\":\"d8701508-41b7-471e-9b32-61cf824a660d\",\"pid\":\"[email protected]:9050\",\"hostname\":\"127.0.0.1\","
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMockConfiguration.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMockConfiguration.java
deleted file mode 100644
index be34e49..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/master/MesosMasterServerMockConfiguration.java
+++ /dev/null
@@ -1,38 +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.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.master;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Mesos master server configuration.
- **/
-@Configuration
-public class MesosMasterServerMockConfiguration {
-    
-    /**
-     * inject mesos master server mock.
-     *
-     * @return mesos master server mock.
-     */
-    @Bean
-    public MesosMasterServerMock mesosMasterServerMock() {
-        return new MesosMasterServerMock();
-    }
-}
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMock.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMock.java
index 9de423d..800ed86 100755
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMock.java
+++ 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMock.java
@@ -17,23 +17,18 @@
 
 package 
org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.slave;
 
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.apache.shardingsphere.elasticjob.restful.Http;
+import org.apache.shardingsphere.elasticjob.restful.RestfulController;
+import org.apache.shardingsphere.elasticjob.restful.annotation.Mapping;
 
-@Controller
-@RequestMapping("/")
-public class MesosSlaveServerMock {
+public class MesosSlaveServerMock implements RestfulController {
     
     /**
      * Check slave server state.
      *
      * @return json object
      */
-    @ResponseBody
-    @GetMapping(value = "/state", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Mapping(method = Http.GET, path = "/state")
     public String state() {
         return "{\"version\":\"1.1.0\",\"build_date\":\"2017-02-27 
10:51:31\",\"build_time\":1488163891.0,\"build_user\":\"gaohon"
                 + 
"gtao\",\"start_time\":1488179767.60204,\"id\":\"d8701508-41b7-471e-9b32-61cf824a660d-S0\",\"pid\":\"slave(1)@"
diff --git 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMockConfiguration.java
 
b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMockConfiguration.java
deleted file mode 100644
index 4db6590..0000000
--- 
a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/fixture/slave/MesosSlaveServerMockConfiguration.java
+++ /dev/null
@@ -1,38 +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.shardingsphere.elasticjob.cloud.scheduler.mesos.fixture.slave;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Mesos slave server configuration.
- **/
-@Configuration
-public class MesosSlaveServerMockConfiguration {
-    
-    /**
-     * inject mesos slave server mock.
-     *
-     * @return mesos slave server mock
-     */
-    @Bean
-    public MesosSlaveServerMock mesosSlaveServerMock() {
-        return new MesosSlaveServerMock();
-    }
-}

Reply via email to