You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by se...@apache.org on 2021/01/22 13:01:38 UTC

[ignite-3] branch main updated: IGNITE-13836 Support for multiple configuration roots, REST module improvements (#14)

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

sergeychugunov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 02512fe  IGNITE-13836 Support for multiple configuration roots, REST module improvements (#14)
02512fe is described below

commit 02512fe1970b5b9703b9296d178893f879fb7b8a
Author: Sergey Chugunov <se...@gmail.com>
AuthorDate: Fri Jan 22 15:58:09 2021 +0300

    IGNITE-13836 Support for multiple configuration roots, REST module improvements (#14)
---
 modules/configuration-annotation-processor/pom.xml |  12 ++
 .../processor/internal/Processor.java              |  32 ++++-
 .../processor/internal/HasFieldMatcher.java        |   2 +-
 .../processor/internal/HasMethodMatcher.java       |   2 +-
 .../processor/internal/ProcessorTest.java          |  11 +-
 .../sample/CacheConfigurationSchema.java           |   1 +
 .../sample/ClusterWideConfigurationSchema.java     |   1 +
 ...hema.java => DiscoveryConfigurationSchema.java} |  14 +-
 .../sample/NetworkConfigurationSchema.java}        |  16 ++-
 .../ignite/configuration/sample/UsageTest.java     |  78 ++++++++---
 .../configuration/ConfigurationRegistry.java}      |  25 +++-
 .../apache/ignite/configuration/Configurator.java  |  17 +++
 .../org/apache/ignite/configuration/RootKey.java}  |  15 +-
 .../src/main/resources/bootstrap-config.json       |   1 -
 modules/{ignite-runner => rest}/pom.xml            |  34 +++--
 .../java/org/apache/ignite/rest/ErrorResult.java   |   0
 .../java/org/apache/ignite/rest/RestModule.java    | 153 +++++++++++++--------
 .../configuration}/RestConfigurationSchema.java    |   5 +-
 .../presentation/ConfigurationPresentation.java    |  52 +++++++
 .../ignite/rest}/presentation/FormatConverter.java |   7 +-
 .../rest}/presentation/json/JsonConverter.java     |  17 ++-
 .../rest/presentation/json/JsonPresentation.java   |  83 +++++++++++
 modules/{ignite-runner => runner}/pom.xml          |   7 +
 .../java/org/apache/ignite/app/IgniteRunner.java   |  52 +++++--
 .../ignite/configuration/ConfigurationModule.java  |  38 ++---
 .../extended/AutoAdjustConfigurationSchema.java    |   1 -
 .../extended/BaselineConfigurationSchema.java      |   0
 .../extended/DataStorageConfigurationSchema.java   |   0
 .../extended/LocalConfigurationSchema.java         |   4 -
 .../org/apache/ignite/utils/IgniteProperties.java  |   0
 .../src/main/resources/bootstrap-config.json       |  19 +++
 .../src/main/resources/ignite.properties           |   0
 .../src/main/resources/simplelogger.properties     |   0
 parent/pom.xml                                     |   7 +
 pom.xml                                            |   5 +-
 35 files changed, 529 insertions(+), 182 deletions(-)

diff --git a/modules/configuration-annotation-processor/pom.xml b/modules/configuration-annotation-processor/pom.xml
index a986a59..f74d5fd 100644
--- a/modules/configuration-annotation-processor/pom.xml
+++ b/modules/configuration-annotation-processor/pom.xml
@@ -64,6 +64,18 @@
             <groupId>com.google.testing.compile</groupId>
             <artifactId>compile-testing</artifactId>
             <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+            <scope>test</scope>
         </dependency>
 
         <dependency>
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Processor.java b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Processor.java
index 50d10c9..b86a3c5 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Processor.java
+++ b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Processor.java
@@ -55,6 +55,7 @@ import javax.lang.model.util.Elements;
 import org.apache.ignite.configuration.ConfigurationTree;
 import org.apache.ignite.configuration.ConfigurationValue;
 import org.apache.ignite.configuration.Configurator;
+import org.apache.ignite.configuration.RootKey;
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.ConfigValue;
 import org.apache.ignite.configuration.annotation.NamedConfigValue;
