You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by me...@apache.org on 2020/07/21 01:43:58 UTC

[shardingsphere-elasticjob-ui] 02/21: UI refactor

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

menghaoran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob-ui.git

commit 61f0d2361dabca697d232ee041b6363b34d7245e
Author: menghaoranss <lo...@163.com>
AuthorDate: Thu Jul 16 12:37:31 2020 +0800

    UI refactor
---
 shardingsphere-elasticjob-ui-backend/pom.xml       |  93 ++++++++-
 .../shardingsphere/elasticjob/ui/Bootstrap.java    |  39 ++++
 .../ui/config/DynamicDataSourceConfig.java         | 116 +++++++++++
 .../elasticjob/ui/config/FilterConfiguration.java  |  73 +++++++
 .../config/advice/ConsoleRestControllerAdvice.java |  67 +++++++
 .../ui/dao/search/JobExecutionLogRepository.java   |  25 +++
 .../ui/dao/search/JobStatusTraceLogRepository.java |  25 +++
 .../JobRegisterStatisticsRepository.java           |  43 ++++
 .../statistics/JobRunningStatisticsRepository.java |  43 ++++
 .../ui/dao/statistics/StatisticInterval.java       |  37 ++++
 .../statistics/TaskResultStatisticsRepository.java |  55 ++++++
 .../TaskRunningStatisticsRepository.java           |  43 ++++
 .../type/job/JobExecutionTypeStatistics.java       |  33 ++++
 .../dao/statistics/type/job/JobTypeStatistics.java |  35 ++++
 .../elasticjob/ui/domain/DataSourceFactory.java    |  41 ++++
 .../elasticjob/ui/domain/EventTraceDataSource.java |  52 +++++
 .../domain/EventTraceDataSourceConfiguration.java  |  66 +++++++
 .../domain/EventTraceDataSourceConfigurations.java |  37 ++++
 .../ui/domain/EventTraceDataSourceFactory.java     |  66 +++++++
 .../elasticjob/ui/domain/GlobalConfiguration.java  |  39 ++++
 .../elasticjob/ui/domain/JobExecutionLog.java      |  86 ++++++++
 .../ui/domain/JobRegisterStatistics.java           |  59 ++++++
 .../elasticjob/ui/domain/JobRunningStatistics.java |  59 ++++++
 .../elasticjob/ui/domain/JobStatusTraceLog.java    |  86 ++++++++
 .../ui/domain/RegistryCenterConfiguration.java     |  56 ++++++
 .../ui/domain/RegistryCenterConfigurations.java    |  37 ++++
 .../elasticjob/ui/domain/TaskResultStatistics.java |  72 +++++++
 .../ui/domain/TaskRunningStatistics.java           |  59 ++++++
 .../elasticjob/ui/dto/request/BasePageRequest.java |  60 ++++++
 .../dto/request/FindJobExecutionEventsRequest.java |  76 ++++++++
 .../request/FindJobStatusTraceEventsRequest.java   |  63 ++++++
 .../ui/dto/response/BasePageResponse.java          |  65 ++++++
 .../ui/exception/JobConsoleException.java          |  45 +++++
 .../ui/repository/ConfigurationsXmlRepository.java |  26 +++
 .../elasticjob/ui/repository/XmlRepository.java    |  40 ++++
 .../repository/impl/AbstractXmlRepositoryImpl.java |  80 ++++++++
 .../impl/ConfigurationsXmlRepositoryImpl.java      |  31 +++
 .../ui/security/AuthenticationFilter.java          |  99 ++++++++++
 .../ui/security/AuthenticationResult.java          |  39 ++++
 .../elasticjob/ui/security/UserAccount.java        |  33 ++++
 .../ui/security/UserAuthenticationService.java     |  74 +++++++
 .../EventTraceDataSourceConfigurationService.java  |  75 +++++++
 .../ui/service/EventTraceHistoryService.java       |  46 +++++
 .../elasticjob/ui/service/JobAPIService.java       |  70 +++++++
 .../RegistryCenterConfigurationService.java        |  75 +++++++
 ...entTraceDataSourceConfigurationServiceImpl.java | 124 ++++++++++++
 .../service/impl/EventTraceHistoryServiceImpl.java | 132 +++++++++++++
 .../ui/service/impl/JobAPIServiceImpl.java         |  73 +++++++
 .../RegistryCenterConfigurationServiceImpl.java    | 113 +++++++++++
 .../elasticjob/ui/util/BeanUtils.java              |  56 ++++++
 .../elasticjob/ui/util/HomeFolderUtils.java        |  58 ++++++
 .../SessionEventTraceDataSourceConfiguration.java  |  42 ++++
 .../util/SessionRegistryCenterConfiguration.java   |  49 +++++
 .../controller/EventTraceDataSourceController.java | 138 +++++++++++++
 .../controller/EventTraceHistoryController.java    |  67 +++++++
 .../ui/web/controller/JobConfigController.java     |  77 ++++++++
 .../ui/web/controller/JobOperationController.java  | 139 +++++++++++++
 .../web/controller/RegistryCenterController.java   | 124 ++++++++++++
 .../web/controller/ServerOperationController.java  | 162 +++++++++++++++
 .../elasticjob/ui/web/filter/CORSFilter.java       |  60 ++++++
 .../elasticjob/ui/web/response/ResponseResult.java |  45 +++++
 .../ui/web/response/ResponseResultUtil.java        | 120 ++++++++++++
 .../src/main/resources/application.properties      |  15 +-
 .../ui/dao/search/RDBJobEventSearchTest.java       | 217 +++++++++++++++++++++
 .../search/RDBJobEventSearchTestConfiguration.java |  70 +++++++
 .../statistics/rdb/RDBStatisticRepositoryTest.java | 175 +++++++++++++++++
 .../elasticjob/ui/util/HomeFolderUtilsTest.java    |  35 ++++
 .../config/index.js                                |   2 +-
 .../src/lang/en-US.js                              |  37 ++--
 .../src/lang/zh-CN.js                              |  37 ++--
 70 files changed, 4672 insertions(+), 34 deletions(-)

diff --git a/shardingsphere-elasticjob-ui-backend/pom.xml b/shardingsphere-elasticjob-ui-backend/pom.xml
index 302129e..ac95197 100644
--- a/shardingsphere-elasticjob-ui-backend/pom.xml
+++ b/shardingsphere-elasticjob-ui-backend/pom.xml
@@ -25,9 +25,98 @@
     </parent>
     <artifactId>shardingsphere-elasticjob-ui-backend</artifactId>
     <name>${project.artifactId}</name>
-    
+
+    <properties>
+        <spring-boot.version>2.3.1.RELEASE</spring-boot.version>
+        <springframework.version>5.2.7.RELEASE</springframework.version>
+    </properties>
+
     <dependencies>
-        
+        <dependency>
+            <groupId>org.apache.shardingsphere.elasticjob</groupId>
+            <artifactId>elasticjob-lite-lifecycle</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>${spring-boot.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </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>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-dbcp2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-dbcp</groupId>
+            <artifactId>commons-dbcp</artifactId>
+            <version>1.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
     
     <build>
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/Bootstrap.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/Bootstrap.java
new file mode 100644
index 0000000..3af08d0
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/Bootstrap.java
@@ -0,0 +1,39 @@
+/*
+ * 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.ui;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Console bootstrap.
+ */
+@SpringBootApplication
+public class Bootstrap {
+    
+    /**
+     * Startup RESTful server.
+     *
+     * @param args arguments
+     */
+    //CHECKSTYLE:OFF
+    public static void main(final String[] args) {
+    //CHECKSTYLE:ON
+        SpringApplication.run(Bootstrap.class, args);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/DynamicDataSourceConfig.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/DynamicDataSourceConfig.java
new file mode 100644
index 0000000..8e87862
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/DynamicDataSourceConfig.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ui.config;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.env.Environment;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Dynamic datasource config.
+ */
+@Configuration
+public class DynamicDataSourceConfig {
+    
+    public static final String DRIVER_CLASS_NAME = "spring.datasource.default.driver-class-name";
+    
+    public static final String DATASOURCE_URL = "spring.datasource.default.url";
+    
+    public static final String DATASOURCE_USERNAME = "spring.datasource.default.username";
+    
+    public static final String DATASOURCE_PASSWORD = "spring.datasource.default.password";
+    
+    public static final String DEFAULT_DATASOURCE_NAME = "default";
+    
+    /**
+     * Declare dynamicDataSource instead of default dataSource.
+     * @param environment spring environment
+     * @return A subClass of AbstractRoutingDataSource
+     */
+    @Bean(name = "dynamicDataSource")
+    @Primary
+    public DynamicDataSource dynamicDataSource(final Environment environment) {
+        DataSource defaultDataSource = createDefaultDataSource(environment);
+        DynamicDataSource dynamicDataSource = new DynamicDataSource();
+        dynamicDataSource.addDataSource(DEFAULT_DATASOURCE_NAME, defaultDataSource);
+        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
+        return dynamicDataSource;
+    }
+    
+    private DataSource createDefaultDataSource(final Environment environment) {
+        String driverName = environment.getProperty(DRIVER_CLASS_NAME);
+        String url = environment.getProperty(DATASOURCE_URL);
+        String username = environment.getProperty(DATASOURCE_USERNAME);
+        String password = environment.getProperty(DATASOURCE_PASSWORD);
+        return DataSourceBuilder.create().driverClassName(driverName).type(BasicDataSource.class).url(url)
+            .username(username).password(password).build();
+    }
+    
+    public static class DynamicDataSource extends AbstractRoutingDataSource {
+        
+        private final Map<Object, Object> dataSourceMap = new HashMap<>(10);
+        
+        @Override
+        protected Object determineCurrentLookupKey() {
+            return DynamicDataSourceContextHolder.getDataSourceName();
+        }
+        
+        /**
+         * Add a data source.
+         * 
+         * @param dataSourceName data source name
+         * @param dataSource data source
+         */
+        public void addDataSource(final String dataSourceName, final DataSource dataSource) {
+            dataSourceMap.put(dataSourceName, dataSource);
+            setTargetDataSources(dataSourceMap);
+            afterPropertiesSet();
+        }
+    }
+    
+    public static class DynamicDataSourceContextHolder {
+        
+        private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
+        
+        /**
+         * Get the specify dataSource.
+         * 
+         * @return data source name
+         */
+        public static String getDataSourceName() {
+            return CONTEXT_HOLDER.get();
+        }
+        
+        /**
+         * Specify a dataSource.
+         * 
+         * @param dataSourceName data source name
+         */
+        public static void setDataSourceName(final String dataSourceName) {
+            CONTEXT_HOLDER.set(dataSourceName);
+        }
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/FilterConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/FilterConfiguration.java
new file mode 100644
index 0000000..32f45b9
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/FilterConfiguration.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ui.config;
+
+import org.apache.shardingsphere.elasticjob.ui.security.AuthenticationFilter;
+import org.apache.shardingsphere.elasticjob.ui.security.UserAuthenticationService;
+import org.apache.shardingsphere.elasticjob.ui.web.filter.CORSFilter;
+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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Web filter configuration.
+ */
+@Configuration
+public class FilterConfiguration {
+    
+    @Autowired
+    private UserAuthenticationService userAuthenticationService;
+    
+    /**
+     * Register the CORS filter.
+     *
+     * @return filter registration bean
+     */
+    @Bean
+    public FilterRegistrationBean corsFilter() {
+        CORSFilter corsFilter = new CORSFilter();
+        FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
+        filterRegBean.setFilter(corsFilter);
+        List<String> urlPatterns = new ArrayList<>();
+        urlPatterns.add("/api/*");
+        filterRegBean.setUrlPatterns(urlPatterns);
+        return filterRegBean;
+    }
+    
+    /**
+     * Register the authentication filter.
+     *
+     * @return filter registration bean
+     */
+    @Bean
+    public FilterRegistrationBean authenticationFilter() {
+        AuthenticationFilter authenticationFilter = new AuthenticationFilter();
+        authenticationFilter.setUserAuthenticationService(userAuthenticationService);
+        FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
+        filterRegBean.setFilter(authenticationFilter);
+        List<String> urlPatterns = new ArrayList<>();
+        urlPatterns.add("/api/*");
+        filterRegBean.setUrlPatterns(urlPatterns);
+        return filterRegBean;
+    }
+    
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/advice/ConsoleRestControllerAdvice.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/advice/ConsoleRestControllerAdvice.java
new file mode 100644
index 0000000..e3e6898
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/config/advice/ConsoleRestControllerAdvice.java
@@ -0,0 +1,67 @@
+/*
+ * 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.ui.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) {
+        log.error("CONSOLE ERROR", ex);
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ExceptionUtils.transform(ex));
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/search/JobExecutionLogRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/search/JobExecutionLogRepository.java
new file mode 100644
index 0000000..c27d2c1
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/search/JobExecutionLogRepository.java
@@ -0,0 +1,25 @@
+/*
+ * 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.ui.dao.search;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.JobExecutionLog;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface JobExecutionLogRepository extends JpaRepository<JobExecutionLog, String>, JpaSpecificationExecutor<JobExecutionLog> {
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/search/JobStatusTraceLogRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/search/JobStatusTraceLogRepository.java
new file mode 100644
index 0000000..ee451f0
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/search/JobStatusTraceLogRepository.java
@@ -0,0 +1,25 @@
+/*
+ * 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.ui.dao.search;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.JobStatusTraceLog;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface JobStatusTraceLogRepository extends JpaRepository<JobStatusTraceLog, String>, JpaSpecificationExecutor<JobStatusTraceLog> {
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/JobRegisterStatisticsRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/JobRegisterStatisticsRepository.java
new file mode 100644
index 0000000..393bd89
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/JobRegisterStatisticsRepository.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ui.dao.statistics;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.JobRegisterStatistics;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Job register statistics repository.
+ */
+@Repository
+public interface JobRegisterStatisticsRepository extends JpaRepository<JobRegisterStatistics, Long> {
+    
+    /**
+     * Find job register statistics.
+     *
+     * @param fromTime from date to statistics
+     * @return job register statistics
+     */
+    @Query("FROM JobRegisterStatistics WHERE statisticsTime >= :fromTime")
+    List<JobRegisterStatistics> findJobRegisterStatistics(@Param("fromTime") Date fromTime);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/JobRunningStatisticsRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/JobRunningStatisticsRepository.java
new file mode 100644
index 0000000..a5b8a1d
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/JobRunningStatisticsRepository.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ui.dao.statistics;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.JobRunningStatistics;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Job running statistics repository.
+ */
+@Repository
+public interface JobRunningStatisticsRepository extends JpaRepository<JobRunningStatistics, Long> {
+    
+    /**
+     * Find job running statistics.
+     *
+     * @param fromTime from date to statistics
+     * @return job running statistics
+     */
+    @Query("FROM JobRunningStatistics WHERE statisticsTime >= :fromTime")
+    List<JobRunningStatistics> findJobRunningStatistics(@Param("fromTime") Date fromTime);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/StatisticInterval.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/StatisticInterval.java
new file mode 100644
index 0000000..0322a03
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/StatisticInterval.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ui.dao.statistics;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Statistic interval.
+ */
+@Getter
+@RequiredArgsConstructor
+public enum StatisticInterval {
+    
+    MINUTE("0 * * * * ?"),
+    
+    HOUR("0 0 * * * ?"), 
+    
+    DAY("0 0 0 * * ?");
+    
+    private final String cron;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/TaskResultStatisticsRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/TaskResultStatisticsRepository.java
new file mode 100644
index 0000000..248f027
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/TaskResultStatisticsRepository.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ui.dao.statistics;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.TaskResultStatistics;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Task result statistics repository.
+ */
+@Repository
+public interface TaskResultStatisticsRepository extends JpaRepository<TaskResultStatistics, Long> {
+    
+    /**
+     * Find task result statistics.
+     *
+     * @param fromTime from date to statistics
+     * @param statisticInterval statistic interval
+     * @return task result statistics
+     */
+    @Query("FROM TaskResultStatistics WHERE statisticInterval = :statisticInterval AND statisticsTime >= :fromTime ORDER BY id ASC")
+    List<TaskResultStatistics> findTaskResultStatistics(@Param("fromTime") Date fromTime, @Param("statisticInterval") String statisticInterval);
+    
+    /**
+     * Get summed task result statistics.
+     *
+     * @param fromTime from date to statistics
+     * @param statisticInterval statistic interval
+     * @return summed task result statistics
+     */
+    @Query("SELECT new TaskResultStatistics(SUM(successCount), SUM(failedCount)) FROM TaskResultStatistics WHERE "
+        + "statisticInterval = :statisticInterval AND statisticsTime >= :fromTime")
+    TaskResultStatistics getSummedTaskResultStatistics(@Param("fromTime") Date fromTime, @Param("statisticInterval") String statisticInterval);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/TaskRunningStatisticsRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/TaskRunningStatisticsRepository.java
new file mode 100644
index 0000000..328028c
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/TaskRunningStatisticsRepository.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ui.dao.statistics;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.TaskRunningStatistics;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Task running statistics repository.
+ */
+@Repository
+public interface TaskRunningStatisticsRepository extends JpaRepository<TaskRunningStatistics, Long> {
+    
+    /**
+     * Find task running statistics.
+     *
+     * @param fromTime from date to statistics
+     * @return Task running statistics
+     */
+    @Query("FROM TaskRunningStatistics where statisticsTime >= :fromTime")
+    List<TaskRunningStatistics> findTaskRunningStatistics(@Param("fromTime") Date fromTime);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/type/job/JobExecutionTypeStatistics.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/type/job/JobExecutionTypeStatistics.java
new file mode 100644
index 0000000..8aace8d
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/type/job/JobExecutionTypeStatistics.java
@@ -0,0 +1,33 @@
+/*
+ * 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.ui.dao.statistics.type.job;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Job execution type statistics.
+ */
+@Getter
+@AllArgsConstructor
+public final class JobExecutionTypeStatistics {
+    
+    private int transientJobCount;
+    
+    private int daemonJobCount;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/type/job/JobTypeStatistics.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/type/job/JobTypeStatistics.java
new file mode 100644
index 0000000..1a9a00c
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/type/job/JobTypeStatistics.java
@@ -0,0 +1,35 @@
+/*
+ * 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.ui.dao.statistics.type.job;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Job type statistics.
+ */
+@Getter
+@AllArgsConstructor
+public final class JobTypeStatistics {
+    
+    private int scriptJobCount;
+    
+    private int simpleJobCount;
+    
+    private int dataflowJobCount;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/DataSourceFactory.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/DataSourceFactory.java
new file mode 100644
index 0000000..d7abd7b
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/DataSourceFactory.java
@@ -0,0 +1,41 @@
+/*
+ * 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.ui.domain;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+
+import javax.sql.DataSource;
+
+/**
+ * Dynamic data source factory.
+ */
+public final class DataSourceFactory {
+    
+    /**
+     * Create a DataSource.
+     * @param config event trace data source config
+     * @return data source
+     */
+    public static DataSource createDataSource(final EventTraceDataSourceConfiguration config) {
+        // Determine whether the data source is valid.
+        new EventTraceDataSource(config).init();
+        return DataSourceBuilder.create().type(BasicDataSource.class).driverClassName(config.getDriver()).url(config.getUrl())
+            .username(config.getUsername()).password(config.getPassword()).build();
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSource.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSource.java
new file mode 100644
index 0000000..bc0cad0
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSource.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ui.domain;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Event tracing data source.
+ */
+@Slf4j
+public final class EventTraceDataSource {
+    
+    @Getter(AccessLevel.PROTECTED)
+    private EventTraceDataSourceConfiguration eventTraceDataSourceConfiguration;
+    
+    public EventTraceDataSource(final EventTraceDataSourceConfiguration eventTraceDataSourceConfiguration) {
+        this.eventTraceDataSourceConfiguration = eventTraceDataSourceConfiguration;
+    }
+    
+    /**
+     * Initialize data source.
+     */
+    public void init() {
+        log.debug("Elastic job: data source init, connection url is: {}.", eventTraceDataSourceConfiguration.getUrl());
+        try {
+            Class.forName(eventTraceDataSourceConfiguration.getDriver());
+            DriverManager.getConnection(eventTraceDataSourceConfiguration.getUrl(), eventTraceDataSourceConfiguration.getUsername(), eventTraceDataSourceConfiguration.getPassword());
+        } catch (final ClassNotFoundException | SQLException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceConfiguration.java
new file mode 100644
index 0000000..dc683f7
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceConfiguration.java
@@ -0,0 +1,66 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+
+/**
+ * Event trace data source configuration.
+ */
+@NoArgsConstructor
+@Getter
+@Setter
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public final class EventTraceDataSourceConfiguration implements Serializable {
+    
+    private static final long serialVersionUID = -5996257770767863699L;
+    
+    @XmlAttribute(required = true)
+    private String name;
+    
+    @XmlAttribute(required = true)
+    private String driver;
+    
+    @XmlAttribute
+    private String url;
+    
+    @XmlAttribute
+    private String username;
+    
+    @XmlAttribute
+    private String password;
+    
+    @XmlAttribute
+    private boolean activated;
+    
+    public EventTraceDataSourceConfiguration(final String driver, final String url, final String username, final String password) {
+        this.driver = driver;
+        this.url = url;
+        this.username = username;
+        this.password = password;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceConfigurations.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceConfigurations.java
new file mode 100644
index 0000000..9250f7f
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceConfigurations.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Getter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Event trace data source configurations.
+ */
+@Getter
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public final class EventTraceDataSourceConfigurations {
+    
+    private Set<EventTraceDataSourceConfiguration> eventTraceDataSourceConfiguration = new LinkedHashSet<>();
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceFactory.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceFactory.java
new file mode 100644
index 0000000..36fc116
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/EventTraceDataSourceFactory.java
@@ -0,0 +1,66 @@
+/*
+ * 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.ui.domain;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Event trace data source factory.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class EventTraceDataSourceFactory {
+    
+    private static final ConcurrentHashMap<HashCode, EventTraceDataSource> DATA_SOURCE_REGISTRY = new ConcurrentHashMap<>();
+    
+    /**
+     * Create event trace data source.
+     * 
+     * @param driverClassName database driver class name
+     * @param url database URL
+     * @param username database username
+     * @param password database password
+     * @return event trace data source
+     */
+    public static EventTraceDataSource createEventTraceDataSource(final String driverClassName, final String url, final String username, final String password) {
+        Hasher hasher = Hashing.sha256().newHasher().putString(driverClassName, Charsets.UTF_8).putString(url, Charsets.UTF_8);
+        if (!Strings.isNullOrEmpty(username)) {
+            hasher.putString(username, Charsets.UTF_8);
+        }
+        if (null != password) {
+            hasher.putString(password, Charsets.UTF_8);
+        }
+        HashCode hashCode = hasher.hash();
+        EventTraceDataSource result = DATA_SOURCE_REGISTRY.get(hashCode);
+        if (null != result) {
+            return result;
+        }
+        EventTraceDataSourceConfiguration eventTraceDataSourceConfiguration = new EventTraceDataSourceConfiguration(driverClassName, url, username, password);
+        result = new EventTraceDataSource(eventTraceDataSourceConfiguration);
+        result.init();
+        DATA_SOURCE_REGISTRY.put(hashCode, result);
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/GlobalConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/GlobalConfiguration.java
new file mode 100644
index 0000000..273a90d
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/GlobalConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Global configuration.
+ */
+@Getter
+@Setter
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public final class GlobalConfiguration {
+    
+    private RegistryCenterConfigurations registryCenterConfigurations;
+    
+    private EventTraceDataSourceConfigurations eventTraceDataSourceConfigurations;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobExecutionLog.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobExecutionLog.java
new file mode 100644
index 0000000..ce98008
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobExecutionLog.java
@@ -0,0 +1,86 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Data;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+@Data
+@Entity(name = "JOB_EXECUTION_LOG")
+public class JobExecutionLog {
+    
+    @Id
+    private String id;
+    
+    @Column(name = "job_name")
+    private String jobName;
+    
+    @Column(name = "task_id")
+    private String taskId;
+    
+    @Column(name = "hostname")
+    private String hostname;
+    
+    @Column(name = "ip")
+    private String ip;
+    
+    @Column(name = "sharding_item")
+    private Integer shardingItem;
+    
+    @Column(name = "execution_source")
+    private String executionSource;
+    
+    @Column(name = "failure_cause")
+    private String failureCause;
+    
+    @Column(name = "is_success")
+    private Boolean isSuccess;
+    
+    @Column(name = "start_time")
+    private Date startTime;
+    
+    @Column(name = "complete_time")
+    private Date completeTime;
+    
+    /**
+     * JobExecutionLog convert to JobExecutionEvent.
+     *
+     * @return JobExecutionEvent entity
+     */
+    public JobExecutionEvent toJobExecutionEvent() {
+        return new JobExecutionEvent(
+                id,
+                hostname,
+                ip,
+                taskId,
+                jobName,
+                JobExecutionEvent.ExecutionSource.valueOf(executionSource),
+                shardingItem,
+                startTime,
+                completeTime,
+                isSuccess,
+                failureCause
+        );
+    }
+    
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobRegisterStatistics.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobRegisterStatistics.java
new file mode 100644
index 0000000..62f3713
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobRegisterStatistics.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ui.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/**
+ * Job register statistics.
+ */
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "JOB_REGISTER_STATISTICS")
+public final class JobRegisterStatistics {
+    
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Column(name = "registered_count", length = 11)
+    private Integer registeredCount;
+    
+    @Column(name = "statistics_time", nullable = false)
+    private Date statisticsTime;
+    
+    @Column(name = "creation_time", nullable = false)
+    private Date creationTime = new Date();
+    
+    public JobRegisterStatistics(final Integer registeredCount, final Date statisticsTime) {
+        this.registeredCount = registeredCount;
+        this.statisticsTime = statisticsTime;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobRunningStatistics.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobRunningStatistics.java
new file mode 100644
index 0000000..e8e5eea
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobRunningStatistics.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ui.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/**
+ * Job running statistics.
+ */
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "JOB_RUNNING_STATISTICS")
+public final class JobRunningStatistics {
+    
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Column(name = "running_count", length = 11)
+    private Integer runningCount;
+    
+    @Column(name = "statistics_time", nullable = false)
+    private Date statisticsTime;
+    
+    @Column(name = "creation_time", nullable = false)
+    private Date creationTime = new Date();
+    
+    public JobRunningStatistics(final Integer runningCount, final Date statisticsTime) {
+        this.runningCount = runningCount;
+        this.statisticsTime = statisticsTime;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobStatusTraceLog.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobStatusTraceLog.java
new file mode 100644
index 0000000..7803e09
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/JobStatusTraceLog.java
@@ -0,0 +1,86 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Data;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+@Data
+@Entity(name = "JOB_STATUS_TRACE_LOG")
+public class JobStatusTraceLog {
+    
+    @Id
+    private String id;
+    
+    @Column(name = "job_name")
+    private String jobName;
+    
+    @Column(name = "original_task_id")
+    private String originalTaskId;
+    
+    @Column(name = "task_id")
+    private String taskId;
+    
+    @Column(name = "slave_id")
+    private String slaveId;
+    
+    @Column(name = "source")
+    private String source;
+    
+    @Column(name = "execution_type")
+    private String executionType;
+    
+    @Column(name = "sharding_item")
+    private String shardingItem;
+    
+    @Column(name = "state")
+    private String state;
+    
+    @Column(name = "message")
+    private String message;
+    
+    @Column(name = "creation_time")
+    private Date creationTime;
+    
+    /**
+     * JobStatusTraceLog convert to JobStatusTraceEvent.
+     *
+     * @return JobStatusTraceEvent entity
+     */
+    public JobStatusTraceEvent toJobStatusTraceEvent() {
+        return new JobStatusTraceEvent(
+                id,
+                jobName,
+                originalTaskId,
+                taskId,
+                slaveId,
+                JobStatusTraceEvent.Source.valueOf(source),
+                executionType,
+                shardingItem,
+                JobStatusTraceEvent.State.valueOf(state),
+                message,
+                creationTime
+        );
+    }
+    
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/RegistryCenterConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/RegistryCenterConfiguration.java
new file mode 100644
index 0000000..6f46434
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/RegistryCenterConfiguration.java
@@ -0,0 +1,56 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+
+/**
+ * Registry center configuration.
+ */
+@Getter
+@Setter
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+@NoArgsConstructor
+public final class RegistryCenterConfiguration implements Serializable {
+    
+    private static final long serialVersionUID = -5996257770767863699L;
+    
+    @XmlAttribute(required = true)
+    private String name;
+    
+    @XmlAttribute(required = true)
+    private String zkAddressList;
+    
+    @XmlAttribute
+    private String namespace;
+    
+    @XmlAttribute
+    private String digest;
+    
+    @XmlAttribute
+    private boolean activated;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/RegistryCenterConfigurations.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/RegistryCenterConfigurations.java
new file mode 100644
index 0000000..403d29f
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/RegistryCenterConfigurations.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ui.domain;
+
+import lombok.Getter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Registry center configurations.
+ */
+@Getter
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public final class RegistryCenterConfigurations {
+    
+    private Set<RegistryCenterConfiguration> registryCenterConfiguration = new LinkedHashSet<>();
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/TaskResultStatistics.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/TaskResultStatistics.java
new file mode 100644
index 0000000..e0006d8
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/TaskResultStatistics.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.ui.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/**
+ * Task result statistics.
+ */
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "TASK_RESULT_STATISTICS")
+public final class TaskResultStatistics {
+    
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Column(name = "success_count", length = 11)
+    private Long successCount;
+    
+    @Column(name = "failed_count", length = 11)
+    private Long failedCount;
+    
+    @Column(name = "statistic_interval", length = 10)
+    private String statisticInterval;
+    
+    @Column(name = "statistics_time", nullable = false)
+    private Date statisticsTime;
+    
+    @Column(name = "creation_time", nullable = false)
+    private Date creationTime = new Date();
+    
+    public TaskResultStatistics(final Long successCount, final Long failedCount) {
+        this.successCount = successCount;
+        this.failedCount = failedCount;
+    }
+    
+    public TaskResultStatistics(final Long successCount, final Long failedCount, final String statisticInterval, final Date statisticsTime) {
+        this.successCount = successCount;
+        this.failedCount = failedCount;
+        this.statisticInterval = statisticInterval;
+        this.statisticsTime = statisticsTime;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/TaskRunningStatistics.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/TaskRunningStatistics.java
new file mode 100644
index 0000000..638ff6c
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/domain/TaskRunningStatistics.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ui.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/**
+ * Task running statistics.
+ */
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "TASK_RUNNING_STATISTICS")
+public final class TaskRunningStatistics {
+    
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Column(name = "running_count", length = 11)
+    private Integer runningCount;
+    
+    @Column(name = "statistics_time", nullable = false)
+    private Date statisticsTime;
+    
+    @Column(name = "creation_time", nullable = false)
+    private Date creationTime = new Date();
+    
+    public TaskRunningStatistics(final Integer runningCount, final Date statisticsTime) {
+        this.runningCount = runningCount;
+        this.statisticsTime = statisticsTime;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/BasePageRequest.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/BasePageRequest.java
new file mode 100644
index 0000000..2358c03
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/BasePageRequest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ui.dto.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Pageable request base request.
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BasePageRequest {
+    
+    public static final int DEFAULT_PAGE_SIZE = 10;
+    
+    /**
+     * Page size of request.
+     */
+    @JsonProperty("per_page")
+    private Integer pageSize = DEFAULT_PAGE_SIZE;
+    
+    /**
+     * Page number of request.
+     */
+    @JsonProperty("page")
+    private Integer pageNumber = 1;
+    
+    /**
+     * The field name for sort by.
+     */
+    @JsonProperty("sort")
+    private String sortBy;
+    
+    /**
+     * Order type, asc or desc.
+     */
+    @JsonProperty("order")
+    private String orderType;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/FindJobExecutionEventsRequest.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/FindJobExecutionEventsRequest.java
new file mode 100644
index 0000000..c937059
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/FindJobExecutionEventsRequest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.ui.dto.request;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * Request object of uri '/event-trace/execution'.
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class FindJobExecutionEventsRequest extends BasePageRequest {
+    
+    private String jobName;
+    
+    private String ip;
+    
+    private Boolean isSuccess;
+    
+    @JsonProperty("startTime")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date start;
+    
+    @JsonProperty("endTime")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date end;
+    
+    /**
+     * Create new FindJobExecutionEventsRequest with pageSize and pageNumber.
+     * @param pageNumber page number
+     * @param pageSize page size
+     */
+    public FindJobExecutionEventsRequest(final Integer pageSize, final Integer pageNumber) {
+        super(pageSize, pageNumber, null, null);
+    }
+    
+    /**
+     * Create new FindJobExecutionEventsRequest with properties.
+     * @param pageNumber page number
+     * @param pageSize page size
+     * @param sortBy the field name sort by
+     * @param orderType order type, asc or desc
+     * @param startTime start time
+     * @param endTime end time
+     */
+    public FindJobExecutionEventsRequest(final Integer pageSize, final Integer pageNumber, final String sortBy,
+                                         final String orderType, final Date startTime, final Date endTime) {
+        super(pageSize, pageNumber, sortBy, orderType);
+        this.start = startTime;
+        this.end = endTime;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/FindJobStatusTraceEventsRequest.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/FindJobStatusTraceEventsRequest.java
new file mode 100644
index 0000000..f10e0e6
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/request/FindJobStatusTraceEventsRequest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.ui.dto.request;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * Request object of uri '/event-trace/status'.
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class FindJobStatusTraceEventsRequest extends BasePageRequest {
+    
+    private String jobName;
+    
+    private String source;
+    
+    private String executionType;
+    
+    private String state;
+    
+    @JsonProperty("startTime")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date start;
+    
+    @JsonProperty("endTime")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date end;
+    
+    public FindJobStatusTraceEventsRequest(final Integer pageSize, final Integer pageNumber) {
+        super(pageSize, pageNumber, null, null);
+    }
+    
+    public FindJobStatusTraceEventsRequest(final Integer pageSize, final Integer pageNumber, final String sortBy, final String orderType, final Date startTime, final Date endTime) {
+        super(pageSize, pageNumber, sortBy, orderType);
+        this.start = startTime;
+        this.end = endTime;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/response/BasePageResponse.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/response/BasePageResponse.java
new file mode 100644
index 0000000..fdfd767
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/dto/response/BasePageResponse.java
@@ -0,0 +1,65 @@
+/*
+ * 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.ui.dto.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import org.springframework.data.domain.Page;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class BasePageResponse<T> implements Serializable {
+    
+    /**
+     * Total count of rows.
+     */
+    private Long total;
+    
+    /**
+     * Rows data.
+     */
+    private List<T> rows;
+    
+    /**
+     * Create new BasePageResponse with total and data.
+     * @param total Total count of match data
+     * @param data Current page of data
+     * @param <T> Data type
+     * @return BasePageResponse
+     */
+    public static <T> BasePageResponse of(final Long total, final List<T> data) {
+        return new BasePageResponse(total, data);
+    }
+    
+    /**
+     * Create new BasePageResponse with Page.
+     * @param page match data info.
+     * @param <T> Data type
+     * @return BasePageResponse
+     */
+    public static <T> BasePageResponse of(final Page<T> page) {
+        return new BasePageResponse(page.getTotalElements(), page.getContent());
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/exception/JobConsoleException.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/exception/JobConsoleException.java
new file mode 100644
index 0000000..d2c0f29
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/exception/JobConsoleException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ui.exception;
+
+import lombok.Getter;
+
+/**
+ * Job console exception.
+ */
+@Getter
+public final class JobConsoleException extends RuntimeException {
+    
+    private static final long serialVersionUID = 1393957353478034407L;
+    
+    public static final int INVALID_PARAM = 400;
+    
+    public static final int NO_RIGHT = 403;
+    
+    public static final int SERVER_ERROR = 500;
+    
+    private final int errorCode;
+    
+    private final String errorMessage;
+    
+    public JobConsoleException(final int errorCode, final String errorMessage) {
+        super(errorMessage);
+        this.errorCode = errorCode;
+        this.errorMessage = errorMessage;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/ConfigurationsXmlRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/ConfigurationsXmlRepository.java
new file mode 100644
index 0000000..c9e644c
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/ConfigurationsXmlRepository.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.shardingsphere.elasticjob.ui.repository;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.GlobalConfiguration;
+
+/**
+ * Configurations XML repository.
+ */
+public interface ConfigurationsXmlRepository extends XmlRepository<GlobalConfiguration> {
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/XmlRepository.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/XmlRepository.java
new file mode 100644
index 0000000..e8f0caf
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/XmlRepository.java
@@ -0,0 +1,40 @@
+/*
+ * 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.ui.repository;
+
+/**
+ * XML repository.
+ *
+ * @param <E> type of data
+ */
+public interface XmlRepository<E> {
+    
+    /**
+     * Load data.
+     * 
+     * @return load result
+     */
+    E load();
+    
+    /**
+     * Save data.
+     * 
+     * @param entity entity
+     */
+    void save(E entity);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/impl/AbstractXmlRepositoryImpl.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/impl/AbstractXmlRepositoryImpl.java
new file mode 100644
index 0000000..fcb9247
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/impl/AbstractXmlRepositoryImpl.java
@@ -0,0 +1,80 @@
+/*
+ * 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.ui.repository.impl;
+
+import org.apache.shardingsphere.elasticjob.ui.exception.JobConsoleException;
+import org.apache.shardingsphere.elasticjob.ui.repository.XmlRepository;
+import org.apache.shardingsphere.elasticjob.ui.util.HomeFolderUtils;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.io.File;
+
+/**
+ * Abstract XML repository implementation.
+ *
+ * @param <E> type of data
+ */
+public abstract class AbstractXmlRepositoryImpl<E> implements XmlRepository<E> {
+    
+    private final File file;
+    
+    private final Class<E> clazz;
+    
+    private JAXBContext jaxbContext;
+    
+    protected AbstractXmlRepositoryImpl(final String fileName, final Class<E> clazz) {
+        file = new File(HomeFolderUtils.getFilePathInHomeFolder(fileName));
+        this.clazz = clazz;
+        HomeFolderUtils.createHomeFolderIfNotExisted();
+        try {
+            jaxbContext = JAXBContext.newInstance(clazz);
+        } catch (final JAXBException ex) {
+            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, ex.getMessage());
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public synchronized E load() {
+        if (!file.exists()) {
+            try {
+                return clazz.newInstance();
+            } catch (final InstantiationException | IllegalAccessException ex) {
+                throw new JobConsoleException(JobConsoleException.SERVER_ERROR, ex.getMessage());
+            }
+        }
+        try {
+            return (E) jaxbContext.createUnmarshaller().unmarshal(file);
+        } catch (final JAXBException ex) {
+            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, ex.getMessage());
+        }
+    }
+    
+    @Override
+    public synchronized void save(final E entity) {
+        try {
+            Marshaller marshaller = jaxbContext.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+            marshaller.marshal(entity, file);
+        } catch (final JAXBException ex) {
+            throw new JobConsoleException(JobConsoleException.SERVER_ERROR, ex.getMessage());
+        }
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/impl/ConfigurationsXmlRepositoryImpl.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/impl/ConfigurationsXmlRepositoryImpl.java
new file mode 100644
index 0000000..5b4b64e
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/repository/impl/ConfigurationsXmlRepositoryImpl.java
@@ -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.
+ */
+
+package org.apache.shardingsphere.elasticjob.ui.repository.impl;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.GlobalConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.repository.ConfigurationsXmlRepository;
+
+/**
+ * Configurations XML repository implementation.
+ */
+public final class ConfigurationsXmlRepositoryImpl extends AbstractXmlRepositoryImpl<GlobalConfiguration> implements ConfigurationsXmlRepository {
+    
+    public ConfigurationsXmlRepositoryImpl() {
+        super("Configurations.xml", GlobalConfiguration.class);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/AuthenticationFilter.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/AuthenticationFilter.java
new file mode 100644
index 0000000..a892759
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/AuthenticationFilter.java
@@ -0,0 +1,99 @@
+/*
+ * 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.ui.security;
+
+import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import lombok.Setter;
+import org.apache.shardingsphere.elasticjob.ui.web.response.ResponseResultUtil;
+
+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 java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Authentication filter.
+ */
+public final class AuthenticationFilter implements Filter {
+    
+    private static final String LOGIN_URI = "/api/login";
+    
+    private final Gson gson = new Gson();
+    
+    @Setter
+    private UserAuthenticationService userAuthenticationService;
+    
+    @Override
+    public void init(final FilterConfig filterConfig) {
+    }
+    
+    @Override
+    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
+        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
+        if (LOGIN_URI.equals(httpRequest.getRequestURI())) {
+            handleLogin(httpRequest, httpResponse);
+        } else {
+            String accessToken = httpRequest.getHeader("Access-Token");
+            if (!Strings.isNullOrEmpty(accessToken) && accessToken.equals(userAuthenticationService.getToken())) {
+                filterChain.doFilter(httpRequest, httpResponse);
+            } else {
+                respondWithUnauthorized(httpResponse);
+            }
+        }
+    }
+    
+    @Override
+    public void destroy() {
+    }
+    
+    private void handleLogin(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
+        try {
+            UserAccount user = gson.fromJson(httpRequest.getReader(), UserAccount.class);
+            AuthenticationResult authenticationResult = userAuthenticationService.checkUser(user);
+            if (null != authenticationResult && authenticationResult.isSuccess()) {
+                httpResponse.setContentType("application/json");
+                httpResponse.setCharacterEncoding("UTF-8");
+                Map<String, Object> result = new HashMap<>();
+                result.put("username", authenticationResult.getUsername());
+                result.put("accessToken", userAuthenticationService.getToken());
+                result.put("isGuest", authenticationResult.isGuest());
+                httpResponse.getWriter().write(gson.toJson(ResponseResultUtil.build(result)));
+            } else {
+                respondWithUnauthorized(httpResponse);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        
+    }
+    
+    private void respondWithUnauthorized(final HttpServletResponse httpResponse) throws IOException {
+        httpResponse.setContentType("application/json");
+        httpResponse.setCharacterEncoding("UTF-8");
+        httpResponse.getWriter().write(new Gson().toJson(ResponseResultUtil.handleUnauthorizedException("Unauthorized.")));
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/AuthenticationResult.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/AuthenticationResult.java
new file mode 100644
index 0000000..8758f43
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/AuthenticationResult.java
@@ -0,0 +1,39 @@
+/*
+ * 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.ui.security;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Authentication result.
+ **/
+@Getter
+@RequiredArgsConstructor
+public final class AuthenticationResult {
+    
+    private final String username;
+
+    private final String password;
+    
+    private final boolean success;
+    
+    private final boolean isGuest;
+    
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/UserAccount.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/UserAccount.java
new file mode 100644
index 0000000..3fe02f3
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/UserAccount.java
@@ -0,0 +1,33 @@
+/*
+ * 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.ui.security;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * User account.
+ */
+@Getter
+@Setter
+public final class UserAccount {
+    
+    private String username;
+    
+    private String password;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/UserAuthenticationService.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/UserAuthenticationService.java
new file mode 100644
index 0000000..b41d7d3
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/security/UserAuthenticationService.java
@@ -0,0 +1,74 @@
+/*
+ * 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.ui.security;
+
+import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import lombok.Setter;
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * User authentication service.
+ */
+@Component
+@ConfigurationProperties(prefix = "auth")
+@Setter
+public final class UserAuthenticationService {
+    
+    private String rootUsername;
+    
+    private String rootPassword;
+    
+    private String guestUsername;
+    
+    private String guestPassword;
+    
+    private final Base64 base64 = new Base64();
+    
+    private Gson gson = new Gson();
+    
+    /**
+     * Check user.
+     *
+     * @param userAccount user account
+     * @return check success or failure
+     */
+    public AuthenticationResult checkUser(final UserAccount userAccount) {
+        if (null == userAccount || Strings.isNullOrEmpty(userAccount.getUsername()) || Strings.isNullOrEmpty(userAccount.getPassword())) {
+            return new AuthenticationResult(null, null, false, false);
+        }
+        if (rootUsername.equals(userAccount.getUsername()) && rootPassword.equals(userAccount.getPassword())) {
+            return new AuthenticationResult(rootUsername, rootPassword, true, false);
+        }
+        if (guestUsername.equals(userAccount.getUsername()) && guestPassword.equals(userAccount.getPassword())) {
+            return new AuthenticationResult(guestUsername, guestPassword, true, true);
+        }
+        return new AuthenticationResult(null ,null, false, false);
+    }
+    
+    /**
+     * Get user authentication token.
+     *
+     * @return authentication token
+     */
+    public String getToken() {
+        return base64.encodeToString(gson.toJson(this).getBytes());
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/EventTraceDataSourceConfigurationService.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/EventTraceDataSourceConfigurationService.java
new file mode 100644
index 0000000..0135623
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/EventTraceDataSourceConfigurationService.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ui.service;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceConfigurations;
+
+import java.util.Optional;
+
+/**
+ * Event trace data source configuration service.
+ */
+public interface EventTraceDataSourceConfigurationService {
+    
+    /**
+     * Load all event trace data source configurations.
+     *
+     * @return all event trace data source configuration
+     */
+    EventTraceDataSourceConfigurations loadAll();
+    
+    /**
+     * Load event trace data source configuration.
+     * 
+     * @param name name of event trace data source configuration
+     * @return event trace data source configuration
+     */
+    EventTraceDataSourceConfiguration load(String name);
+    
+    /**
+     * Find event trace data source configuration.
+     *
+     * @param name name of event trace data source configuration
+     * @param configs event trace data source configurations
+     * @return event trace data source configuration
+     */
+    EventTraceDataSourceConfiguration find(String name, EventTraceDataSourceConfigurations configs);
+    
+    /**
+     * Load activated event trace data source configuration.
+     * 
+     * @return activated event trace data source configuration
+     */
+    Optional<EventTraceDataSourceConfiguration> loadActivated();
+    
+    /**
+     * Add event trace data source configuration.
+     * 
+     * @param config event trace data source configuration
+     * @return success to add or not
+     */
+    boolean add(EventTraceDataSourceConfiguration config);
+    
+    /**
+     * Delete event trace data source configuration.
+     *
+     * @param name name of event trace data source configuration
+     */
+    void delete(String name);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/EventTraceHistoryService.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/EventTraceHistoryService.java
new file mode 100644
index 0000000..9a64552
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/EventTraceHistoryService.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ui.service;
+
+import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobExecutionEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobStatusTraceEventsRequest;
+import org.springframework.data.domain.Page;
+
+/**
+ * Event trace history service.
+ */
+public interface EventTraceHistoryService {
+    
+    /**
+     * Find job execution events.
+     *
+     * @param findJobExecutionEventsRequest query params
+     * @return job execution events
+     */
+    Page<JobExecutionEvent> findJobExecutionEvents(FindJobExecutionEventsRequest findJobExecutionEventsRequest);
+    
+    /**
+     * Find job status trace events.
+     *
+     * @param findJobStatusTraceEventsRequest query params
+     * @return job status trace events
+     */
+    Page<JobStatusTraceEvent> findJobStatusTraceEvents(FindJobStatusTraceEventsRequest findJobStatusTraceEventsRequest);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/JobAPIService.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/JobAPIService.java
new file mode 100644
index 0000000..01008f5
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/JobAPIService.java
@@ -0,0 +1,70 @@
+/*
+ * 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.ui.service;
+
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobConfigurationAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobOperateAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobStatisticsAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.ServerStatisticsAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.ShardingOperateAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.ShardingStatisticsAPI;
+
+public interface JobAPIService {
+    
+    /**
+     * Job configuration API.
+     *
+     * @return job configuration API
+     */
+    JobConfigurationAPI getJobConfigurationAPI();
+    
+    /**
+     * Job operate API.
+     *
+     * @return Job operate API
+     */
+    JobOperateAPI getJobOperatorAPI();
+    
+    /**
+     * Sharding operate API.
+     *
+     * @return sharding operate API
+     */
+    ShardingOperateAPI getShardingOperateAPI();
+    
+    /**
+     * Job statistics API.
+     *
+     * @return job statistics API
+     */
+    JobStatisticsAPI getJobStatisticsAPI();
+    
+    /**
+     * Servers statistics API.
+     *
+     * @return server statistics API
+     */
+    ServerStatisticsAPI getServerStatisticsAPI();
+    
+    /**
+     * Sharding statistics API.
+     *
+     * @return sharding statistics API
+     */
+    ShardingStatisticsAPI getShardingStatisticsAPI();
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/RegistryCenterConfigurationService.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/RegistryCenterConfigurationService.java
new file mode 100644
index 0000000..9aad0d8
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/RegistryCenterConfigurationService.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ui.service;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfigurations;
+
+import java.util.Optional;
+
+/**
+ * Registry center configuration service.
+ */
+public interface RegistryCenterConfigurationService {
+    
+    /**
+     * Load all registry center configurations.
+     *
+     * @return all registry center configurations
+     */
+    RegistryCenterConfigurations loadAll();
+    
+    /**
+     * Load registry center configuration.
+     *
+     * @param name name of registry center configuration
+     * @return registry center configuration
+     */
+    RegistryCenterConfiguration load(String name);
+    
+    /**
+     * Find registry center configuration.
+     * 
+     * @param name name of registry center configuration
+     * @param configs registry center configurations
+     * @return registry center configuration
+     */
+    RegistryCenterConfiguration find(String name, RegistryCenterConfigurations configs);
+    
+    /**
+     * Load activated registry center configuration.
+     *
+     * @return activated registry center configuration
+     */
+    Optional<RegistryCenterConfiguration> loadActivated();
+    
+    /**
+     * Add registry center configuration.
+     *
+     * @param config registry center configuration
+     * @return success to add or not
+     */
+    boolean add(RegistryCenterConfiguration config);
+    
+    /**
+     * Delete registry center configuration.
+     *
+     * @param name name of registry center configuration
+     */
+    void delete(String name);
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/EventTraceDataSourceConfigurationServiceImpl.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/EventTraceDataSourceConfigurationServiceImpl.java
new file mode 100644
index 0000000..b3a80d9
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/EventTraceDataSourceConfigurationServiceImpl.java
@@ -0,0 +1,124 @@
+/*
+ * 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.ui.service.impl;
+
+import org.apache.shardingsphere.elasticjob.ui.config.DynamicDataSourceConfig;
+import org.apache.shardingsphere.elasticjob.ui.domain.DataSourceFactory;
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceConfigurations;
+import org.apache.shardingsphere.elasticjob.ui.domain.GlobalConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.repository.ConfigurationsXmlRepository;
+import org.apache.shardingsphere.elasticjob.ui.repository.impl.ConfigurationsXmlRepositoryImpl;
+import org.apache.shardingsphere.elasticjob.ui.service.EventTraceDataSourceConfigurationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.sql.DataSource;
+import java.util.Optional;
+
+/**
+ * Event trace data source configuration service implementation.
+ */
+@Service
+public final class EventTraceDataSourceConfigurationServiceImpl implements EventTraceDataSourceConfigurationService {
+    
+    private ConfigurationsXmlRepository configurationsXmlRepository = new ConfigurationsXmlRepositoryImpl();
+    
+    @Autowired
+    private DynamicDataSourceConfig.DynamicDataSource dynamicDataSource;
+    
+    @Override
+    public EventTraceDataSourceConfigurations loadAll() {
+        return loadGlobal().getEventTraceDataSourceConfigurations();
+    }
+    
+    @Override
+    public EventTraceDataSourceConfiguration load(final String name) {
+        GlobalConfiguration configs = loadGlobal();
+        EventTraceDataSourceConfiguration result = find(name, configs.getEventTraceDataSourceConfigurations());
+        setActivated(configs, result);
+        // Activate the dataSource by data source name for spring boot
+        DynamicDataSourceConfig.DynamicDataSourceContextHolder.setDataSourceName(name);
+        return result;
+    }
+    
+    @Override
+    public EventTraceDataSourceConfiguration find(final String name, final EventTraceDataSourceConfigurations configs) {
+        for (EventTraceDataSourceConfiguration each : configs.getEventTraceDataSourceConfiguration()) {
+            if (name.equals(each.getName())) {
+                return each;
+            }
+        }
+        return null;
+    }
+    
+    private void setActivated(final GlobalConfiguration configs, final EventTraceDataSourceConfiguration toBeConnectedConfig) {
+        EventTraceDataSourceConfiguration activatedConfig = findActivatedDataSourceConfiguration(configs);
+        if (!toBeConnectedConfig.equals(activatedConfig)) {
+            if (null != activatedConfig) {
+                activatedConfig.setActivated(false);
+            }
+            toBeConnectedConfig.setActivated(true);
+            configurationsXmlRepository.save(configs);
+        }
+    }
+    
+    @Override
+    public Optional<EventTraceDataSourceConfiguration> loadActivated() {
+        return Optional.ofNullable(findActivatedDataSourceConfiguration(loadGlobal()));
+    }
+    
+    private EventTraceDataSourceConfiguration findActivatedDataSourceConfiguration(final GlobalConfiguration configs) {
+        for (EventTraceDataSourceConfiguration each : configs.getEventTraceDataSourceConfigurations().getEventTraceDataSourceConfiguration()) {
+            if (each.isActivated()) {
+                return each;
+            }
+        }
+        return null;
+    }
+    
+    @Override
+    public boolean add(final EventTraceDataSourceConfiguration config) {
+        GlobalConfiguration configs = loadGlobal();
+        boolean result = configs.getEventTraceDataSourceConfigurations().getEventTraceDataSourceConfiguration().add(config);
+        if (result) {
+            configurationsXmlRepository.save(configs);
+        }
+        DataSource dataSource = DataSourceFactory.createDataSource(config);
+        dynamicDataSource.addDataSource(config.getName(), dataSource);
+        return result;
+    }
+    
+    @Override
+    public void delete(final String name) {
+        GlobalConfiguration configs = loadGlobal();
+        EventTraceDataSourceConfiguration toBeRemovedConfig = find(name, configs.getEventTraceDataSourceConfigurations());
+        if (null != toBeRemovedConfig) {
+            configs.getEventTraceDataSourceConfigurations().getEventTraceDataSourceConfiguration().remove(toBeRemovedConfig);
+            configurationsXmlRepository.save(configs);
+        }
+    }
+    
+    private GlobalConfiguration loadGlobal() {
+        GlobalConfiguration result = configurationsXmlRepository.load();
+        if (null == result.getEventTraceDataSourceConfigurations()) {
+            result.setEventTraceDataSourceConfigurations(new EventTraceDataSourceConfigurations());
+        }
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/EventTraceHistoryServiceImpl.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/EventTraceHistoryServiceImpl.java
new file mode 100644
index 0000000..d80e1a5
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/EventTraceHistoryServiceImpl.java
@@ -0,0 +1,132 @@
+/*
+ * 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.ui.service.impl;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
+import org.apache.shardingsphere.elasticjob.ui.dao.search.JobExecutionLogRepository;
+import org.apache.shardingsphere.elasticjob.ui.dao.search.JobStatusTraceLogRepository;
+import org.apache.shardingsphere.elasticjob.ui.domain.JobExecutionLog;
+import org.apache.shardingsphere.elasticjob.ui.domain.JobStatusTraceLog;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.BasePageRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobExecutionEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobStatusTraceEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.service.EventTraceHistoryService;
+import org.apache.shardingsphere.elasticjob.ui.util.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.convert.QueryByExamplePredicateBuilder;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Component;
+
+import javax.persistence.criteria.Predicate;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Event trace history service implementation.
+ */
+@Slf4j
+@Component
+public final class EventTraceHistoryServiceImpl implements EventTraceHistoryService {
+    
+    @Autowired
+    private JobExecutionLogRepository jobExecutionLogRepository;
+    
+    @Autowired
+    private JobStatusTraceLogRepository jobStatusTraceLogRepository;
+    
+    @Override
+    public Page<JobExecutionEvent> findJobExecutionEvents(final FindJobExecutionEventsRequest findJobExecutionEventsRequest) {
+        Example<JobExecutionLog> jobExecutionLogExample = getExample(findJobExecutionEventsRequest, JobExecutionLog.class);
+        Specification<JobExecutionLog> specification = getSpecWithExampleAndDate(jobExecutionLogExample, findJobExecutionEventsRequest.getStart(),
+            findJobExecutionEventsRequest.getEnd(), "startTime");
+
+        Page<JobExecutionLog> page = jobExecutionLogRepository.findAll(specification, getPageable(findJobExecutionEventsRequest, JobExecutionLog.class));
+        return new PageImpl<>(page.get().map(JobExecutionLog::toJobExecutionEvent).collect(Collectors.toList()), page.getPageable(), page.getTotalElements());
+    }
+    
+    @Override
+    public Page<JobStatusTraceEvent> findJobStatusTraceEvents(final FindJobStatusTraceEventsRequest findJobStatusTraceEventsRequest) {
+        Example<JobStatusTraceLog> jobStatusTraceLogExample = getExample(findJobStatusTraceEventsRequest, JobStatusTraceLog.class);
+        Specification<JobStatusTraceLog> specification = getSpecWithExampleAndDate(jobStatusTraceLogExample, findJobStatusTraceEventsRequest.getStart(),
+            findJobStatusTraceEventsRequest.getEnd(), "creationTime");
+        Page<JobStatusTraceLog> page = jobStatusTraceLogRepository.findAll(specification, getPageable(findJobStatusTraceEventsRequest, JobStatusTraceLog.class));
+        return new PageImpl<>(page.get().map(JobStatusTraceLog::toJobStatusTraceEvent).collect(Collectors.toList()), page.getPageable(), page.getTotalElements());
+    }
+    
+    private <T> Pageable getPageable(final BasePageRequest pageRequest, final Class<T> clazz) {
+        int page = 0;
+        int perPage = BasePageRequest.DEFAULT_PAGE_SIZE;
+        if (pageRequest.getPageNumber() > 0 && pageRequest.getPageSize() > 0) {
+            page = pageRequest.getPageNumber() - 1;
+            perPage = pageRequest.getPageSize();
+        }
+        return PageRequest.of(page, perPage, getSort(pageRequest, clazz));
+    }
+    
+    private <T> Sort getSort(final BasePageRequest pageRequest, final Class<T> clazz) {
+        Sort sort = Sort.unsorted();
+        boolean sortFieldIsPresent = Arrays.stream(clazz.getDeclaredFields())
+            .map(Field::getName)
+            .anyMatch(e -> e.equals(pageRequest.getSortBy()));
+        if (!sortFieldIsPresent) {
+            return sort;
+        }
+        if (!Strings.isNullOrEmpty(pageRequest.getSortBy())) {
+            Sort.Direction order = Sort.Direction.ASC;
+            try {
+                order = Sort.Direction.valueOf(pageRequest.getOrderType());
+            } catch (IllegalArgumentException ignored) {
+            }
+            sort = Sort.by(order, pageRequest.getSortBy());
+        }
+        return sort;
+    }
+    
+    private <T> Specification<T> getSpecWithExampleAndDate(final Example<T> example, final Date from, final Date to, final String field) {
+        return (Specification<T>) (root, query, builder) -> {
+            final List<Predicate> predicates = new ArrayList<>();
+            if (from != null) {
+                predicates.add(builder.greaterThan(root.get(field), from));
+            }
+            if (to != null) {
+                predicates.add(builder.lessThan(root.get(field), to));
+            }
+            predicates.add(QueryByExamplePredicateBuilder.getPredicate(root, builder, example));
+            return builder.and(predicates.toArray(new Predicate[0]));
+        };
+    }
+    
+    private <T> Example<T> getExample(final Object source, final Class<T> clazz) {
+        T instance = BeanUtils.newInstance(clazz);
+        BeanUtils.copyProperties(source, instance);
+        return Example.of(instance);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/JobAPIServiceImpl.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/JobAPIServiceImpl.java
new file mode 100644
index 0000000..d135341
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/JobAPIServiceImpl.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ui.service.impl;
+
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobAPIFactory;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobConfigurationAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobOperateAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.JobStatisticsAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.ServerStatisticsAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.ShardingOperateAPI;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.api.ShardingStatisticsAPI;
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.service.JobAPIService;
+import org.apache.shardingsphere.elasticjob.ui.util.SessionRegistryCenterConfiguration;
+import org.springframework.stereotype.Service;
+
+/**
+ * Job API service implementation.
+ */
+@Service
+public final class JobAPIServiceImpl implements JobAPIService {
+    
+    @Override
+    public JobConfigurationAPI getJobConfigurationAPI() {
+        RegistryCenterConfiguration regCenterConfig = SessionRegistryCenterConfiguration.getRegistryCenterConfiguration();
+        return JobAPIFactory.createJobConfigurationAPI(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+    }
+    
+    @Override
+    public JobOperateAPI getJobOperatorAPI() {
+        RegistryCenterConfiguration regCenterConfig = SessionRegistryCenterConfiguration.getRegistryCenterConfiguration();
+        return JobAPIFactory.createJobOperateAPI(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+    }
+    
+    @Override
+    public ShardingOperateAPI getShardingOperateAPI() {
+        RegistryCenterConfiguration regCenterConfig = SessionRegistryCenterConfiguration.getRegistryCenterConfiguration();
+        return JobAPIFactory.createShardingOperateAPI(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+    }
+    
+    @Override
+    public JobStatisticsAPI getJobStatisticsAPI() {
+        RegistryCenterConfiguration regCenterConfig = SessionRegistryCenterConfiguration.getRegistryCenterConfiguration();
+        return JobAPIFactory.createJobStatisticsAPI(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+    }
+    
+    @Override
+    public ServerStatisticsAPI getServerStatisticsAPI() {
+        RegistryCenterConfiguration regCenterConfig = SessionRegistryCenterConfiguration.getRegistryCenterConfiguration();
+        return JobAPIFactory.createServerStatisticsAPI(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+    }
+    
+    @Override
+    public ShardingStatisticsAPI getShardingStatisticsAPI() {
+        RegistryCenterConfiguration regCenterConfig = SessionRegistryCenterConfiguration.getRegistryCenterConfiguration();
+        return JobAPIFactory.createShardingStatisticsAPI(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/RegistryCenterConfigurationServiceImpl.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/RegistryCenterConfigurationServiceImpl.java
new file mode 100644
index 0000000..ddbb47e
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/service/impl/RegistryCenterConfigurationServiceImpl.java
@@ -0,0 +1,113 @@
+/*
+ * 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.ui.service.impl;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.GlobalConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfigurations;
+import org.apache.shardingsphere.elasticjob.ui.repository.ConfigurationsXmlRepository;
+import org.apache.shardingsphere.elasticjob.ui.repository.impl.ConfigurationsXmlRepositoryImpl;
+import org.apache.shardingsphere.elasticjob.ui.service.RegistryCenterConfigurationService;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+/**
+ * Registry center configuration service implementation.
+ */
+@Service
+public final class RegistryCenterConfigurationServiceImpl implements RegistryCenterConfigurationService {
+    
+    private ConfigurationsXmlRepository configurationsXmlRepository = new ConfigurationsXmlRepositoryImpl();
+    
+    @Override
+    public RegistryCenterConfigurations loadAll() {
+        return loadGlobal().getRegistryCenterConfigurations();
+    }
+    
+    @Override
+    public RegistryCenterConfiguration load(final String name) {
+        GlobalConfiguration configs = loadGlobal();
+        RegistryCenterConfiguration result = find(name, configs.getRegistryCenterConfigurations());
+        setActivated(configs, result);
+        return result;
+    }
+    
+    @Override
+    public RegistryCenterConfiguration find(final String name, final RegistryCenterConfigurations configs) {
+        for (RegistryCenterConfiguration each : configs.getRegistryCenterConfiguration()) {
+            if (name.equals(each.getName())) {
+                return each;
+            }
+        }
+        return null;
+    }
+    
+    private void setActivated(final GlobalConfiguration configs, final RegistryCenterConfiguration toBeConnectedConfig) {
+        RegistryCenterConfiguration activatedConfig = findActivatedRegistryCenterConfiguration(configs);
+        if (!toBeConnectedConfig.equals(activatedConfig)) {
+            if (null != activatedConfig) {
+                activatedConfig.setActivated(false);
+            }
+            toBeConnectedConfig.setActivated(true);
+            configurationsXmlRepository.save(configs);
+        }
+    }
+    
+    @Override
+    public Optional<RegistryCenterConfiguration> loadActivated() {
+        return Optional.ofNullable(findActivatedRegistryCenterConfiguration(loadGlobal()));
+    }
+    
+    private RegistryCenterConfiguration findActivatedRegistryCenterConfiguration(final GlobalConfiguration configs) {
+        for (RegistryCenterConfiguration each : configs.getRegistryCenterConfigurations().getRegistryCenterConfiguration()) {
+            if (each.isActivated()) {
+                return each;
+            }
+        }
+        return null;
+    }
+    
+    @Override
+    public boolean add(final RegistryCenterConfiguration config) {
+        GlobalConfiguration configs = loadGlobal();
+        boolean result = configs.getRegistryCenterConfigurations().getRegistryCenterConfiguration().add(config);
+        if (result) {
+            configurationsXmlRepository.save(configs);
+        }
+        return result;
+    }
+    
+    @Override
+    public void delete(final String name) {
+        GlobalConfiguration configs = loadGlobal();
+        RegistryCenterConfiguration toBeRemovedConfig = find(name, configs.getRegistryCenterConfigurations());
+        if (null != toBeRemovedConfig) {
+            configs.getRegistryCenterConfigurations().getRegistryCenterConfiguration().remove(toBeRemovedConfig);
+            configurationsXmlRepository.save(configs);
+        }
+    }
+    
+    private GlobalConfiguration loadGlobal() {
+        GlobalConfiguration result = configurationsXmlRepository.load();
+        if (null == result.getRegistryCenterConfigurations()) {
+            result.setRegistryCenterConfigurations(new RegistryCenterConfigurations());
+        }
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/BeanUtils.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/BeanUtils.java
new file mode 100644
index 0000000..0566471
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/BeanUtils.java
@@ -0,0 +1,56 @@
+/*
+ * 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.ui.util;
+
+import org.springframework.cglib.beans.BeanMap;
+
+import java.util.Map;
+import java.util.Objects;
+
+public class BeanUtils extends org.springframework.beans.BeanUtils {
+    
+    /**
+     * return a new instance by specified java type.
+     *
+     * @param clazz java type class
+     * @param <T>   java type
+     * @return new instance
+     */
+    public static <T> T newInstance(final Class<T> clazz) {
+        return instantiateClass(clazz);
+    }
+    
+    /**
+     * map to java object.
+     *
+     * @param map  source map
+     * @param type class
+     * @param <T>  target java type
+     * @return java object
+     */
+    public static <T> T toBean(final Map<String, Object> map, final Class<T> type) {
+        if (Objects.isNull(map)) {
+            return null;
+        }
+        T bean = newInstance(type);
+        BeanMap beanMap = BeanMap.create(bean);
+        beanMap.putAll(map);
+        return bean;
+    }
+    
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/HomeFolderUtils.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/HomeFolderUtils.java
new file mode 100644
index 0000000..1c4aa10
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/HomeFolderUtils.java
@@ -0,0 +1,58 @@
+/*
+ * 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.ui.util;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.io.File;
+
+/**
+ * Home folder Utils.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class HomeFolderUtils {
+    
+    private static final String USER_HOME = System.getProperty("user.home");
+    
+    private static final String CONSOLE_ROOT_FOLDER = ".elasticjob-console";
+    
+    /**
+     * Get file path in home folder.
+     * 
+     * @param fileName file name
+     * @return file path in home folder
+     */
+    public static String getFilePathInHomeFolder(final String fileName) {
+        return String.format("%s%s", getHomeFolder(), fileName);
+    }
+    
+    /**
+     * Create home folder if not existed.
+     */
+    public static void createHomeFolderIfNotExisted() {
+        File file = new File(getHomeFolder());
+        if (!file.exists()) {
+            file.mkdirs();
+        }
+    }
+    
+    private static String getHomeFolder() {
+        return String.format("%s%s%s%s", USER_HOME, File.separator, CONSOLE_ROOT_FOLDER, File.separator);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/SessionEventTraceDataSourceConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/SessionEventTraceDataSourceConfiguration.java
new file mode 100644
index 0000000..1445b7d
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/SessionEventTraceDataSourceConfiguration.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ui.util;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.ui.config.DynamicDataSourceConfig;
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceConfiguration;
+
+/**
+ * Event trace data source configuration in session.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class SessionEventTraceDataSourceConfiguration {
+    
+    private static EventTraceDataSourceConfiguration eventTraceDataSourceConfiguration;
+    
+    /**
+     * Set event trace data source configuration.
+     *
+     * @param eventTraceDataSourceConfiguration event trace data source configuration
+     */
+    public static void setDataSourceConfiguration(final EventTraceDataSourceConfiguration eventTraceDataSourceConfiguration) {
+        DynamicDataSourceConfig.DynamicDataSourceContextHolder.setDataSourceName(eventTraceDataSourceConfiguration.getName());
+        SessionEventTraceDataSourceConfiguration.eventTraceDataSourceConfiguration = eventTraceDataSourceConfiguration;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/SessionRegistryCenterConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/SessionRegistryCenterConfiguration.java
new file mode 100644
index 0000000..74fe0c2
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/util/SessionRegistryCenterConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ui.util;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfiguration;
+
+/**
+ * Registry center configuration configuration.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class SessionRegistryCenterConfiguration {
+    
+    private static RegistryCenterConfiguration regCenterConfig;
+    
+    /**
+     * Get registry center configuration.
+     *
+     * @return registry center configuration
+     */
+    public static RegistryCenterConfiguration getRegistryCenterConfiguration() {
+        return regCenterConfig;
+    }
+    
+    /**
+     * Set registry center configuration.
+     * 
+     * @param regCenterConfig registry center configuration
+     */
+    public static void setRegistryCenterConfiguration(final RegistryCenterConfiguration regCenterConfig) {
+        SessionRegistryCenterConfiguration.regCenterConfig = regCenterConfig;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/EventTraceDataSourceController.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/EventTraceDataSourceController.java
new file mode 100644
index 0000000..d4bd7c0
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/EventTraceDataSourceController.java
@@ -0,0 +1,138 @@
+/*
+ * 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.ui.web.controller;
+
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.domain.EventTraceDataSourceFactory;
+import org.apache.shardingsphere.elasticjob.ui.service.EventTraceDataSourceConfigurationService;
+import org.apache.shardingsphere.elasticjob.ui.util.SessionEventTraceDataSourceConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import java.util.Collection;
+
+/**
+ * Event trace data source RESTful API.
+ */
+@RestController
+@RequestMapping("/data-source")
+public final class EventTraceDataSourceController {
+    
+    public static final String DATA_SOURCE_CONFIG_KEY = "data_source_config_key";
+    
+    private EventTraceDataSourceConfigurationService eventTraceDataSourceConfigurationService;
+    
+    @Autowired
+    public EventTraceDataSourceController(final EventTraceDataSourceConfigurationService eventTraceDataSourceConfigurationService) {
+        this.eventTraceDataSourceConfigurationService = eventTraceDataSourceConfigurationService;
+    }
+    
+    /**
+     * Judge whether event trace data source is activated.
+     *
+     * @param request HTTP request
+     * @return event trace data source is activated or not
+     */
+    @GetMapping("/activated")
+    public boolean activated(@Context final HttpServletRequest request) {
+        return eventTraceDataSourceConfigurationService.loadActivated().isPresent();
+    }
+    
+    /**
+     * Load event trace data source configuration.
+     *
+     * @param request HTTP request
+     * @return event trace data source configurations
+     */
+    @GetMapping(produces = MediaType.APPLICATION_JSON)
+    public Collection<EventTraceDataSourceConfiguration> load(@Context final HttpServletRequest request) {
+        eventTraceDataSourceConfigurationService.loadActivated().ifPresent(eventTraceDataSourceConfig -> setDataSourceNameToSession(eventTraceDataSourceConfig, request.getSession()));
+        return eventTraceDataSourceConfigurationService.loadAll().getEventTraceDataSourceConfiguration();
+    }
+    
+    /**
+     * Add event trace data source configuration.
+     *
+     * @param config event trace data source configuration
+     * @return success to added or not
+     */
+    @PostMapping(produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
+    public boolean add(@RequestBody final EventTraceDataSourceConfiguration config) {
+        return eventTraceDataSourceConfigurationService.add(config);
+    }
+    
+    /**
+     * Delete event trace data source configuration.
+     *
+     * @param config event trace data source configuration
+     */
+    @DeleteMapping(consumes = MediaType.APPLICATION_JSON)
+    public void delete(@RequestBody final EventTraceDataSourceConfiguration config) {
+        eventTraceDataSourceConfigurationService.delete(config.getName());
+    }
+    
+    /**
+     * Test event trace data source connection.
+     *
+     * @param config  event trace data source configuration
+     * @param request HTTP request
+     * @return success or not
+     */
+    @PostMapping(value = "/connectTest", produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
+    public boolean connectTest(@RequestBody final EventTraceDataSourceConfiguration config, @Context final HttpServletRequest request) {
+        return setDataSourceNameToSession(config, request.getSession());
+    }
+    
+    /**
+     * Connect event trace data source.
+     *
+     * @param config  event trace data source
+     * @param request HTTP request
+     * @return success or not
+     */
+    @PostMapping(value = "/connect", produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
+    public boolean connect(@RequestBody final EventTraceDataSourceConfiguration config, @Context final HttpServletRequest request) {
+        boolean isConnected = setDataSourceNameToSession(eventTraceDataSourceConfigurationService.find(config.getName(), eventTraceDataSourceConfigurationService.loadAll()), request.getSession());
+        if (isConnected) {
+            eventTraceDataSourceConfigurationService.load(config.getName());
+        }
+        return isConnected;
+    }
+    
+    private boolean setDataSourceNameToSession(final EventTraceDataSourceConfiguration dataSourceConfig, final HttpSession session) {
+        session.setAttribute(DATA_SOURCE_CONFIG_KEY, dataSourceConfig);
+        try {
+            EventTraceDataSourceFactory.createEventTraceDataSource(dataSourceConfig.getDriver(), dataSourceConfig.getUrl(), dataSourceConfig.getUsername(), dataSourceConfig.getPassword());
+            SessionEventTraceDataSourceConfiguration.setDataSourceConfiguration((EventTraceDataSourceConfiguration) session.getAttribute(DATA_SOURCE_CONFIG_KEY));
+        // CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        // CHECKSTYLE:ON
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/EventTraceHistoryController.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/EventTraceHistoryController.java
new file mode 100644
index 0000000..c8499e1
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/EventTraceHistoryController.java
@@ -0,0 +1,67 @@
+/*
+ * 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.ui.web.controller;
+
+import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobExecutionEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobStatusTraceEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.response.BasePageResponse;
+import org.apache.shardingsphere.elasticjob.ui.service.EventTraceHistoryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.ws.rs.core.MediaType;
+
+/**
+ * Event trace history RESTful API.
+ */
+@RestController
+@RequestMapping("/event-trace")
+public final class EventTraceHistoryController {
+    
+    @Autowired
+    private EventTraceHistoryService eventTraceHistoryService;
+    
+    /**
+     * Find job execution events.
+     *
+     * @param requestParams query criteria
+     * @return job execution event trace result
+     */
+    @GetMapping(value = "/execution", produces = MediaType.APPLICATION_JSON)
+    public BasePageResponse<JobExecutionEvent> findJobExecutionEvents(final FindJobExecutionEventsRequest requestParams) {
+        Page<JobExecutionEvent> jobExecutionEvents = eventTraceHistoryService.findJobExecutionEvents(requestParams);
+        return BasePageResponse.of(jobExecutionEvents);
+    }
+    
+    /**
+     * Find job status trace events.
+     *
+     * @param requestParams query criteria
+     * @return job status trace result
+     */
+    @GetMapping(value = "/status", produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
+    public BasePageResponse<JobStatusTraceEvent> findJobStatusTraceEvents(final FindJobStatusTraceEventsRequest requestParams) {
+        Page<JobStatusTraceEvent> jobStatusTraceEvents = eventTraceHistoryService.findJobStatusTraceEvents(requestParams);
+        return BasePageResponse.of(jobStatusTraceEvents);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/JobConfigController.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/JobConfigController.java
new file mode 100644
index 0000000..65c876b
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/JobConfigController.java
@@ -0,0 +1,77 @@
+/*
+ * 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.ui.web.controller;
+
+import org.apache.shardingsphere.elasticjob.lite.internal.config.pojo.JobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.ui.service.JobAPIService;
+import org.springframework.beans.factory.annotation.Autowired;
+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.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.ws.rs.core.MediaType;
+
+/**
+ * Job configuration RESTful API.
+ */
+@RestController
+@RequestMapping("/jobs/config")
+public final class JobConfigController {
+    
+    private JobAPIService jobAPIService;
+    
+    @Autowired
+    public JobConfigController(final JobAPIService jobAPIService) {
+        this.jobAPIService = jobAPIService;
+    }
+    
+    /**
+     * Get job configuration.
+     *
+     * @param jobName job name
+     * @return job configuration
+     */
+    @GetMapping(value = "/{jobName}", produces = MediaType.APPLICATION_JSON)
+    public JobConfigurationPOJO getJobConfig(@PathVariable("jobName") final String jobName) {
+        return jobAPIService.getJobConfigurationAPI().getJobConfiguration(jobName);
+    }
+    
+    /**
+     * Update job configuration.
+     *
+     * @param jobConfiguration job configuration
+     */
+    @PutMapping(consumes = MediaType.APPLICATION_JSON)
+    public void updateJobConfig(@RequestBody final JobConfigurationPOJO jobConfiguration) {
+        jobAPIService.getJobConfigurationAPI().updateJobConfiguration(jobConfiguration);
+    }
+    
+    /**
+     * Remove job configuration.
+     *
+     * @param jobName job name
+     */
+    @DeleteMapping("/{jobName}")
+    public void removeJob(@PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobConfigurationAPI().removeJobConfiguration(jobName);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/JobOperationController.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/JobOperationController.java
new file mode 100644
index 0000000..f5ba118
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/JobOperationController.java
@@ -0,0 +1,139 @@
+/*
+ * 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.ui.web.controller;
+
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.domain.JobBriefInfo;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.domain.ShardingInfo;
+import org.apache.shardingsphere.elasticjob.ui.service.JobAPIService;
+import org.springframework.beans.factory.annotation.Autowired;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.ws.rs.core.MediaType;
+import java.util.Collection;
+
+/**
+ * Job operation RESTful API.
+ */
+@RestController
+@RequestMapping("/jobs")
+public final class JobOperationController {
+    
+    private JobAPIService jobAPIService;
+    
+    @Autowired
+    public JobOperationController(final JobAPIService jobAPIService) {
+        this.jobAPIService = jobAPIService;
+    }
+    
+    /**
+     * Get jobs total count.
+     * 
+     * @return jobs total count
+     */
+    @GetMapping("/count")
+    public int getJobsTotalCount() {
+        return jobAPIService.getJobStatisticsAPI().getJobsTotalCount();
+    }
+    
+    /**
+     * Get all jobs brief info.
+     * 
+     * @return all jobs brief info
+     */
+    @GetMapping(produces = MediaType.APPLICATION_JSON)
+    public Collection<JobBriefInfo> getAllJobsBriefInfo() {
+        return jobAPIService.getJobStatisticsAPI().getAllJobsBriefInfo();
+    }
+    
+    /**
+     * Trigger job.
+     * 
+     * @param jobName job name
+     */
+    @PostMapping("/{jobName}/trigger")
+    public void triggerJob(@PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().trigger(jobName);
+    }
+    
+    /**
+     * Disable job.
+     * 
+     * @param jobName job name
+     */
+    @PostMapping(value = "/{jobName}/disable")
+    public void disableJob(@PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().disable(jobName, null);
+    }
+    
+    /**
+     * Enable job.
+     *
+     * @param jobName job name
+     */
+    @PostMapping(value = "/{jobName}/enable")
+    public void enableJob(@PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().enable(jobName, null);
+    }
+    
+    /**
+     * Shutdown job.
+     * 
+     * @param jobName job name
+     */
+    @PostMapping(value = "/{jobName}/shutdown")
+    public void shutdownJob(@PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().shutdown(jobName, null);
+    }
+    
+    /**
+     * Get sharding info.
+     * 
+     * @param jobName job name
+     * @return sharding info
+     */
+    @GetMapping(value = "/{jobName}/sharding", produces = MediaType.APPLICATION_JSON)
+    public Collection<ShardingInfo> getShardingInfo(@PathVariable("jobName") final String jobName) {
+        return jobAPIService.getShardingStatisticsAPI().getShardingInfo(jobName);
+    }
+    
+    /**
+     * Disable sharding.
+     *
+     * @param jobName job name
+     * @param item sharding item
+     */
+    @PostMapping(value = "/{jobName}/sharding/{item}/disable")
+    public void disableSharding(@PathVariable("jobName") final String jobName, @PathVariable("item") final String item) {
+        jobAPIService.getShardingOperateAPI().disable(jobName, item);
+    }
+    
+    /**
+     * Enable sharding.
+     *
+     * @param jobName job name
+     * @param item sharding item
+     */
+    @PostMapping(value = "/{jobName}/sharding/{item}/enable")
+    public void enableSharding(@PathVariable("jobName") final String jobName, @PathVariable("item") final String item) {
+        jobAPIService.getShardingOperateAPI().enable(jobName, item);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/RegistryCenterController.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/RegistryCenterController.java
new file mode 100644
index 0000000..9225b91
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/RegistryCenterController.java
@@ -0,0 +1,124 @@
+/*
+ * 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.ui.web.controller;
+
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.internal.reg.RegistryCenterFactory;
+import org.apache.shardingsphere.elasticjob.reg.exception.RegException;
+import org.apache.shardingsphere.elasticjob.ui.domain.RegistryCenterConfiguration;
+import org.apache.shardingsphere.elasticjob.ui.service.RegistryCenterConfigurationService;
+import org.apache.shardingsphere.elasticjob.ui.util.SessionRegistryCenterConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import java.util.Collection;
+
+/**
+ * Registry center RESTful API.
+ */
+@RestController
+@RequestMapping("/registry-center")
+public final class RegistryCenterController {
+    
+    public static final String REG_CENTER_CONFIG_KEY = "reg_center_config_key";
+    
+    private RegistryCenterConfigurationService regCenterService;
+    
+    @Autowired
+    public RegistryCenterController(final RegistryCenterConfigurationService regCenterService) {
+        this.regCenterService = regCenterService;
+    }
+    
+    /**
+     * Judge whether registry center is activated.
+     *
+     * @return registry center is activated or not
+     */
+    @GetMapping("/activated")
+    public boolean activated() {
+        return regCenterService.loadActivated().isPresent();
+    }
+    
+    /**
+     * Load configuration from registry center.
+     *
+     * @param request HTTP request
+     * @return registry center configurations
+     */
+    @GetMapping(produces = MediaType.APPLICATION_JSON)
+    public Collection<RegistryCenterConfiguration> load(final HttpServletRequest request) {
+        regCenterService.loadActivated().ifPresent(regCenterConfig -> setRegistryCenterNameToSession(regCenterConfig, request.getSession()));
+        return regCenterService.loadAll().getRegistryCenterConfiguration();
+    }
+    
+    /**
+     * Add registry center.
+     *
+     * @param config registry center configuration
+     * @return success to add or not
+     */
+    @PostMapping(produces = MediaType.APPLICATION_JSON)
+    public boolean add(@RequestBody final RegistryCenterConfiguration config) {
+        return regCenterService.add(config);
+    }
+    
+    /**
+     * Delete registry center.
+     *
+     * @param config registry center configuration
+     */
+    @DeleteMapping(consumes = MediaType.APPLICATION_JSON)
+    public void delete(@RequestBody final RegistryCenterConfiguration config) {
+        regCenterService.delete(config.getName());
+    }
+    
+    /**
+     * Connect to registry center.
+     *
+     * @param config  config of registry center
+     * @param request HTTP request
+     * @return connected or not
+     */
+    @PostMapping(value = "/connect", consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
+    public boolean connect(@RequestBody final RegistryCenterConfiguration config, @Context final HttpServletRequest request) {
+        boolean isConnected = setRegistryCenterNameToSession(regCenterService.find(config.getName(), regCenterService.loadAll()), request.getSession());
+        if (isConnected) {
+            regCenterService.load(config.getName());
+        }
+        return isConnected;
+    }
+    
+    private boolean setRegistryCenterNameToSession(final RegistryCenterConfiguration regCenterConfig, final HttpSession session) {
+        session.setAttribute(REG_CENTER_CONFIG_KEY, regCenterConfig);
+        try {
+            RegistryCenterFactory.createCoordinatorRegistryCenter(regCenterConfig.getZkAddressList(), regCenterConfig.getNamespace(), regCenterConfig.getDigest());
+            SessionRegistryCenterConfiguration.setRegistryCenterConfiguration((RegistryCenterConfiguration) session.getAttribute(REG_CENTER_CONFIG_KEY));
+        } catch (final RegException ex) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/ServerOperationController.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/ServerOperationController.java
new file mode 100644
index 0000000..2a36f66
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/controller/ServerOperationController.java
@@ -0,0 +1,162 @@
+/*
+ * 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.ui.web.controller;
+
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.domain.JobBriefInfo;
+import org.apache.shardingsphere.elasticjob.lite.lifecycle.domain.ServerBriefInfo;
+import org.apache.shardingsphere.elasticjob.ui.service.JobAPIService;
+import org.springframework.beans.factory.annotation.Autowired;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.ws.rs.core.MediaType;
+import java.util.Collection;
+
+/**
+ * Server operation RESTful API.
+ */
+@RestController
+@RequestMapping("/servers")
+public final class ServerOperationController {
+    
+    private JobAPIService jobAPIService;
+    
+    @Autowired
+    public ServerOperationController(final JobAPIService jobAPIService) {
+        this.jobAPIService = jobAPIService;
+    }
+    
+    /**
+     * Get servers total count.
+     * 
+     * @return servers total count
+     */
+    @GetMapping("/count")
+    public int getServersTotalCount() {
+        return jobAPIService.getServerStatisticsAPI().getServersTotalCount();
+    }
+    
+    /**
+     * Get all servers brief info.
+     * 
+     * @return all servers brief info
+     */
+    @GetMapping(produces = MediaType.APPLICATION_JSON)
+    public Collection<ServerBriefInfo> getAllServersBriefInfo() {
+        return jobAPIService.getServerStatisticsAPI().getAllServersBriefInfo();
+    }
+    
+    /**
+     * Disable server.
+     *
+     * @param serverIp server IP address
+     */
+    @PostMapping("/{serverIp}/disable")
+    public void disableServer(@PathVariable("serverIp") final String serverIp) {
+        jobAPIService.getJobOperatorAPI().disable(null, serverIp);
+    }
+    
+    /**
+     * Enable server.
+     *
+     * @param serverIp server IP address
+     */
+    @PostMapping("/{serverIp}/enable")
+    public void enableServer(@PathVariable("serverIp") final String serverIp) {
+        jobAPIService.getJobOperatorAPI().enable(null, serverIp);
+    }
+    
+    /**
+     * Shutdown server.
+     *
+     * @param serverIp server IP address
+     */
+    @PostMapping("/{serverIp}/shutdown")
+    public void shutdownServer(@PathVariable("serverIp") final String serverIp) {
+        jobAPIService.getJobOperatorAPI().shutdown(null, serverIp);
+    }
+    
+    /**
+     * Remove server.
+     *
+     * @param serverIp server IP address
+     */
+    @DeleteMapping("/{serverIp}")
+    public void removeServer(@PathVariable("serverIp") final String serverIp) {
+        jobAPIService.getJobOperatorAPI().remove(null, serverIp);
+    }
+    
+    /**
+     * Get jobs.
+     *
+     * @param serverIp server IP address
+     * @return Job brief info
+     */
+    @GetMapping(value = "/{serverIp}/jobs", produces = MediaType.APPLICATION_JSON)
+    public Collection<JobBriefInfo> getJobs(@PathVariable("serverIp") final String serverIp) {
+        return jobAPIService.getJobStatisticsAPI().getJobsBriefInfo(serverIp);
+    }
+    
+    /**
+     * Disable server job.
+     * 
+     * @param serverIp server IP address
+     * @param jobName job name
+     */
+    @PostMapping(value = "/{serverIp}/jobs/{jobName}/disable")
+    public void disableServerJob(@PathVariable("serverIp") final String serverIp, @PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().disable(jobName, serverIp);
+    }
+    
+    /**
+     * Enable server job.
+     *
+     * @param serverIp server IP address
+     * @param jobName job name
+     */
+    @PostMapping("/{serverIp}/jobs/{jobName}/enable")
+    public void enableServerJob(@PathVariable("serverIp") final String serverIp, @PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().enable(jobName, serverIp);
+    }
+    
+    /**
+     * Shutdown server job.
+     *
+     * @param serverIp server IP address
+     * @param jobName job name
+     */
+    @PostMapping("/{serverIp}/jobs/{jobName}/shutdown")
+    public void shutdownServerJob(@PathVariable("serverIp") final String serverIp, @PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().shutdown(jobName, serverIp);
+    }
+    
+    /**
+     * Remove server job.
+     *
+     * @param serverIp server IP address
+     * @param jobName job name
+     */
+    @DeleteMapping("/{serverIp}/jobs/{jobName}")
+    public void removeServerJob(@PathVariable("serverIp") final String serverIp, @PathVariable("jobName") final String jobName) {
+        jobAPIService.getJobOperatorAPI().remove(jobName, serverIp);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/filter/CORSFilter.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/filter/CORSFilter.java
new file mode 100644
index 0000000..95c0869
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/filter/CORSFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ui.web.filter;
+
+import org.springframework.http.HttpStatus;
+
+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 java.io.IOException;
+
+/**
+ * CORS filter.
+ */
+public final class CORSFilter implements Filter {
+    
+    @Override
+    public void init(final FilterConfig filterConfig) {
+    }
+    
+    @Override
+    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
+        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
+        response.setHeader("Access-Control-Max-Age", "3600");
+        response.setHeader("Access-Control-Allow-Credentials", "true");
+        response.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token");
+        if ("OPTIONS".equals(request.getMethod())) {
+            response.setStatus(HttpStatus.OK.value());
+        } else {
+            filterChain.doFilter(request, response);
+        }
+    }
+    
+    @Override
+    public void destroy() {
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/response/ResponseResult.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/response/ResponseResult.java
new file mode 100644
index 0000000..b01b109
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/response/ResponseResult.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ui.web.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * Restful Response result.
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public final class ResponseResult<T> implements Serializable {
+    
+    private static final long serialVersionUID = 8144393142115317354L;
+    
+    private boolean success = true;
+    
+    private int errorCode;
+    
+    private String errorMsg;
+    
+    private T model;
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/response/ResponseResultUtil.java b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/response/ResponseResultUtil.java
new file mode 100644
index 0000000..0422956
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/ui/web/response/ResponseResultUtil.java
@@ -0,0 +1,120 @@
+/*
+ * 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.ui.web.response;
+
+import com.google.gson.Gson;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.ui.exception.JobConsoleException;
+
+/**
+ * Response result utility.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ResponseResultUtil {
+    
+    /**
+     * Build the successful response without data model.
+     *
+     * @return response result
+     */
+    public static ResponseResult success() {
+        return build(null);
+    }
+    
+    /**
+     * Build the successful response with data model.
+     *
+     * @param model data model
+     * @param <T> data model type
+     * @return response result
+     */
+    public static <T> ResponseResult<T> build(final T model) {
+        ResponseResult<T> result = new ResponseResult<>();
+        result.setSuccess(true);
+        result.setModel(model);
+        return result;
+    }
+    
+    /**
+     * Build the response from json.
+     *
+     * @param responseResultJson response result json string
+     * @return response result
+     */
+    public static ResponseResult buildFromJson(final String responseResultJson) {
+        return new Gson().fromJson(responseResultJson, ResponseResult.class);
+    }
+    
+    /**
+     * Build the error response of illegal argument exception.
+     *
+     * @param errorMsg error message
+     * @return response result
+     */
+    public static ResponseResult handleIllegalArgumentException(final String errorMsg) {
+        ResponseResult result = new ResponseResult<>();
+        result.setSuccess(false);
+        result.setErrorCode(JobConsoleException.INVALID_PARAM);
+        result.setErrorMsg(errorMsg);
+        return result;
+    }
+    
+    /**
+     * Build the error response of unauthorized exception.
+     *
+     * @param errorMsg error message
+     * @return response result
+     */
+    public static ResponseResult handleUnauthorizedException(final String errorMsg) {
+        ResponseResult result = new ResponseResult<>();
+        result.setSuccess(false);
+        result.setErrorCode(JobConsoleException.NO_RIGHT);
+        result.setErrorMsg(errorMsg);
+        return result;
+    }
+    
+    /**
+     * Build the error response of ShardingSphere UI exception.
+     *
+     * @param exception ShardingSphere UI exception
+     * @return response result
+     */
+    public static ResponseResult handleShardingSphereUIException(final JobConsoleException exception) {
+        ResponseResult result = new ResponseResult<>();
+        result.setSuccess(false);
+        result.setErrorCode(exception.getErrorCode());
+        result.setErrorMsg(exception.getMessage());
+        return result;
+    }
+    
+    /**
+     * Build the error response of uncaught exception.
+     *
+     * @param errorMsg error message
+     * @return response result
+     */
+    public static ResponseResult handleUncaughtException(final String errorMsg) {
+        ResponseResult result = new ResponseResult<>();
+        result.setSuccess(false);
+        result.setErrorCode(JobConsoleException.SERVER_ERROR);
+        result.setErrorMsg(errorMsg);
+        return result;
+    }
+    
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/main/resources/application.properties b/shardingsphere-elasticjob-ui-backend/src/main/resources/application.properties
index 51e047a..f4f0513 100644
--- a/shardingsphere-elasticjob-ui-backend/src/main/resources/application.properties
+++ b/shardingsphere-elasticjob-ui-backend/src/main/resources/application.properties
@@ -15,7 +15,16 @@
 # limitations under the License.
 #
 
-server.port=8088
+server.port=8899
 
-user.admin.username=admin
-user.admin.password=admin
+auth.root_username=root
+auth.root_password=root
+auth.guest_username=guest
+auth.guest_password=guest
+
+spring.datasource.default.driver-class-name=org.h2.Driver
+spring.datasource.default.url=jdbc:h2:mem:
+spring.datasource.default.username=sa
+spring.datasource.default.password=
+spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
+spring.jpa.show-sql=false
diff --git a/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/search/RDBJobEventSearchTest.java b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/search/RDBJobEventSearchTest.java
new file mode 100644
index 0000000..558be6b
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/search/RDBJobEventSearchTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.ui.dao.search;
+
+import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobExecutionEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobStatusTraceEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.service.EventTraceHistoryService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.domain.Page;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Date;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Import(RDBJobEventSearchTestConfiguration.class)
+public final class RDBJobEventSearchTest {
+    
+    @Autowired
+    private EventTraceHistoryService eventTraceHistoryService;
+    
+    @Test
+    public void assertFindJobExecutionEventsWithPageSizeAndNumber() {
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest());
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(50, 1));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(50));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(100, 5));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(100));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(100, 6));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(0));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithErrorPageSizeAndNumber() {
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(-1, -1, null, null, null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithSort() {
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, "jobName", "ASC", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        assertThat(result.getContent().get(0).getJobName(), is("test_job_1"));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, "jobName", "DESC", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        assertThat(result.getContent().get(0).getJobName(), is("test_job_99"));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithErrorSort() {
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, "jobName", "ERROR_SORT", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        assertThat(result.getContent().get(0).getJobName(), is("test_job_1"));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, "notExistField", "ASC", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithTime() {
+        Date now = new Date();
+        Date tenMinutesBefore = new Date(now.getTime() - 10 * 60 * 1000);
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, null, null, tenMinutesBefore, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, null, null, now, null));
+        assertThat(result.getTotalElements(), is(0L));
+        assertThat(result.getContent().size(), is(0));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, null, null, null, tenMinutesBefore));
+        assertThat(result.getTotalElements(), is(0L));
+        assertThat(result.getContent().size(), is(0));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, null, null, null, now));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1, null, null, tenMinutesBefore, now));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithFields() {
+        FindJobExecutionEventsRequest findJobExecutionEventsRequest = new FindJobExecutionEventsRequest(10, 1, null, null, null, null);
+        findJobExecutionEventsRequest.setIsSuccess(true);
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(findJobExecutionEventsRequest);
+        assertThat(result.getTotalElements(), is(250L));
+        assertThat(result.getContent().size(), is(10));
+        findJobExecutionEventsRequest.setIsSuccess(null);
+        findJobExecutionEventsRequest.setJobName("test_job_1");
+        result = eventTraceHistoryService.findJobExecutionEvents(findJobExecutionEventsRequest);
+        assertThat(result.getTotalElements(), is(1L));
+        assertThat(result.getContent().size(), is(1));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithErrorFields() {
+        Page<JobExecutionEvent> result = eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithPageSizeAndNumber() {
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, null, null, null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(50, 1, null, null, null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(50));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(100, 5, null, null, null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(100));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(100, 6, null, null, null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(0));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithErrorPageSizeAndNumber() {
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(-1, -1));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithSort() {
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, "jobName", "ASC", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        assertThat(result.getContent().get(0).getJobName(), is("test_job_1"));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, "jobName", "DESC", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        assertThat(result.getContent().get(0).getJobName(), is("test_job_99"));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithErrorSort() {
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, "jobName", "ERROR_SORT", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        assertThat(result.getContent().get(0).getJobName(), is("test_job_1"));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, "notExistField", "ASC", null, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithTime() {
+        Date now = new Date();
+        Date tenMinutesBefore = new Date(now.getTime() - 10 * 60 * 1000);
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, null, null, tenMinutesBefore, null));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, null, null, now, null));
+        assertThat(result.getTotalElements(), is(0L));
+        assertThat(result.getContent().size(), is(0));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, null, null, null, tenMinutesBefore));
+        assertThat(result.getTotalElements(), is(0L));
+        assertThat(result.getContent().size(), is(0));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, null, null, null, now));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+        result = eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1, null, null, tenMinutesBefore, now));
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithFields() {
+        FindJobStatusTraceEventsRequest findJobStatusTraceEventsRequest = new FindJobStatusTraceEventsRequest(10, 1);
+        findJobStatusTraceEventsRequest.setJobName("test_job_1");
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(findJobStatusTraceEventsRequest);
+        assertThat(result.getTotalElements(), is(1L));
+        assertThat(result.getContent().size(), is(1));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithErrorFields() {
+        FindJobStatusTraceEventsRequest findJobStatusTraceEventsRequest = new FindJobStatusTraceEventsRequest(10, 1);
+        Page<JobStatusTraceEvent> result = eventTraceHistoryService.findJobStatusTraceEvents(findJobStatusTraceEventsRequest);
+        assertThat(result.getTotalElements(), is(500L));
+        assertThat(result.getContent().size(), is(10));
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/search/RDBJobEventSearchTestConfiguration.java b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/search/RDBJobEventSearchTestConfiguration.java
new file mode 100644
index 0000000..16b5f08
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/search/RDBJobEventSearchTestConfiguration.java
@@ -0,0 +1,70 @@
+/*
+ * 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.ui.dao.search;
+
+import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
+import org.apache.shardingsphere.elasticjob.tracing.rdb.storage.RDBJobEventStorage;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobExecutionEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.dto.request.FindJobStatusTraceEventsRequest;
+import org.apache.shardingsphere.elasticjob.ui.service.EventTraceHistoryService;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.TestConfiguration;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+@TestConfiguration
+public class RDBJobEventSearchTestConfiguration implements InitializingBean {
+    
+    @Autowired
+    private EventTraceHistoryService eventTraceHistoryService;
+    
+    @Autowired
+    private DataSource dataSource;
+    
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        initStorage();
+    }
+    
+    private void initStorage() throws SQLException {
+        eventTraceHistoryService.findJobExecutionEvents(new FindJobExecutionEventsRequest(10, 1));
+        eventTraceHistoryService.findJobStatusTraceEvents(new FindJobStatusTraceEventsRequest(10, 1));
+        RDBJobEventStorage storage = new RDBJobEventStorage(dataSource);
+        for (int i = 1; i <= 500L; i++) {
+            JobExecutionEvent startEvent = new JobExecutionEvent("localhost", "127.0.0.1", "fake_task_id", "test_job_" + i, JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
+            storage.addJobExecutionEvent(startEvent);
+            if (i % 2 == 0) {
+                JobExecutionEvent successEvent = startEvent.executionSuccess();
+                storage.addJobExecutionEvent(successEvent);
+            }
+            storage.addJobStatusTraceEvent(new JobStatusTraceEvent(
+                    "test_job_" + i,
+                    "fake_failed_failover_task_id",
+                    "fake_slave_id",
+                    JobStatusTraceEvent.Source.LITE_EXECUTOR,
+                    "FAILOVER",
+                    "0",
+                    JobStatusTraceEvent.State.TASK_FAILED,
+                    "message is empty."
+            ));
+        }
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/rdb/RDBStatisticRepositoryTest.java b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/rdb/RDBStatisticRepositoryTest.java
new file mode 100644
index 0000000..f5f0419
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/dao/statistics/rdb/RDBStatisticRepositoryTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.ui.dao.statistics.rdb;
+
+import org.apache.shardingsphere.elasticjob.ui.dao.statistics.JobRegisterStatisticsRepository;
+import org.apache.shardingsphere.elasticjob.ui.dao.statistics.JobRunningStatisticsRepository;
+import org.apache.shardingsphere.elasticjob.ui.dao.statistics.StatisticInterval;
+import org.apache.shardingsphere.elasticjob.ui.dao.statistics.TaskResultStatisticsRepository;
+import org.apache.shardingsphere.elasticjob.ui.dao.statistics.TaskRunningStatisticsRepository;
+import org.apache.shardingsphere.elasticjob.ui.domain.JobRegisterStatistics;
+import org.apache.shardingsphere.elasticjob.ui.domain.JobRunningStatistics;
+import org.apache.shardingsphere.elasticjob.ui.domain.TaskResultStatistics;
+import org.apache.shardingsphere.elasticjob.ui.domain.TaskRunningStatistics;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.util.Date;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+@SpringBootTest
+@RunWith(SpringJUnit4ClassRunner.class)
+public class RDBStatisticRepositoryTest {
+    
+    @Autowired
+    private TaskResultStatisticsRepository taskResultStatisticsRepository;
+    
+    @Autowired
+    private TaskRunningStatisticsRepository taskRunningStatisticsRepository;
+    
+    @Autowired
+    private JobRegisterStatisticsRepository jobRegisterStatisticsRepository;
+    
+    @Autowired
+    private JobRunningStatisticsRepository jobRunningStatisticsRepository;
+    
+    @Test
+    public void assertAddTaskResultStatistics() {
+        for (StatisticInterval each : StatisticInterval.values()) {
+            TaskResultStatistics taskResultStatistics = new TaskResultStatistics(100L, 0L, each.name(), new Date());
+            assertTrue(taskResultStatistics.equals(taskResultStatisticsRepository.save(taskResultStatistics)));
+        }
+    }
+    
+    @Test
+    public void assertAddTaskRunningStatistics() {
+        TaskRunningStatistics taskRunningStatistics = new TaskRunningStatistics(100, new Date());
+        assertTrue(taskRunningStatistics.equals(taskRunningStatisticsRepository.save(taskRunningStatistics)));
+    }
+    
+    @Test
+    public void assertAddJobRunningStatistics() {
+        JobRunningStatistics jobRunningStatistics = new JobRunningStatistics(100, new Date());
+        assertTrue(jobRunningStatistics.equals(jobRunningStatisticsRepository.save(jobRunningStatistics)));
+    }
+    
+    @Test
+    public void assertAddJobRegisterStatistics() {
+        JobRegisterStatistics jobRegisterStatistics = new JobRegisterStatistics(100, new Date());
+        assertTrue(jobRegisterStatistics.equals(jobRegisterStatisticsRepository.save(jobRegisterStatistics)));
+    }
+    
+    @Test
+    public void assertFindTaskResultStatisticsWhenTableIsEmpty() {
+        Date now = new Date();
+        assertThat(taskResultStatisticsRepository.findTaskResultStatistics(now, StatisticInterval.MINUTE.name()).size(), is(0));
+        assertThat(taskResultStatisticsRepository.findTaskResultStatistics(now, StatisticInterval.HOUR.name()).size(), is(0));
+        assertThat(taskResultStatisticsRepository.findTaskResultStatistics(now, StatisticInterval.DAY.name()).size(), is(0));
+    }
+    
+    @Test
+    public void assertFindTaskResultStatisticsWithDifferentFromDate() {
+        Date now = new Date();
+        Date yesterday = getYesterday();
+        for (StatisticInterval each : StatisticInterval.values()) {
+            taskResultStatisticsRepository.save(new TaskResultStatistics(100L, 0L, each.name(), yesterday));
+            taskResultStatisticsRepository.save(new TaskResultStatistics(100L, 0L, each.name(), now));
+            assertThat(taskResultStatisticsRepository.findTaskResultStatistics(yesterday, each.name()).size(), is(2));
+            assertThat(taskResultStatisticsRepository.findTaskResultStatistics(now, each.name()).size(), is(1));
+        }
+    }
+    
+    @Test
+    public void assertGetSummedTaskResultStatisticsWhenTableIsEmpty() {
+        for (StatisticInterval each : StatisticInterval.values()) {
+            TaskResultStatistics po = taskResultStatisticsRepository.getSummedTaskResultStatistics(new Date(), each.name());
+            assertThat(po.getSuccessCount(), nullValue());
+            assertThat(po.getFailedCount(), nullValue());
+        }
+    }
+    
+    @Test
+    public void assertGetSummedTaskResultStatistics() {
+        for (StatisticInterval each : StatisticInterval.values()) {
+            Date date = new Date();
+            taskResultStatisticsRepository.save(new TaskResultStatistics(100L, 2L, each.name(), date));
+            taskResultStatisticsRepository.save(new TaskResultStatistics(200L, 5L, each.name(), date));
+            TaskResultStatistics po = taskResultStatisticsRepository.getSummedTaskResultStatistics(date, each.name());
+            assertThat(po.getSuccessCount(), is(300L));
+            assertThat(po.getFailedCount(), is(7L));
+        }
+    }
+
+    @Test
+    public void assertFindTaskRunningStatisticsWhenTableIsEmpty() {
+        assertThat(taskRunningStatisticsRepository.findTaskRunningStatistics(new Date()).size(), is(0));
+    }
+    
+    @Test
+    public void assertFindTaskRunningStatisticsWithDifferentFromDate() {
+        Date now = new Date();
+        Date yesterday = getYesterday();
+        taskRunningStatisticsRepository.deleteAll();
+        taskRunningStatisticsRepository.save(new TaskRunningStatistics(100, yesterday));
+        taskRunningStatisticsRepository.save(new TaskRunningStatistics(100, now));
+        assertThat(taskRunningStatisticsRepository.findTaskRunningStatistics(yesterday).size(), is(2));
+        assertThat(taskRunningStatisticsRepository.findTaskRunningStatistics(now).size(), is(1));
+    }
+    
+    @Test
+    public void assertFindJobRunningStatisticsWhenTableIsEmpty() {
+        assertThat(jobRunningStatisticsRepository.findJobRunningStatistics(new Date()).size(), is(0));
+    }
+    
+    @Test
+    public void assertFindJobRunningStatisticsWithDifferentFromDate() {
+        Date now = new Date();
+        Date yesterday = getYesterday();
+        jobRunningStatisticsRepository.deleteAll();
+        jobRunningStatisticsRepository.save(new JobRunningStatistics(100, yesterday));
+        jobRunningStatisticsRepository.save(new JobRunningStatistics(100, now));
+        assertThat(jobRunningStatisticsRepository.findJobRunningStatistics(yesterday).size(), is(2));
+        assertThat(jobRunningStatisticsRepository.findJobRunningStatistics(now).size(), is(1));
+    }
+    
+    @Test
+    public void assertFindJobRegisterStatisticsWhenTableIsEmpty() {
+        assertThat(jobRegisterStatisticsRepository.findJobRegisterStatistics(new Date()).size(), is(0));
+    }
+    
+    @Test
+    public void assertFindJobRegisterStatisticsWithDifferentFromDate() {
+        Date now = new Date();
+        Date yesterday = getYesterday();
+        jobRegisterStatisticsRepository.save(new JobRegisterStatistics(100, yesterday));
+        jobRegisterStatisticsRepository.save(new JobRegisterStatistics(100, now));
+        assertThat(jobRegisterStatisticsRepository.findJobRegisterStatistics(yesterday).size(), is(2));
+        assertThat(jobRegisterStatisticsRepository.findJobRegisterStatistics(now).size(), is(1));
+    }
+    
+    private Date getYesterday() {
+        return new Date(new Date().getTime() - 24 * 60 * 60 * 1000);
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/util/HomeFolderUtilsTest.java b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/util/HomeFolderUtilsTest.java
new file mode 100644
index 0000000..590c9f8
--- /dev/null
+++ b/shardingsphere-elasticjob-ui-backend/src/test/java/org/apache/shardingsphere/elasticjob/ui/util/HomeFolderUtilsTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.ui.util;
+
+import org.junit.Test;
+
+import java.io.File;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public final class HomeFolderUtilsTest {
+    
+    private static final String HOME_FOLDER = System.getProperty("user.home") + File.separator + ".elasticjob-console" + File.separator;
+    
+    @Test
+    public void assertGetFilePathInHomeFolder() {
+        assertThat(HomeFolderUtils.getFilePathInHomeFolder("test_file"), is(HOME_FOLDER + "test_file"));
+    }
+}
diff --git a/shardingsphere-elasticjob-ui-frontend/config/index.js b/shardingsphere-elasticjob-ui-frontend/config/index.js
index fdce0d8..38637c9 100644
--- a/shardingsphere-elasticjob-ui-frontend/config/index.js
+++ b/shardingsphere-elasticjob-ui-frontend/config/index.js
@@ -28,7 +28,7 @@ module.exports = {
     assetsPublicPath: '/',
     proxyTable: {
       '/api': {
-        target: 'http://localhost:8089',
+        target: 'http://localhost:8899',
         changeOrigin: true,
         pathRewrite: {
           '^/api': '/api'
diff --git a/shardingsphere-elasticjob-ui-frontend/src/lang/en-US.js b/shardingsphere-elasticjob-ui-frontend/src/lang/en-US.js
index cdd3b6e..ad569ac 100644
--- a/shardingsphere-elasticjob-ui-frontend/src/lang/en-US.js
+++ b/shardingsphere-elasticjob-ui-frontend/src/lang/en-US.js
@@ -20,38 +20,47 @@ export default {
     home: 'Home',
     menuData: [
       {
-        title: 'Config Center',
+        title: 'Global settings',
         child: [
           {
-            title: 'Config Server',
-            href: '/config-center'
+            title: 'Registry center',
+            href: '/registry-center'
           },
           {
-            title: 'Rule Config',
-            href: '/rule-config'
+            title: 'Event trace data source',
+            href: '/data-source'
           }
         ]
       },
       {
-        title: 'Registry Center',
+        title: 'Job operation',
         child: [
           {
-            title: 'Registry Server',
-            href: '/registry-center'
+            title: 'Job dimension',
+            href: '/operation-jobs'
           },
           {
-            title: 'Runtime Status',
-            href: '/runtime-status'
+            title: 'Server dimension',
+            href: '/operation-servers'
           }
         ]
       },
       {
-        title: 'Data scaling',
-        href: '/data-scaling'
+        title: 'Job history',
+        child: [
+          {
+            title: 'Job trace',
+            href: '/history-trace'
+          },
+          {
+            title: 'History status',
+            href: '/history-status'
+          }
+        ]
       },
       {
-        title: 'Cluster state',
-        href: '/cluster-state'
+        title: 'Help',
+        href: '/job-help'
       }
     ],
     connected: 'Connected',
diff --git a/shardingsphere-elasticjob-ui-frontend/src/lang/zh-CN.js b/shardingsphere-elasticjob-ui-frontend/src/lang/zh-CN.js
index 7d16891..d860c3d 100644
--- a/shardingsphere-elasticjob-ui-frontend/src/lang/zh-CN.js
+++ b/shardingsphere-elasticjob-ui-frontend/src/lang/zh-CN.js
@@ -20,38 +20,47 @@ export default {
     home: '主页',
     menuData: [
       {
-        title: '配置中心',
+        title: '全局配置',
         child: [
           {
-            title: '服务列表',
-            href: '/config-center'
+            title: '注册中心配置',
+            href: '/registry-center'
           },
           {
-            title: '配置管理',
-            href: '/rule-config'
+            title: '事件追踪数据源配置',
+            href: '/data-source'
           }
         ]
       },
       {
-        title: '注册中心',
+        title: '作业操作',
         child: [
           {
-            title: '服务列表',
-            href: '/registry-center'
+            title: '作业维度',
+            href: '/operation-jobs'
           },
           {
-            title: '运行状态',
-            href: '/runtime-status'
+            title: '服务器维度',
+            href: '/operation-servers'
           }
         ]
       },
       {
-        title: '数据扩容',
-        href: '/data-scaling'
+        title: '作业历史',
+        child: [
+          {
+            title: '历史轨迹',
+            href: '/history-trace'
+          },
+          {
+            title: '历史状态',
+            href: '/history-status'
+          }
+        ]
       },
       {
-        title: '节点状态',
-        href: '/cluster-state'
+        title: '帮助',
+        href: '/job-help'
       }
     ],
     connect: '已连接',