@@ -273,6 +274,9 @@ public class Processor extends AbstractProcessor {
             // Create VIEW, INIT and CHANGE classes
             createPojoBindings(packageName, fields, schemaClassName, configurationClassBuilder, configurationInterfaceBuilder);
 
+            if (isRoot)
+                createRootKeyField(configInterface, configurationClassBuilder, configDesc);
+
             // Create constructors for configuration class
             createConstructors(configClass, configName, configurationClassBuilder, CONFIGURATOR_TYPE, constructorBodyBuilder, copyConstructorBodyBuilder);
 
@@ -313,6 +317,32 @@ public class Processor extends AbstractProcessor {
         return true;
     }
 
+    /** */
+    private void createRootKeyField(ClassName configInterface,
+        TypeSpec.Builder configurationClassBuilder,
+        ConfigurationDescription configDesc) {
+
+        ParameterizedTypeName fieldTypeName = ParameterizedTypeName.get(ClassName.get(RootKey.class), configInterface);
+
+        TypeSpec anonymousClass = TypeSpec.anonymousClassBuilder("")
+            .addSuperinterface(fieldTypeName)
+            .addMethod(MethodSpec
+                .methodBuilder("key")
+                .addAnnotation(Override.class)
+                .addModifiers(PUBLIC)
+                .returns(TypeName.get(String.class))
+                .addStatement("return $S", configDesc.getName())
+                .build()).build();
+
+        FieldSpec keyField = FieldSpec.builder(
+            fieldTypeName, "KEY", PUBLIC, STATIC
+            )
+            .initializer("$L", anonymousClass)
+            .build();
+
+        configurationClassBuilder.addField(keyField);
+    }
+
     /**
      * Create getters and setters for configuration class.
      *
@@ -589,7 +619,6 @@ public class Processor extends AbstractProcessor {
 
                 if (current.getParent() != null) {
                     String newMethodCall = "." + current.getOriginalName() + "()";
-
                     // if config is named, then create a call with name parameter
                     if (isNamed)
                         newMethodCall += ".get(name" + (namedCount - 1) + ")";
@@ -618,7 +647,6 @@ public class Processor extends AbstractProcessor {
                         .build()
                 );
 
-
                 // Build a list of parameters for statement
                 List<Object> params = new ArrayList<>();
                 params.add(MethodHandle.class);
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasFieldMatcher.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasFieldMatcher.java
index 7b729fd..53836cc 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasFieldMatcher.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasFieldMatcher.java
@@ -54,7 +54,7 @@ public class HasFieldMatcher extends BaseMatcher<ParsedClass> {
 
         List<HasFieldMatcher> matcherList = new ArrayList<>();
 
-        for (int i = 0; i < arguments.length; i+=2)
+        for (int i = 0; i < arguments.length; i += 2)
             matcherList.add(new HasFieldMatcher(arguments[i], arguments[i + 1]));
 
         return new BaseMatcher<ParsedClass>() {
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasMethodMatcher.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasMethodMatcher.java
index 385a280..c4642ea 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasMethodMatcher.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/HasMethodMatcher.java
@@ -50,7 +50,7 @@ public class HasMethodMatcher extends BaseMatcher<ParsedClass> {
 
         List<HasMethodMatcher> matcherList = new ArrayList<>();
 
-        for (int i = 0; i < arguments.length; i+=2)
+        for (int i = 0; i < arguments.length; i += 2)
             matcherList.add(new HasMethodMatcher(arguments[i], arguments[i + 1]));
 
         return new BaseMatcher<ParsedClass>() {
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/ProcessorTest.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/ProcessorTest.java
index dc361dc..68b19c6 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/ProcessorTest.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/processor/internal/ProcessorTest.java
@@ -16,14 +16,15 @@
  */
 package org.apache.ignite.configuration.processor.internal;
 
-import com.google.testing.compile.CompilationSubject;
+import com.google.testing.compile.Compilation;
 import com.squareup.javapoet.ClassName;
 import org.hamcrest.MatcherAssert;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.configuration.processor.internal.HasFieldMatcher.hasFields;
 import static org.apache.ignite.configuration.processor.internal.HasMethodMatcher.hasMethods;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
@@ -41,7 +42,9 @@ public class ProcessorTest extends AbstractProcessorTest {
 
         final BatchCompilation batch = batchCompile(testConfigurationSchema);
 
-        CompilationSubject.assertThat(batch.getCompilationStatus()).succeeded();
+        final Compilation status = batch.getCompilationStatus();
+
+        assertNotEquals(Compilation.Status.FAILURE, status);
 
         assertEquals(7, batch.generated().size());
 
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java
index e6da55b..8d35e66 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java
@@ -20,6 +20,7 @@ package org.apache.ignite.configuration.sample;
 import javax.validation.constraints.Min;
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.Value;
+
 /**
  * Test cache configuration schema.
  */
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/ClusterWideConfigurationSchema.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/ClusterWideConfigurationSchema.java
index 2c51d25..8594c87 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/ClusterWideConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/ClusterWideConfigurationSchema.java
@@ -20,6 +20,7 @@ package org.apache.ignite.configuration.sample;
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.ConfigValue;
 import org.apache.ignite.configuration.annotation.NamedConfigValue;
+
 /**
  * Test cluster wide configuration schema.
  */
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/DiscoveryConfigurationSchema.java
similarity index 80%
copy from modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/DiscoveryConfigurationSchema.java
index e6da55b..289878d 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/CacheConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/DiscoveryConfigurationSchema.java
@@ -17,17 +17,19 @@
 
 package org.apache.ignite.configuration.sample;
 
-import javax.validation.constraints.Min;
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.Value;
+
 /**
- * Test cache configuration schema.
+ * Test discovery configuration schema.
  */
 @Config
-public class CacheConfigurationSchema {
-    /** Size. */
+public class DiscoveryConfigurationSchema {
+    /** Node failure detection timeout. */
     @Value
-    @Min(value = 1, message = "Minimal cache size is 1")
-    private int size;
+    private int failureDetectionTimeout;
 
+    /** Node join timeout. */
+    @Value
+    private int joinTimeout;
 }
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/NetworkConfigurationSchema.java
similarity index 78%
copy from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java
copy to modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/NetworkConfigurationSchema.java
index 930c67b..8f2fb7f 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/NetworkConfigurationSchema.java
@@ -15,15 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.configuration.extended;
+package org.apache.ignite.configuration.sample;
 
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.ConfigValue;
 
-/** */
-@Config
-public class BaselineConfigurationSchema {
-    /** */
+/**
+ * Test network configuration schema.
+ */
+@Config(value = "network", root = true)
+public class NetworkConfigurationSchema {
+    /** Discovery. */
     @ConfigValue
-    private AutoAdjustConfigurationSchema autoAdjust;
+    private DiscoveryConfigurationSchema discovery;
+
+
 }
diff --git a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java
index d200efc..f1ea2d9 100644
--- a/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java
+++ b/modules/configuration-annotation-processor/src/test/java/org/apache/ignite/configuration/sample/UsageTest.java
@@ -21,41 +21,41 @@ import java.io.Serializable;
 import java.util.Collections;
 import java.util.function.Consumer;
 import org.apache.ignite.configuration.Configurator;
+import org.apache.ignite.configuration.ConfigurationRegistry;
 import org.apache.ignite.configuration.internal.NamedList;
 import org.apache.ignite.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.configuration.storage.StorageException;
 import org.apache.ignite.configuration.validation.ConfigurationValidationException;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.apache.ignite.configuration.PublicConfigurator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
 /**
  * Simple usage test of generated configuration schema.
  */
 public class UsageTest {
+    private final ConfigurationStorage storage = new ConfigurationStorage() {
+        @Override public <T extends Serializable> void save(String propertyName, T object) throws StorageException {
+
+        }
+
+        @Override public <T extends Serializable> T get(String propertyName) throws StorageException {
+            return null;
+        }
+
+        @Override
+        public <T extends Serializable> void listen(String key, Consumer<T> listener) throws StorageException {
+
+        }
+    };
 
     /**
      * Test creation of configuration and calling configuration API methods.
      */
     @Test
     public void test() {
-        final ConfigurationStorage storage = new ConfigurationStorage() {
-
-            @Override
-            public <T extends Serializable> void save(String propertyName, T object) {
-
-            }
-
-            @Override
-            public <T extends Serializable> T get(String propertyName) {
-                return null;
-            }
-
-            @Override
-            public <T extends Serializable> void listen(String key, Consumer<T> listener) {
-
-            }
-        };
-
         InitLocal initLocal = new InitLocal().withBaseline(
             new InitBaseline()
                 .withNodes(
@@ -84,7 +84,7 @@ public class UsageTest {
         configurator.getRoot().baseline().autoAdjust().enabled(true);
         configurator.getRoot().baseline().nodes().get("node1").autoAdjustEnabled(true);
 
-        try{
+        try {
             configurator.getRoot().baseline().autoAdjust().enabled(false);
             Assertions.fail();
         } catch (ConfigurationValidationException e) {}
@@ -92,4 +92,44 @@ public class UsageTest {
         PublicConfigurator<LocalConfiguration> con = new PublicConfigurator<>(configurator);
     }
 
+    /**
+     * Test to show an API to work with multiroot configurations.
+     */
+    @Test
+    public void multiRootConfigurationTest() {
+        ConfigurationRegistry sysConf = new ConfigurationRegistry();
+
+        int failureDetectionTimeout = 30_000;
+        int joinTimeout = 10_000;
+
+        long autoAdjustTimeout = 30_000L;
+
+        InitNetwork initNetwork = new InitNetwork().withDiscovery(
+            new InitDiscovery()
+                .withFailureDetectionTimeout(failureDetectionTimeout)
+                .withJoinTimeout(joinTimeout)
+        );
+
+        InitLocal initLocal = new InitLocal().withBaseline(
+            new InitBaseline().withAutoAdjust(
+                new InitAutoAdjust().withEnabled(true)
+                    .withTimeout(autoAdjustTimeout))
+        );
+
+        Configurator<LocalConfigurationImpl> localConf = Configurator.create(storage,
+            LocalConfigurationImpl::new, initLocal);
+
+        sysConf.registerConfigurator(localConf);
+
+        Configurator<NetworkConfigurationImpl> networkConf = Configurator.create(storage,
+            NetworkConfigurationImpl::new, initNetwork);
+
+        sysConf.registerConfigurator(networkConf);
+
+        assertEquals(failureDetectionTimeout,
+            sysConf.getConfiguration(NetworkConfigurationImpl.KEY).discovery().failureDetectionTimeout().value());
+
+        assertEquals(autoAdjustTimeout,
+            sysConf.getConfiguration(LocalConfigurationImpl.KEY).baseline().autoAdjust().timeout().value());
+    }
 }
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/FormatConverter.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java
similarity index 51%
copy from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/FormatConverter.java
copy to modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java
index 6bba4cf..356d8e5 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/FormatConverter.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/ConfigurationRegistry.java
@@ -15,21 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.configuration.presentation;
+package org.apache.ignite.configuration;
 
-import java.io.Reader;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.configuration.internal.DynamicConfiguration;
 
 /** */
-public interface FormatConverter {
+public class ConfigurationRegistry {
     /** */
-    String convertTo(Object obj);
+    private final Map<String, Configurator<?>> configs = new HashMap<>();
 
     /** */
-    String convertTo(String rootName, Object obj);
+    public <T extends DynamicConfiguration<?, ?, ?>> void registerConfigurator(Configurator<T> unitConfig) {
+        String key = unitConfig.getRoot().key();
+
+        configs.put(key, unitConfig);
+    }
 
     /** */
-    <T> T convertFrom(String source, String rootName, Class<T> clazz);
+    public <V, C, T extends ConfigurationTree<V, C>> T getConfiguration(RootKey<T> rootKey) {
+        return (T) configs.get(rootKey.key()).getRoot();
+    }
 
     /** */
-    <T> T convertFrom(Reader source, String rootName, Class<T> clazz);
+    public Map<String, Configurator<? extends DynamicConfiguration<?, ?, ?>>> getConfigurators() {
+        return Collections.unmodifiableMap(configs);
+    }
 }
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/Configurator.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/Configurator.java
index 6150b60..3e3592a 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/configuration/Configurator.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/Configurator.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.configuration;
 
 import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -119,6 +121,21 @@ public class Configurator<T extends DynamicConfiguration<?, ?, ?>> {
     }
 
     /**
+     * 
+     */
+    public Class<?> getChangeType() {
+        Type sClass = root.getClass().getGenericSuperclass();
+
+        assert sClass instanceof ParameterizedType;
+
+        ParameterizedType pt = (ParameterizedType)sClass;
+
+        assert pt.getActualTypeArguments().length == 3;
+
+        return (Class<?>) pt.getActualTypeArguments()[2];
+    }
+
+    /**
      *
      * @param selector
      * @param newValue
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/rest/ErrorResult.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/RootKey.java
similarity index 75%
copy from modules/ignite-runner/src/main/java/org/apache/ignite/rest/ErrorResult.java
copy to modules/configuration/src/main/java/org/apache/ignite/configuration/RootKey.java
index 431f3d1..488eb03 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/rest/ErrorResult.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/RootKey.java
@@ -15,19 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.rest;
+package org.apache.ignite.configuration;
 
 /** */
-public class ErrorResult {
+public interface RootKey<T extends ConfigurationTree<?, ?>> {
     /** */
-    private final String type;
-
-    /** */
-    private final String message;
-
-    /** */
-    public ErrorResult(String type, String message) {
-        this.type = type;
-        this.message = message;
-    }
+    public String key();
 }
diff --git a/modules/ignite-runner/src/main/resources/bootstrap-config.json b/modules/ignite-runner/src/main/resources/bootstrap-config.json
deleted file mode 100644
index b9fd7a1..0000000
--- a/modules/ignite-runner/src/main/resources/bootstrap-config.json
+++ /dev/null
@@ -1 +0,0 @@
-{"local":{"rest":{"port":10300,"portRange":100},"baseline":{"autoAdjust":{"timeout":10000,"enabled":true}},"dataStorage": {"pageSize":4096,"storagePath":"db/data","walPath":"db/wal"}}}
diff --git a/modules/ignite-runner/pom.xml b/modules/rest/pom.xml
similarity index 84%
copy from modules/ignite-runner/pom.xml
copy to modules/rest/pom.xml
index f527e09..79849e9 100644
--- a/modules/ignite-runner/pom.xml
+++ b/modules/rest/pom.xml
@@ -26,13 +26,12 @@
 
     <parent>
         <groupId>org.apache.ignite</groupId>
-        <artifactId>ignite-parent</artifactId>
-        <version>1</version>
-        <relativePath>../../parent/pom.xml</relativePath>
+        <artifactId>apache-ignite</artifactId>
+        <version>3.0.0-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
     </parent>
 
-    <artifactId>ignite-runner</artifactId>
-    <version>3.0.0-SNAPSHOT</version>
+    <artifactId>ignite-rest</artifactId>
 
     <dependencies>
         <dependency>
@@ -42,14 +41,6 @@
         </dependency>
 
         <dependency>
-            <groupId>org.apache.ignite</groupId>
-            <artifactId>ignite-configuration-annotation-processor</artifactId>
-            <version>${project.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <!-- 3rd party dependencies. -->
-        <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
         </dependency>
@@ -63,6 +54,13 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-simple</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-configuration-annotation-processor</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>
@@ -72,5 +70,13 @@
                 <filtering>true</filtering>
             </resource>
         </resources>
+
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+            </plugin>
+        </plugins>
     </build>
-</project>
+</project>
\ No newline at end of file
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/rest/ErrorResult.java b/modules/rest/src/main/java/org/apache/ignite/rest/ErrorResult.java
similarity index 100%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/rest/ErrorResult.java
rename to modules/rest/src/main/java/org/apache/ignite/rest/ErrorResult.java
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/rest/RestModule.java b/modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java
similarity index 65%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/rest/RestModule.java
rename to modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java
index 87fb2e6..7a77b05 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/rest/RestModule.java
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/RestModule.java
@@ -19,16 +19,19 @@ package org.apache.ignite.rest;
 
 import com.google.gson.JsonSyntaxException;
 import io.javalin.Javalin;
-import org.apache.ignite.configuration.ConfigurationModule;
+import java.io.Reader;
 import org.apache.ignite.configuration.Configurator;
-import org.apache.ignite.configuration.extended.ChangeLocal;
-import org.apache.ignite.configuration.extended.Local;
-import org.apache.ignite.configuration.extended.LocalConfigurationImpl;
-import org.apache.ignite.configuration.extended.Selectors;
+import org.apache.ignite.configuration.ConfigurationRegistry;
 import org.apache.ignite.configuration.internal.selector.SelectorNotFoundException;
-import org.apache.ignite.configuration.presentation.FormatConverter;
-import org.apache.ignite.configuration.presentation.json.JsonConverter;
+import org.apache.ignite.rest.presentation.ConfigurationPresentation;
+import org.apache.ignite.rest.presentation.FormatConverter;
+import org.apache.ignite.rest.presentation.json.JsonConverter;
+import org.apache.ignite.rest.presentation.json.JsonPresentation;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
 import org.apache.ignite.configuration.validation.ConfigurationValidationException;
+import org.apache.ignite.rest.configuration.InitRest;
+import org.apache.ignite.rest.configuration.RestConfigurationImpl;
+import org.apache.ignite.rest.configuration.Selectors;
 import org.slf4j.Logger;
 
 /**
@@ -48,80 +51,58 @@ public class RestModule {
     private static final String PATH_PARAM = "selector";
 
     /** */
-    private final ConfigurationModule confModule;
+    private ConfigurationRegistry sysConf;
+
+    /** */
+    private volatile ConfigurationPresentation<String> presentation;
 
     /** */
     private final Logger log;
 
     /** */
-    public RestModule(ConfigurationModule confModule, Logger log) {
-        this.confModule = confModule;
+    public RestModule(Logger log) {
         this.log = log;
     }
 
     /** */
-    public void start() {
-        Configurator<LocalConfigurationImpl> configurator = confModule.localConfigurator();
-
-        Integer port = configurator.getPublic(Selectors.LOCAL_REST_PORT);
-        Integer portRange = configurator.getPublic(Selectors.LOCAL_REST_PORT_RANGE);
-        Javalin app = null;
-
-        if (portRange == null || portRange == 0) {
-            try {
-                app = Javalin.create().start(port != null ? port : DFLT_PORT);
-            }
-            catch (RuntimeException e) {
-                log.warn("Failed to start REST endpoint: ", e);
-
-                throw e;
-            }
+    public void prepareStart(ConfigurationRegistry sysConfig, Reader moduleConfReader, ConfigurationStorage storage) {
+        try {
+            Class.forName(Selectors.class.getName());
+        }
+        catch (ClassNotFoundException e) {
+            // No-op.
         }
-        else {
-            int startPort = port;
 
-            for (int portCandidate = startPort; portCandidate < startPort + portRange; portCandidate++) {
-                try {
-                    app = Javalin.create().start(portCandidate);
-                }
-                catch (RuntimeException ignored) {
-                    // No-op.
-                }
+        sysConf = sysConfig;
 
-                if (app != null)
-                    break;
-            }
+        presentation = new JsonPresentation(sysConfig.getConfigurators());
 
-            if (app == null) {
-                String msg = "Cannot start REST endpoint. " +
-                    "All ports in range [" + startPort + ", " + (startPort + portRange) + ") are in use.";
+        FormatConverter converter = new JsonConverter();
 
-                log.warn(msg);
+        Configurator<RestConfigurationImpl> restConf = Configurator.create(storage, RestConfigurationImpl::new,
+            converter.convertFrom(moduleConfReader, "rest", InitRest.class));
 
-                throw new RuntimeException(msg);
-            }
-        }
+        sysConfig.registerConfigurator(restConf);
+    }
 
-        log.info("REST protocol started successfully on port " + app.port());
+    /** */
+    public void start() {
+        Javalin app = startRestEndpoint();
 
         FormatConverter converter = new JsonConverter();
 
         app.get(CONF_URL, ctx -> {
-            Local local = configurator.getRoot().value();
-
-            ctx.result(converter.convertTo("local", local));
+            ctx.result(presentation.represent());
         });
 
         app.get(CONF_URL + ":" + PATH_PARAM, ctx -> {
-            try {
-                Object subTree = configurator.getPublic(Selectors.find(ctx.pathParam(PATH_PARAM)));
-
-                String res = converter.convertTo(subTree);
+            String configPath = ctx.pathParam(PATH_PARAM);
 
-                ctx.result(res);
+            try {
+                ctx.result(presentation.representByPath(configPath));
             }
-            catch (SelectorNotFoundException selectorE) {
-                ErrorResult eRes = new ErrorResult("CONFIG_PATH_UNRECOGNIZED", selectorE.getMessage());
+            catch (SelectorNotFoundException | IllegalArgumentException pathE) {
+                ErrorResult eRes = new ErrorResult("CONFIG_PATH_UNRECOGNIZED", pathE.getMessage());
 
                 ctx.status(400).result(converter.convertTo("error", eRes));
             }
@@ -129,12 +110,10 @@ public class RestModule {
 
         app.post(CONF_URL, ctx -> {
             try {
-                ChangeLocal local = converter.convertFrom(ctx.body(), "local", ChangeLocal.class);
-
-                configurator.set(Selectors.LOCAL, local);
+                presentation.update(ctx.body());
             }
-            catch (SelectorNotFoundException selectorE) {
-                ErrorResult eRes = new ErrorResult("CONFIG_PATH_UNRECOGNIZED", selectorE.getMessage());
+            catch (SelectorNotFoundException | IllegalArgumentException argE) {
+                ErrorResult eRes = new ErrorResult("CONFIG_PATH_UNRECOGNIZED", argE.getMessage());
 
                 ctx.status(400).result(converter.convertTo("error", eRes));
             }
@@ -157,4 +136,56 @@ public class RestModule {
             }
         });
     }
+
+    /** */
+    private Javalin startRestEndpoint() {
+        Integer port = sysConf.getConfiguration(RestConfigurationImpl.KEY).port().value();
+        Integer portRange = sysConf.getConfiguration(RestConfigurationImpl.KEY).portRange().value();
+
+        Javalin app = null;
+
+        if (portRange == null || portRange == 0) {
+            try {
+                app = Javalin.create().start(port != null ? port : DFLT_PORT);
+            }
+            catch (RuntimeException e) {
+                log.warn("Failed to start REST endpoint: ", e);
+
+                throw e;
+            }
+        }
+        else {
+            int startPort = port;
+
+            for (int portCandidate = startPort; portCandidate < startPort + portRange; portCandidate++) {
+                try {
+                    app = Javalin.create().start(portCandidate);
+                }
+                catch (RuntimeException ignored) {
+                    // No-op.
+                }
+
+                if (app != null)
+                    break;
+            }
+
+            if (app == null) {
+                String msg = "Cannot start REST endpoint. " +
+                    "All ports in range [" + startPort + ", " + (startPort + portRange) + ") are in use.";
+
+                log.warn(msg);
+
+                throw new RuntimeException(msg);
+            }
+        }
+
+        log.info("REST protocol started successfully on port " + app.port());
+
+        return app;
+    }
+
+    /** */
+    public String configRootKey() {
+        return "rest";
+    }
 }
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/RestConfigurationSchema.java b/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
similarity index 92%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/RestConfigurationSchema.java
rename to modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
index d25c61c..e842c9a 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/RestConfigurationSchema.java
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/configuration/RestConfigurationSchema.java
@@ -15,13 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.configuration.extended;
+package org.apache.ignite.rest.configuration;
 
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.Value;
 
-/** */
-@Config
+@Config(value = "rest", root = true)
 public class RestConfigurationSchema {
     /** */
     @Value
diff --git a/modules/rest/src/main/java/org/apache/ignite/rest/presentation/ConfigurationPresentation.java b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/ConfigurationPresentation.java
new file mode 100644
index 0000000..53b3653
--- /dev/null
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/ConfigurationPresentation.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.ignite.rest.presentation;
+
+/** */
+public interface ConfigurationPresentation<R> {
+    /**
+     * Converts to presentation whole system configuration (all system modules are included).
+     *
+     * @return System configuration presentation converted to a given presentation type.
+     */
+    R represent();
+
+    /**
+     * Converts to presentation only a fraction of system configuration defined by given path.
+     *
+     * If null path is passed method should fall back to returning whole system configuration.
+     *
+     * @param path Path to requested configuration in configuration tree or {@code null}.
+     *
+     * @return Requested configuration fraction or whole configuration if {@code null} was passed.
+     */
+    R representByPath(String path);
+
+    /**
+     * Converts and applies configuration update request to system configuration.
+     *
+     * Note: for simplisity on this stage of development it is supposed that update request
+     * contains only one root to update despite of multiroot configuration is supported.
+     *
+     * To support updating multiple roots at once more logic should be implemented including
+     * support in {@link FormatConverter} subclasses.
+     *
+     * @param configUpdate Configuration update request in representation form.
+     */
+    void update(R configUpdate);
+}
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/FormatConverter.java b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/FormatConverter.java
similarity index 86%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/FormatConverter.java
rename to modules/rest/src/main/java/org/apache/ignite/rest/presentation/FormatConverter.java
index 6bba4cf..eee1d16 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/FormatConverter.java
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/FormatConverter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.configuration.presentation;
+package org.apache.ignite.rest.presentation;
 
 import java.io.Reader;
 
@@ -28,7 +28,10 @@ public interface FormatConverter {
     String convertTo(String rootName, Object obj);
 
     /** */
-    <T> T convertFrom(String source, String rootName, Class<T> clazz);
+    String rootName(String source);
+
+    /** */
+    Object convertFrom(String source, String rootName, Class<?> clazz);
 
     /** */
     <T> T convertFrom(Reader source, String rootName, Class<T> clazz);
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/json/JsonConverter.java b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/json/JsonConverter.java
similarity index 74%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/json/JsonConverter.java
rename to modules/rest/src/main/java/org/apache/ignite/rest/presentation/json/JsonConverter.java
index 5622e2f..4156f14 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/presentation/json/JsonConverter.java
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/json/JsonConverter.java
@@ -15,14 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.configuration.presentation.json;
+package org.apache.ignite.rest.presentation.json;
 
 import java.io.Reader;
 
 import com.google.gson.Gson;
 import java.util.HashMap;
 import java.util.Map;
-import org.apache.ignite.configuration.presentation.FormatConverter;
+import java.util.Optional;
+import org.apache.ignite.rest.presentation.FormatConverter;
 
 /** */
 public class JsonConverter implements FormatConverter {
@@ -44,7 +45,17 @@ public class JsonConverter implements FormatConverter {
     }
 
     /** {@inheritDoc} */
-    @Override public <T> T convertFrom(String source, String rootName, Class<T> clazz) {
+    @Override public String rootName(String source) {
+        Map<String, Object> map = gson.fromJson(source, Map.class);
+
+        // Peek only first root for simplicite. See comment in ConfigurationPresentation#update for more context.
+        Optional<String> firstOpt = map.keySet().stream().findFirst();
+
+        return firstOpt.isPresent() ? firstOpt.get() : null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object convertFrom(String source, String rootName, Class<?> clazz) {
         Map map = gson.fromJson(source, Map.class);
 
         String root = gson.toJson(map.get(rootName));
diff --git a/modules/rest/src/main/java/org/apache/ignite/rest/presentation/json/JsonPresentation.java b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/json/JsonPresentation.java
new file mode 100644
index 0000000..1d54253
--- /dev/null
+++ b/modules/rest/src/main/java/org/apache/ignite/rest/presentation/json/JsonPresentation.java
@@ -0,0 +1,83 @@
+/*
+ * 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.ignite.rest.presentation.json;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.ignite.configuration.ConfigurationProperty;
+import org.apache.ignite.configuration.Configurator;
+import org.apache.ignite.configuration.internal.DynamicConfiguration;
+import org.apache.ignite.configuration.internal.selector.BaseSelectors;
+import org.apache.ignite.rest.presentation.ConfigurationPresentation;
+
+/** */
+public class JsonPresentation implements ConfigurationPresentation<String> {
+    /** */
+    private final JsonConverter converter = new JsonConverter();
+
+    /** */
+    private final Map<String, Configurator<? extends DynamicConfiguration<?, ?, ?>>> configsMap;
+
+    /** */
+    public JsonPresentation(Map<String, Configurator<? extends DynamicConfiguration<?, ?, ?>>> configsMap) {
+        this.configsMap = configsMap;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String represent() {
+        Map<String, ?> preparedMap = configsMap.entrySet().stream().collect(Collectors.toMap(
+            e -> e.getKey(),
+            e -> e.getValue().getRoot().value()
+        ));
+
+        return converter.convertTo(preparedMap);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String representByPath(String path) {
+        if (path == null || path.isEmpty())
+            return represent();
+
+        String root = path.contains(".") ? path.substring(0, path.indexOf('.')) : path;
+
+        Configurator<? extends DynamicConfiguration<?, ?, ?>> configurator = configsMap.get(root);
+
+        ConfigurationProperty<Object, Object> prop = configurator.getInternal(BaseSelectors.find(path));
+
+        return converter.convertTo(prop.value());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void update(String configUpdate) {
+        String root = converter.rootName(configUpdate);
+
+        if (root == null) {
+            throw new IllegalArgumentException("Invalid request, no root in request: " + configUpdate);
+        }
+
+        Configurator<? extends DynamicConfiguration<?, ?, ?>> configurator = configsMap.get(root);
+
+        if (configurator == null) {
+            throw new IllegalArgumentException("Invalid request, configuration root not found: " + configUpdate);
+        }
+
+        Object updateObj = converter.convertFrom(configUpdate, root, configurator.getChangeType());
+
+        configurator.set(BaseSelectors.find(root), updateObj);
+    }
+}
diff --git a/modules/ignite-runner/pom.xml b/modules/runner/pom.xml
similarity index 91%
rename from modules/ignite-runner/pom.xml
rename to modules/runner/pom.xml
index f527e09..af05830 100644
--- a/modules/ignite-runner/pom.xml
+++ b/modules/runner/pom.xml
@@ -48,6 +48,13 @@
             <scope>compile</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-rest</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
         <!-- 3rd party dependencies. -->
         <dependency>
             <groupId>com.google.code.gson</groupId>
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java b/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
similarity index 73%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
rename to modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
index e336292..cb26484 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
+++ b/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
@@ -17,13 +17,17 @@
 
 package org.apache.ignite.app;
 
+import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.Reader;
 import java.util.Arrays;
 import java.util.stream.Collectors;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.util.function.Consumer;
 import org.apache.ignite.configuration.ConfigurationModule;
+import org.apache.ignite.configuration.storage.ConfigurationStorage;
 import org.apache.ignite.rest.RestModule;
 import org.apache.ignite.utils.IgniteProperties;
 import org.slf4j.Logger;
@@ -60,7 +64,25 @@ public class IgniteRunner {
     private static final String VER_KEY = "version";
 
     /** */
-    private final static Logger log = LoggerFactory.getLogger(IgniteRunner.class);
+    private static final Logger log = LoggerFactory.getLogger(IgniteRunner.class);
+
+    /** */
+    private static final ConfigurationStorage STORAGE = new ConfigurationStorage() {
+        /** {@inheritDoc} */
+        @Override public <T extends Serializable> void save(String propertyName, T object) {
+
+        }
+
+        /** {@inheritDoc} */
+        @Override public <T extends Serializable> T get(String propertyName) {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public <T extends Serializable> void listen(String key, Consumer<T> listener) {
+
+        }
+    };
 
     /**
      * It is possible to start application with a custom configuration in form of json file other than that in resources.
@@ -74,13 +96,15 @@ public class IgniteRunner {
 
         ConfigurationModule confModule = new ConfigurationModule();
 
-        Reader confReader = null;
+        RestModule restModule = new RestModule(log);
+
+        BufferedReader confReader = null;
 
         try {
             if (args != null) {
                 for (int i = 0; i < args.length; i++) {
                     if (CONF_PARAM_NAME.equals(args[i]) && i + 1 < args.length) {
-                        confReader = new FileReader(args[i + 1]);
+                        confReader = new BufferedReader(new FileReader(args[i + 1]));
 
                         break;
                     }
@@ -88,20 +112,28 @@ public class IgniteRunner {
             }
 
             if (confReader == null) {
-                confReader = new InputStreamReader(
-                    IgniteRunner.class.getClassLoader().getResourceAsStream(DFLT_CONF_FILE_NAME));
+                confReader = new BufferedReader(new InputStreamReader(
+                    IgniteRunner.class.getClassLoader().getResourceAsStream(DFLT_CONF_FILE_NAME)));
+            }
+
+            StringBuilder bldr = new StringBuilder();
+
+            String str;
+
+            while ((str = confReader.readLine()) != null) {
+                bldr.append(str);
             }
 
-            confModule.bootstrap(confReader);
+            restModule.prepareStart(confModule.configurationRegistry(), new StringReader(bldr.toString()), STORAGE);
+
+            confModule.bootstrap(new StringReader(bldr.toString()), STORAGE);
         }
         finally {
             if (confReader != null)
                 confReader.close();
         }
 
-        RestModule rest = new RestModule(confModule, log);
-
-        rest.start();
+        restModule.start();
 
         ackSuccessStart();
     }
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java b/modules/runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
similarity index 71%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
rename to modules/runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
index c04f5bf..65c89c7 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
+++ b/modules/runner/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
@@ -18,15 +18,13 @@
 package org.apache.ignite.configuration;
 
 import java.io.Reader;
-import java.io.Serializable;
-import java.util.function.Consumer;
 
 import org.apache.ignite.configuration.extended.InitLocal;
 import org.apache.ignite.configuration.extended.LocalConfigurationImpl;
 import org.apache.ignite.configuration.extended.Selectors;
-import org.apache.ignite.configuration.presentation.FormatConverter;
-import org.apache.ignite.configuration.presentation.json.JsonConverter;
 import org.apache.ignite.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.rest.presentation.FormatConverter;
+import org.apache.ignite.rest.presentation.json.JsonConverter;
 
 /**
  * Module is responsible for preparing configuration when module is started.
@@ -37,7 +35,7 @@ import org.apache.ignite.configuration.storage.ConfigurationStorage;
 public class ConfigurationModule {
     static {
         try {
-            Selectors.LOCAL_BASELINE_AUTO_ADJUST_ENABLED.select(null);
+            Selectors.LOCAL_BASELINE.select(null);
         }
         catch (Throwable ignored) {
             // No-op.
@@ -45,38 +43,32 @@ public class ConfigurationModule {
     }
 
     /** */
-    private final ConfigurationStorage storage = new ConfigurationStorage() {
-        /** {@inheritDoc} */
-        @Override public <T extends Serializable> void save(String propertyName, T object) {
-
-        }
-
-        /** {@inheritDoc} */
-        @Override public <T extends Serializable> T get(String propertyName) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public <T extends Serializable> void listen(String key, Consumer<T> listener) {
-
-        }
-    };
+    private Configurator<LocalConfigurationImpl> localConfigurator;
 
     /** */
-    private Configurator<LocalConfigurationImpl> localConfigurator;
+    private final ConfigurationRegistry confRegistry = new ConfigurationRegistry();
 
     /** */
-    public void bootstrap(Reader confReader) {
+    public void bootstrap(Reader confReader, ConfigurationStorage storage) {
         FormatConverter converter = new JsonConverter();
 
         Configurator<LocalConfigurationImpl> configurator =
             Configurator.create(storage, LocalConfigurationImpl::new, converter.convertFrom(confReader, "local", InitLocal.class));
 
         localConfigurator = configurator;
+
+        String key = configurator.getRoot().key();
+
+        confRegistry.registerConfigurator(configurator);
     }
 
     /** */
     public Configurator<LocalConfigurationImpl> localConfigurator() {
         return localConfigurator;
     }
+
+    /** */
+    public ConfigurationRegistry configurationRegistry() {
+        return confRegistry;
+    }
 }
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/AutoAdjustConfigurationSchema.java b/modules/runner/src/main/java/org/apache/ignite/configuration/extended/AutoAdjustConfigurationSchema.java
similarity index 99%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/AutoAdjustConfigurationSchema.java
rename to modules/runner/src/main/java/org/apache/ignite/configuration/extended/AutoAdjustConfigurationSchema.java
index c0bfaca..69df80d 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/AutoAdjustConfigurationSchema.java
+++ b/modules/runner/src/main/java/org/apache/ignite/configuration/extended/AutoAdjustConfigurationSchema.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.configuration.extended;
 
-
 import javax.validation.constraints.Min;
 import org.apache.ignite.configuration.annotation.Config;
 import org.apache.ignite.configuration.annotation.Value;
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java b/modules/runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java
similarity index 100%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java
rename to modules/runner/src/main/java/org/apache/ignite/configuration/extended/BaselineConfigurationSchema.java
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/DataStorageConfigurationSchema.java b/modules/runner/src/main/java/org/apache/ignite/configuration/extended/DataStorageConfigurationSchema.java
similarity index 100%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/DataStorageConfigurationSchema.java
rename to modules/runner/src/main/java/org/apache/ignite/configuration/extended/DataStorageConfigurationSchema.java
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/LocalConfigurationSchema.java b/modules/runner/src/main/java/org/apache/ignite/configuration/extended/LocalConfigurationSchema.java
similarity index 94%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/LocalConfigurationSchema.java
rename to modules/runner/src/main/java/org/apache/ignite/configuration/extended/LocalConfigurationSchema.java
index 60a1a9f..08903f8 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/configuration/extended/LocalConfigurationSchema.java
+++ b/modules/runner/src/main/java/org/apache/ignite/configuration/extended/LocalConfigurationSchema.java
@@ -27,10 +27,6 @@ import org.apache.ignite.configuration.annotation.ConfigValue;
 public class LocalConfigurationSchema {
     /** */
     @ConfigValue
-    private RestConfigurationSchema rest;
-
-    /** */
-    @ConfigValue
     private BaselineConfigurationSchema baseline;
 
     /** */
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/utils/IgniteProperties.java b/modules/runner/src/main/java/org/apache/ignite/utils/IgniteProperties.java
similarity index 100%
rename from modules/ignite-runner/src/main/java/org/apache/ignite/utils/IgniteProperties.java
rename to modules/runner/src/main/java/org/apache/ignite/utils/IgniteProperties.java
diff --git a/modules/runner/src/main/resources/bootstrap-config.json b/modules/runner/src/main/resources/bootstrap-config.json
new file mode 100644
index 0000000..1679263
--- /dev/null
+++ b/modules/runner/src/main/resources/bootstrap-config.json
@@ -0,0 +1,19 @@
+{
+  "local": {
+    "baseline": {
+      "autoAdjust": {
+        "timeout":10000,
+        "enabled":true
+      }
+    },
+    "dataStorage": {
+      "pageSize":4096,
+      "storagePath":"db/data",
+      "walPath":"db/wal"
+    }
+  },
+  "rest": {
+    "port":10300,
+    "portRange":100
+  }
+}
\ No newline at end of file
diff --git a/modules/ignite-runner/src/main/resources/ignite.properties b/modules/runner/src/main/resources/ignite.properties
similarity index 100%
rename from modules/ignite-runner/src/main/resources/ignite.properties
rename to modules/runner/src/main/resources/ignite.properties
diff --git a/modules/ignite-runner/src/main/resources/simplelogger.properties b/modules/runner/src/main/resources/simplelogger.properties
similarity index 100%
rename from modules/ignite-runner/src/main/resources/simplelogger.properties
rename to modules/runner/src/main/resources/simplelogger.properties
diff --git a/parent/pom.xml b/parent/pom.xml
index b0129a1..ac1fc7d 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -71,6 +71,7 @@
         <slf4j.version>1.7.30</slf4j.version>
         <spoon.framework.version>8.3.0</spoon.framework.version>
         <typesafe.version>1.4.1</typesafe.version>
+        <hamcrest.version>2.2</hamcrest.version>
 
         <!-- Plugins versions -->
         <apache.rat.plugin.version>0.13</apache.rat.plugin.version>
@@ -233,6 +234,12 @@
                 <artifactId>spoon-core</artifactId>
                 <version>${spoon.framework.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-library</artifactId>
+                <version>${hamcrest.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/pom.xml b/pom.xml
index 0e6b050..6ce3c26 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,9 +38,10 @@
         <module>modules/cli-common</module>
         <module>modules/configuration</module>
         <module>modules/configuration-annotation-processor</module>
-        <module>modules/ignite-runner</module>
+        <module>modules/rest</module>
+        <module>modules/runner</module>
     </modules>
-    
+
     <build>
         <plugins>
             <!--