http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/96522874/modules/control-center-web/src/main/js/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/metadata-controller.js 
b/modules/control-center-web/src/main/js/controllers/metadata-controller.js
new file mode 100644
index 0000000..c8fad8d
--- /dev/null
+++ b/modules/control-center-web/src/main/js/controllers/metadata-controller.js
@@ -0,0 +1,709 @@
+/*
+ * 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.
+ */
+
+controlCenterModule.controller('metadataController', ['$scope', '$http', 
'$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, 
$confirm, $copy, $table) {
+        $scope.joinTip = $common.joinTip;
+        $scope.getModel = $common.getModel;
+        $scope.javaBuildInTypes = $common.javaBuildInTypes;
+
+        $scope.tableReset = $table.tableReset;
+        $scope.tableNewItem = $table.tableNewItem;
+        $scope.tableNewItemActive = $table.tableNewItemActive;
+        $scope.tableEditing = $table.tableEditing;
+        $scope.tableStartEdit = $table.tableStartEdit;
+        $scope.tableRemove = $table.tableRemove;
+
+        $scope.tableSimpleSave = $table.tableSimpleSave;
+        $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
+        $scope.tableSimpleUp = $table.tableSimpleUp;
+        $scope.tableSimpleDown = $table.tableSimpleDown;
+        $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
+
+        $scope.tablePairSave = $table.tablePairSave;
+        $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+
+        $scope.templates = [
+            {value: {kind: 'query'}, label: 'query'},
+            {value: {kind: 'store'}, label: 'store'},
+            {value: {kind: 'both'}, label: 'both'}
+        ];
+
+        $scope.template = $scope.templates[0].value;
+
+        $scope.kinds = [
+            {value: 'query', label: 'query'},
+            {value: 'store', label: 'store'},
+            {value: 'both', label: 'both'}
+        ];
+
+        $scope.databases = [
+            {value: 'oracle', label: 'Oracle database'},
+            {value: 'db2', label: 'IBM DB2'},
+            {value: 'mssql', label: 'MS SQL Server'},
+            {value: 'postgre', label: 'PostgreSQL'},
+            {value: 'mysql', label: 'MySQL'},
+            {value: 'h2', label: 'H2 database'}
+        ];
+
+        $scope.jdbcTypes = [
+            {value: 'BIT', label: 'BIT'},
+            {value: 'BOOLEAN', label: 'BOOLEAN'},
+            {value: 'TINYINT', label: 'TINYINT'},
+            {value: 'SMALLINT', label: 'SMALLINT'},
+            {value: 'INTEGER', label: 'INTEGER'},
+            {value: 'BIGINT', label: 'BIGINT'},
+            {value: 'REAL', label: 'REAL'},
+            {value: 'FLOAT', label: 'FLOAT'},
+            {value: 'DOUBLE', label: 'DOUBLE'},
+            {value: 'NUMERIC', label: 'NUMERIC'},
+            {value: 'DECIMAL', label: 'DECIMAL'},
+            {value: 'CHAR', label: 'CHAR'},
+            {value: 'VARCHAR', label: 'VARCHAR'},
+            {value: 'LONGVARCHAR', label: 'LONGVARCHAR'},
+            {value: 'NCHAR', label: 'NCHAR'},
+            {value: 'NVARCHAR', label: 'NVARCHAR'},
+            {value: 'LONGNVARCHAR', label: 'LONGNVARCHAR'},
+            {value: 'DATE', label: 'DATE'},
+            {value: 'TIME', label: 'TIME'},
+            {value: 'TIMESTAMP', label: 'TIMESTAMP'}
+        ];
+
+        $scope.javaTypes = [
+            {value: 'boolean', label: 'boolean'},
+            {value: 'Boolean', label: 'Boolean'},
+            {value: 'byte', label: 'byte'},
+            {value: 'Byte', label: 'Byte'},
+            {value: 'short', label: 'short'},
+            {value: 'Short', label: 'Short'},
+            {value: 'int', label: 'int'},
+            {value: 'Integer', label: 'Integer'},
+            {value: 'long', label: 'long'},
+            {value: 'Long', label: 'Long'},
+            {value: 'float', label: 'float'},
+            {value: 'Float', label: 'Float'},
+            {value: 'double', label: 'double'},
+            {value: 'Double', label: 'Double'},
+            {value: 'BigDecimal', label: 'BigDecimal'},
+            {value: 'String', label: 'String'},
+            {value: 'Date', label: 'Date'},
+            {value: 'Time', label: 'Time'},
+            {value: 'Timestamp', label: 'Timestamp'}
+        ];
+
+        $scope.sortDirections = [
+            {value: false, label: 'ASC'},
+            {value: true, label: 'DESC'}
+        ];
+
+        $scope.data = {
+            curTableIdx: 0,
+            curFieldIdx: 0,
+            curKeyClass: '',
+            curValueClass: '',
+            curJavaName: '',
+            curJavaType: '',
+            tables: [
+                {schemaName: 'Schema1', use: true},
+                {
+                    schemaName: 'Schema1',
+                    use: true,
+                    tableName: 'Table1',
+                    keyClass: 'KeyClass1',
+                    valueClass: 'ValueClass1',
+                    fields: [
+                        {
+                            use: true,
+                            key: true,
+                            ak: true,
+                            databaseName: 'name1',
+                            databaseType: 'dbType1',
+                            javaName: 'javaName1',
+                            javaType: 'javaType1'
+                        },
+                        {
+                            use: true,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name2',
+                            databaseType: 'dbType2',
+                            javaName: 'javaName2',
+                            javaType: 'javaType2'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name3',
+                            databaseType: 'dbType3',
+                            javaName: 'javaName3',
+                            javaType: 'javaType3'
+                        }
+                    ]
+                },
+                {schemaName: 'Schema2 with very long name', use: false},
+                {
+                    schemaName: 'Schema2',
+                    use: false,
+                    tableName: 'Table2',
+                    keyClass: 'KeyClass2',
+                    valueClass: 'ValueClass2',
+                    fields: [
+                        {
+                            use: true,
+                            key: true,
+                            ak: true,
+                            databaseName: 'name4',
+                            databaseType: 'dbType4',
+                            javaName: 'javaName4',
+                            javaType: 'javaType4'
+                        },
+                        {
+                            use: true,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name5',
+                            databaseType: 'dbType5',
+                            javaName: 'javaName5',
+                            javaType: 'javaType5'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name6',
+                            databaseType: 'dbType6',
+                            javaName: 'javaName6',
+                            javaType: 'javaType6'
+                        }
+                    ]
+                },
+                {
+                    schemaName: 'Schema2',
+                    use: false,
+                    tableName: 'Table3',
+                    keyClass: 'KeyClass3',
+                    valueClass: 'ValueClass3',
+                    fields: [
+                        {
+                            use: true,
+                            key: true,
+                            ak: true,
+                            databaseName: 'name7',
+                            databaseType: 'dbType7',
+                            javaName: 'javaName7',
+                            javaType: 'javaType7'
+                        },
+                        {
+                            use: true,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name8',
+                            databaseType: 'dbType8',
+                            javaName: 'javaName8',
+                            javaType: 'javaType8'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name9',
+                            databaseType: 'dbType9',
+                            javaName: 'javaName9',
+                            javaType: 'javaType9'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name10',
+                            databaseType: 'dbType10',
+                            javaName: 'javaName10',
+                            javaType: 'javaType10'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name11',
+                            databaseType: 'dbType11',
+                            javaName: 'javaName11',
+                            javaType: 'javaType11'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            databaseName: 'name12',
+                            databaseType: 'dbType12',
+                            javaName: 'javaName12',
+                            javaType: 'javaType12'
+                        }
+                    ]
+                }]
+        };
+
+        $scope.metadatas = [];
+
+        $http.get('/models/metadata.json')
+            .success(function (data) {
+                $scope.screenTip = data.screenTip;
+                $scope.templateTip = data.templateTip;
+                $scope.metadataManual = data.metadataManual;
+                $scope.metadataDb = data.metadataDb;
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+
+        function selectFirstItem() {
+            if ($scope.metadatas.length > 0)
+                $scope.selectItem($scope.metadatas[0]);
+        }
+
+        function setSelectedAndBackupItem(sel, bak) {
+            $table.tableReset();
+
+            $scope.selectedItem = sel;
+            $scope.backupItem = bak;
+
+            $scope.panels.activePanel = [0];
+        }
+
+        // When landing on the page, get metadatas and show them.
+        $http.post('metadata/list')
+            .success(function (data) {
+                $scope.spaces = data.spaces;
+                $scope.metadatas = data.metadatas;
+
+                var restoredItem = 
angular.fromJson(sessionStorage.metadataBackupItem);
+
+                if (restoredItem) {
+                    if (restoredItem._id) {
+                        var idx = _.findIndex($scope.metadatas, function 
(metadata) {
+                            return metadata._id == restoredItem._id;
+                        });
+
+                        if (idx >= 0)
+                            setSelectedAndBackupItem($scope.metadatas[idx], 
restoredItem);
+                        else {
+                            sessionStorage.removeItem('metadataBackupItem');
+
+                            selectFirstItem();
+                        }
+                    }
+                    else
+                        setSelectedAndBackupItem(undefined, restoredItem);
+                }
+                else
+                    selectFirstItem();
+
+                $scope.$watch('backupItem', function (val) {
+                    if (val)
+                        sessionStorage.metadataBackupItem = 
angular.toJson(val);
+                }, true);
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+
+        $scope.selectItem = function (item) {
+            setSelectedAndBackupItem(item, angular.copy(item));
+        };
+
+        // Add new metadata.
+        $scope.createItem = function () {
+            $table.tableReset();
+
+            $scope.backupItem = angular.copy($scope.template);
+            $scope.backupItem.space = $scope.spaces[0]._id;
+        };
+
+        // Check metadata logical consistency.
+        function validate(item) {
+            return true;
+        }
+
+        // Save cache type metadata into database.
+        function save(item) {
+            $http.post('metadata/save', item)
+                .success(function (_id) {
+                    $common.showInfo('Metadata "' + item.name + '" saved.');
+
+                    var idx = _.findIndex($scope.metadatas, function 
(metadata) {
+                        return metadata._id == _id;
+                    });
+
+                    if (idx >= 0)
+                        angular.extend($scope.metadatas[idx], item);
+                    else {
+                        item._id = _id;
+
+                        $scope.metadatas.push(item);
+                    }
+
+                    $scope.selectItem(item);
+
+                    $common.showInfo('Cache type metadata"' + item.name + '" 
saved.');
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
+        }
+
+        // Save cache type metadata.
+        $scope.saveItem = function () {
+            $table.tableReset();
+
+            var item = $scope.backupItem;
+
+            if (validate(item))
+                save(item);
+        };
+
+        // Save cache type metadata with new name.
+        $scope.saveItemAs = function () {
+            $table.tableReset();
+
+            if (validate($scope.backupItem))
+                $copy.show($scope.backupItem.name).then(function (newName) {
+                    var item = angular.copy($scope.backupItem);
+
+                    item._id = undefined;
+                    item.name = newName;
+
+                    save(item);
+                });
+        };
+
+        $scope.removeItem = function () {
+            $table.tableReset();
+
+            var selectedItem = $scope.selectedItem;
+
+            $confirm.show('Are you sure you want to remove cache type 
metadata: "' + selectedItem.name + '"?').then(
+                function () {
+                    var _id = selectedItem._id;
+
+                    $http.post('metadata/remove', {_id: _id})
+                        .success(function () {
+                            $common.showInfo('Cache type metadata has been 
removed: ' + selectedItem.name);
+
+                            var metadatas = $scope.metadatas;
+
+                            var idx = _.findIndex(metadatas, function 
(metadata) {
+                                return metadata._id == _id;
+                            });
+
+                            if (idx >= 0) {
+                                metadatas.splice(idx, 1);
+
+                                if (metadatas.length > 0)
+                                    $scope.selectItem(metadatas[0]);
+                                else {
+                                    $scope.selectedItem = undefined;
+                                    $scope.backupItem = undefined;
+                                }
+                            }
+                        })
+                        .error(function (errMsg) {
+                            $common.showError(errMsg);
+                        });
+                });
+        };
+
+        $scope.tableSimpleValid = function (item, field, name, index) {
+            var model = item[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.indexOf(model, name);
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        $scope.tablePairValid = function (item, field, name, clsName, index) {
+            var model = item[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.findIndex(model, function (pair) {
+                    return pair.name == name
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        $scope.tableDbFieldSaveVisible = function (databaseName, databaseType, 
javaName, javaType) {
+            return $common.isNonEmpty(databaseName) && 
$common.isDefined(databaseType) &&
+                $common.isNonEmpty(javaName) && $common.isDefined(javaType);
+        };
+
+        $scope.tableDbFieldSave = function (field, newDatabaseName, 
newDatabaseType, newJavaName, newJavaType, index) {
+            var item = $scope.backupItem;
+
+            var model = item[field.model];
+
+            var newItem = {databaseName: newDatabaseName, databaseType: 
newDatabaseType, javaName: newJavaName, javaType: newJavaType};
+
+            if ($common.isDefined(model)) {
+                var idx = _.findIndex(model, function (dbMeta) {
+                    return dbMeta.databaseName == newDatabaseName
+                });
+
+                // Found duplicate.
+                if (idx >= 0 && index != idx) {
+                    $common.showError('DB field with such name already 
exists!');
+
+                    return;
+                }
+
+                if (index < 0) {
+                    if (model)
+                        model.push(newItem);
+                    else
+                        item[field.model] = [newItem];
+                }
+                else {
+                    var dbField = model[index];
+
+                    dbField.databaseName = newDatabaseName;
+                    dbField.databaseType = newDatabaseType;
+                    dbField.javaName = newJavaName;
+                    dbField.javaType = newJavaType;
+                }
+            }
+            else
+                item[field.model] = [newItem];
+
+            $table.tableReset();
+        };
+
+        $scope.tableGroupSaveVisible = function (group) {
+            return $common.isNonEmpty(group);
+        };
+
+        function tableGroupValid(groupName, index) {
+            var groups = $scope.backupItem.groups;
+
+            if ($common.isDefined(groups)) {
+                var idx = _.findIndex(groups, function (group) {
+                    return group.name == groupName;
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Group with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        $scope.tableGroupSave = function (groupName, index) {
+            if (tableGroupValid(groupName, index)) {
+                $table.tableReset();
+
+                var item = $scope.backupItem;
+
+                if (index < 0) {
+                    var newGroup = {name: groupName};
+
+                    if (item.groups)
+                        item.groups.push(newGroup);
+                    else
+                        item.groups = [newGroup];
+                }
+                else
+                    item.groups[index].name = groupName;
+            }
+        };
+
+        $scope.tableGroupNewItem = function (groupIndex) {
+            var groupName = $scope.backupItem.groups[groupIndex].name;
+
+            return $table.tableNewItem({model: groupName});
+        };
+
+        $scope.tableGroupNewItemActive = function (groupIndex) {
+            var groups = $scope.backupItem.groups;
+
+            if (groups) {
+                var group = groups[groupIndex];
+
+                if (group) {
+                    var groupName = group.name;
+
+                    return $table.tableNewItemActive({model: groupName});
+                }
+            }
+
+            return false;
+        };
+
+        $scope.tableGroupItemEditing = function (groupIndex, index) {
+            var groups = $scope.backupItem.groups;
+
+            if (groups) {
+                var group = groups[groupIndex];
+
+                if (group)
+                    return $table.tableEditing({model: group.name}, index);
+            }
+
+            return false;
+        };
+
+        $scope.tableGroupItemStartEdit = function (groupIndex, index) {
+            var groups = $scope.backupItem.groups;
+
+            $table.tableState(groups[groupIndex].name, index);
+
+            return groups[groupIndex].fields[index];
+        };
+
+        $scope.tableGroupItemSaveVisible = function (fieldName, className) {
+            return $common.isNonEmpty(fieldName) && 
$common.isNonEmpty(className);
+        };
+
+        function tableGroupItemValid(fieldName, groupIndex, index) {
+            var groupItems = $scope.backupItem.groups[groupIndex].fields;
+
+            if ($common.isDefined(groupItems)) {
+                var idx = _.findIndex(groupItems, function (groupItem) {
+                    return groupItem.name == fieldName;
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists in 
group!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        $scope.tableGroupItemSave = function (fieldName, className, direction, 
groupIndex, index) {
+            if (tableGroupItemValid(fieldName, groupIndex, index)) {
+                $table.tableReset();
+
+                var group = $scope.backupItem.groups[groupIndex];
+
+                if (index < 0) {
+                    var newGroupItem = {name: fieldName, className: className, 
direction: direction};
+
+                    if (group.fields)
+                        group.fields.push(newGroupItem);
+                    else
+                        group.fields = [newGroupItem];
+                }
+                else {
+                    var groupItem = group.fields[index];
+
+                    groupItem.name = fieldName;
+                    groupItem.className = className;
+                    groupItem.direction = direction;
+                }
+            }
+        };
+
+        $scope.tableRemoveGroupItem = function (group, index) {
+            $table.tableReset();
+
+            group.fields.splice(index, 1);
+        };
+
+        $scope.selectSchema = function (idx) {
+            var data = $scope.data;
+            var tables = data.tables;
+            var schemaName = tables[idx].schemaName;
+            var use = tables[idx].use;
+
+            for (var i = idx + 1; i < tables.length; i++) {
+                var item = tables[i];
+
+                if (item.schemaName == schemaName && item.tableName)
+                    item.use = use;
+                else
+                    break;
+            }
+
+            data.curTableIdx = -1;
+            data.curFieldIdx = -1;
+        };
+
+        $scope.selectTable = function (idx) {
+            var data = $scope.data;
+
+            data.curTableIdx = idx;
+            data.curFieldIdx = -1;
+
+            if (idx >= 0) {
+                var tbl = data.tables[idx];
+
+                data.curKeyClass = tbl.keyClass;
+                data.curValueClass = tbl.valueClass;
+            }
+        };
+
+        $scope.selectField = function (idx) {
+            var data = $scope.data;
+
+            data.curFieldIdx = idx;
+
+            if (idx >= 0) {
+                var fld = data.tables[data.curTableIdx].fields[idx];
+
+                data.curJavaName = fld.javaName;
+                data.curJavaType = fld.javaType;
+            }
+        };
+    }]
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/96522874/modules/control-center-web/src/main/js/controllers/models/caches.json
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/models/caches.json 
b/modules/control-center-web/src/main/js/controllers/models/caches.json
new file mode 100644
index 0000000..932eecc
--- /dev/null
+++ b/modules/control-center-web/src/main/js/controllers/models/caches.json
@@ -0,0 +1,943 @@
+{
+  "screenTip": {
+    "workflowTitle": "Use caches view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Configure caches.</li>",
+      "  <li>Associate metadata with cache queries and/or cache store.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Configure cache type metadata.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
+  "general": [
+    {
+      "label": "Name",
+      "type": "text",
+      "model": "name",
+      "required": true,
+      "placeholder": "Input name",
+      "id": "defaultFocusId"
+    },
+    {
+      "label": "Mode",
+      "type": "dropdown",
+      "model": "mode",
+      "placeholder": "PARTITIONED",
+      "items": "modes",
+      "tip": [
+        "Cache modes:",
+        "<ul>",
+        "  <li>Partitioned - in this mode the overall key set will be divided 
into partitions and all partitions will be split equally between participating 
nodes.</li>",
+        "  <li>Replicated - in this mode all the keys are distributed to all 
participating nodes.</li>",
+        "  <li>Local - in this mode caches residing on different grid nodes 
will not know about each other.</li>",
+        "</ul>"
+      ]
+    },
+    {
+      "label": "Atomicity",
+      "type": "dropdown",
+      "model": "atomicityMode",
+      "placeholder": "ATOMIC",
+      "items": "atomicities",
+      "tip": [
+        "Atomicity:",
+        "<ul>",
+        "  <li>Transactional - in this mode specified fully ACID-compliant 
transactional cache behavior.</li>",
+        "  <li>Atomic - in this mode distributed transactions and distributed 
locking are not supported.</li>",
+        "</ul>"
+      ]
+    },
+    {
+      "label": "Backups",
+      "type": "number",
+      "model": "backups",
+      "hide": "backupItem.mode == 'LOCAL'",
+      "placeholder": 0,
+      "tip": [
+        "Number of nodes used to back up single partition for partitioned 
cache."
+      ]
+    },
+    {
+      "label": "Read from backup",
+      "type": "check",
+      "model": "readFromBackup",
+      "placeholder": true,
+      "hide": "!backupItem.backups || backupItem.mode == 'LOCAL'",
+      "tip": [
+        "Flag indicating whether data can be read from backup.",
+        "If not set then always get data from primary node (never from 
backup)."
+      ]
+    },
+    {
+      "label": "Copy on read",
+      "type": "check",
+      "model": "copyOnRead",
+      "placeholder": true,
+      "tip": [
+        "Flag indicating whether copy of of the value stored in cache should 
be created for cache operation implying return value.",
+        "Also if this flag is set copies are created for values passed to 
CacheInterceptor and to CacheEntryProcessor."
+      ]
+    },
+    {
+      "label": "Invalidate near cache",
+      "type": "check",
+      "model": "invalidate",
+      "tip": [
+        "Invalidation flag for near cache entries in transaction.",
+        "If set then values will be invalidated (nullified) upon commit in 
near cache."
+      ]
+    }
+  ],
+  "advanced": [
+    {
+      "label": "Concurrency control",
+      "tip": [
+        "Cache concurrent usage settings."
+      ],
+      "fields": [
+        {
+          "label": "Max async operations",
+          "type": "number",
+          "model": "maxConcurrentAsyncOperations",
+          "placeholder": 500,
+          "tip": [
+            "Maximum number of allowed concurrent asynchronous operations.",
+            "If 0 then number of concurrent asynchronous operations is 
unlimited."
+          ]
+        },
+        {
+          "label": "Default lock timeout",
+          "type": "number",
+          "model": "defaultLockTimeout",
+          "placeholder": 0,
+          "tip": [
+            "Default lock acquisition timeout.",
+            "If 0 then lock acquisition will never timeout."
+          ]
+        },
+        {
+          "label": "Entry versioning",
+          "type": "dropdown",
+          "model": "atomicWriteOrderMode",
+          "placeholder": "Choose versioning",
+          "items": "atomicWriteOrderModes",
+          "hide": "backupItem.atomicityMode == 'TRANSACTIONAL'",
+          "tip": [
+            "Write ordering mode determines which node assigns the write 
version, sender or the primary node.",
+            "<ul>",
+            "  <li>CLOCK - in this mode write versions are assigned on a 
sender node which generally leads to better performance.</li>",
+            "  <li>PRIMARY - in this mode version is assigned only on primary 
node. This means that sender will only send write request to primary node, 
which in turn will assign write version and forward it to backups.</li>",
+            "</ul>"
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Memory",
+      "tip": [
+        "Cache memory settings."
+      ],
+      "fields": [
+        {
+          "label": "Mode",
+          "type": "dropdown",
+          "model": "memoryMode",
+          "placeholder": "ONHEAP_TIERED",
+          "items": "memoryModes",
+          "tip": [
+            "Memory modes:",
+            "<ul>",
+            "  <li>ONHEAP_TIERED - entries are cached on heap memory first.",
+            "    <ul>",
+            "      <li>If offheap memory is enabled and eviction policy evicts 
an entry from heap memory, entry will be moved to offheap memory. If offheap 
memory is disabled, then entry is simply discarded.</li>",
+            "      <li>If swap space is enabled and offheap memory fills up, 
then entry will be evicted into swap space. If swap space is disabled, then 
entry will be discarded. If swap is enabled and offheap memory is disabled, 
then entry will be evicted directly from heap memory into swap.</li>",
+            "    </ul>",
+            "  </li>",
+            "  <li>OFFHEAP_TIERED - works the same as ONHEAP_TIERED, except 
that entries never end up in heap memory and get stored in offheap memory right 
away. Entries get cached in offheap memory first and then get evicted to swap, 
if one is configured.</li>",
+            "  <li>OFFHEAP_VALUES - entry keys will be stored on heap memory, 
and values will be stored in offheap memory. Note that in this mode entries can 
be evicted only to swap.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Off-heap max memory",
+          "type": "number",
+          "model": "offHeapMaxMemory",
+          "min": -1,
+          "placeholder": -1,
+          "hide": "backupItem.memoryMode == 'OFFHEAP_VALUES'",
+          "tip": [
+            "Sets maximum amount of memory available to off-heap storage.",
+            "Possible values are:",
+            "<ul>",
+            "  <li>-1 - means that off-heap storage is disabled.</li>",
+            "  <li>0 - Ignite will not limit off-heap storage (it's up to user 
to properly add and remove entries from cache to ensure that off-heap storage 
does not grow infinitely.</li>",
+            "  <li>Any positive value specifies the limit of off-heap storage 
in bytes.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Eviction policy",
+          "type": "dropdown-details",
+          "path": "evictionPolicy",
+          "model": "kind",
+          "placeholder": "Choose eviction policy",
+          "items": "evictionPolicies",
+          "hide": "backupItem.memoryMode == 'OFFHEAP_TIERED'",
+          "tip": [
+            "Optional cache eviction policy. Must be set for entries to be 
evicted from on-heap to off-heap or swap."
+          ],
+          "details": {
+            "LRU": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "evictionPolicy.LRU",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "evictionPolicy.LRU",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.LRU",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            },
+            "RND": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.RND",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            },
+            "FIFO": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "evictionPolicy.FIFO",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "evictionPolicy.FIFO",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.FIFO",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            },
+            "SORTED": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "evictionPolicy.SORTED",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "evictionPolicy.SORTED",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.SORTED",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            }
+          }
+        },
+        {
+          "label": "Start size",
+          "type": "number",
+          "model": "startSize",
+          "placeholder": 1500000,
+          "tip": [
+            "Initial cache size which will be used to pre-create internal hash 
table after start."
+          ]
+        },
+        {
+          "label": "Swap enabled",
+          "type": "check",
+          "model": "swapEnabled",
+          "tip": [
+            "Flag indicating whether swap storage is enabled or not for this 
cache."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Query",
+      "tip": [
+        "Cache query settings."
+      ],
+      "fields": [
+        {
+          "label": "Escape table and filed names",
+          "type": "check",
+          "model": "sqlEscapeAll",
+          "tip": [
+            "If set then all the SQL table and field names will be escaped 
with double quotes.",
+            "This enforces case sensitivity for field names and also allows 
having special characters in table and field names."
+          ]
+        },
+        {
+          "label": "On-heap cache for off-heap indexes",
+          "type": "number",
+          "model": "sqlOnheapRowCacheSize",
+          "placeholder": 10240,
+          "tip": [
+            "Number of SQL rows which will be cached onheap to avoid 
deserialization on each SQL index access."
+          ]
+        },
+        {
+          "label": "Long query timeout",
+          "type": "number",
+          "model": "longQueryWarningTimeout",
+          "placeholder": 3000,
+          "tip": [
+            "Timeout in milliseconds after which long query warning will be 
printed."
+          ]
+        },
+        {
+          "label": "Metadata",
+          "type": "dropdown-multiple",
+          "model": "queryMetadata",
+          "placeholder": "Choose metadata",
+          "items": "queryMetadata",
+          "tip": [
+            "Select cache type metadata to describe types in cache."
+          ],
+          "addLink": {
+            "label": "Add metadata(s)",
+            "ref": "/configuration/metadata"
+          }
+        } ,
+        {
+          "type": "indexedTypes",
+          "model": "indexedTypes",
+          "keyName": "keyClass",
+          "valueName": "valueClass",
+          "focusNewItemId": "newIndexedType",
+          "focusCurItemId": "curIndexedType",
+          "addTip": "Add new key and value classes to indexed types.",
+          "removeTip": "Remove item from indexed types.",
+          "tip": [
+            "Collection of types to index."
+          ]
+        },
+        {
+          "label": "SQL functions",
+          "type": "table-simple",
+          "model": "sqlFunctionClasses",
+          "editIdx": -1,
+          "placeholder": "SQL function full class name",
+          "focusNewItemId": "newSqlFxField",
+          "focusCurItemId": "curSqlFxField",
+          "addTip": "Add new user-defined functions for SQL queries.",
+          "removeTip": "Remove user-defined function.",
+          "tableTip": [
+            "Collections of classes with user-defined functions for SQL 
queries."
+          ],
+          "tip": [
+            "Class with user-defined functions for SQL queries."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Rebalance",
+      "tip": [
+        "Cache rebalance settings."
+      ],
+      "fields": [
+        {
+          "label": "Mode",
+          "type": "dropdown",
+          "model": "rebalanceMode",
+          "placeholder": "ASYNC",
+          "items": "rebalanceModes",
+          "tip": [
+            "Rebalance modes:",
+            "<ul>",
+            "  <li>Synchronous - in this mode distributed caches will not 
start until all necessary data is loaded from other available grid nodes.</li>",
+            "  <li>Asynchronous - in this mode distributed caches will start 
immediately and will load all necessary data from other available grid nodes in 
the background.</li>",
+            "  <li>None - in this mode no rebalancing will take place which 
means that caches will be either loaded on demand from persistent store 
whenever data is accessed, or will be populated explicitly.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Pool size",
+          "type": "number",
+          "model": "rebalanceThreadPoolSize",
+          "placeholder": 2,
+          "tip": [
+            "Size of rebalancing thread pool.<br>",
+            "Note that size serves as a hint and implementation may create 
more threads for rebalancing than specified here (but never less threads)."
+          ]
+        },
+        {
+          "label": "Batch size",
+          "type": "number",
+          "model": "rebalanceBatchSize",
+          "placeholder": "512 * 1024",
+          "tip": [
+            "Size (in bytes) to be loaded within a single rebalance message.",
+            "Rebalancing algorithm will split total data set on every node 
into multiple batches prior to sending data."
+          ]
+        },
+        {
+          "label": "Order",
+          "type": "number",
+          "model": "rebalanceOrder",
+          "placeholder": 0,
+          "tip": [
+            "If cache rebalance order is positive, rebalancing for this cache 
will be started only when rebalancing for all caches with smaller rebalance 
order (except caches with rebalance order 0) will be completed."
+          ]
+        },
+        {
+          "label": "Delay",
+          "type": "number",
+          "model": "rebalanceDelay",
+          "placeholder": 0,
+          "tip": [
+            "Delay in milliseconds upon a node joining or leaving topology (or 
crash) after which rebalancing should be started automatically."
+          ]
+        },
+        {
+          "label": "Timeout",
+          "type": "number",
+          "model": "rebalanceTimeout",
+          "placeholder": 10000,
+          "tip": [
+            "Rebalance timeout in milliseconds."
+          ]
+        },
+        {
+          "label": "Throttle",
+          "type": "number",
+          "model": "rebalanceThrottle",
+          "placeholder": 0,
+          "tip": [
+            "Time in milliseconds to wait between rebalance messages to avoid 
overloading of CPU or network."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Server near cache",
+      "tip": [
+        "Near cache settings.",
+        "Near cache is a small local cache that stores most recently or most 
frequently accessed data.",
+        "Should be used in case when it is impossible to send computations to 
remote nodes."
+      ],
+      "fields": [
+        {
+          "label": "Enabled",
+          "type": "check",
+          "model": "nearCacheEnabled",
+          "tip": [
+            "Flag indicating whether to configure near cache."
+          ]
+        },
+        {
+          "label": "Start size",
+          "type": "number",
+          "path": "nearConfiguration",
+          "model": "nearStartSize",
+          "hide": "!backupItem.nearCacheEnabled",
+          "placeholder": 375000,
+          "tip": [
+            "Initial cache size for near cache which will be used to 
pre-create internal hash table after start."
+          ]
+        },
+        {
+          "label": "Eviction policy",
+          "type": "dropdown-details",
+          "path": "nearConfiguration.nearEvictionPolicy",
+          "model": "kind",
+          "placeholder": "Choose eviction policy",
+          "items": "evictionPolicies",
+          "hide": "!backupItem.nearCacheEnabled",
+          "tip": [
+            "Cache expiration policy."
+          ],
+          "details": {
+            "LRU": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            },
+            "RND": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.RND",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            },
+            "FIFO": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            },
+            "SORTED": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start 
getting evicted."
+                  ]
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    {
+      "label": "Statistics",
+      "tip": [
+        "Cache statistics and management settings."
+      ],
+      "fields": [
+        {
+          "label": "Statistics enabled",
+          "type": "check",
+          "model": "statisticsEnabled",
+          "tip": [
+            "Flag indicating whether statistics gathering is enabled on a 
cache."
+          ]
+        },
+        {
+          "label": "Management enabled",
+          "type": "check",
+          "model": "managementEnabled",
+          "tip": [
+            "Flag indicating whether management is enabled on this cache."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Store",
+      "tip": [
+        "Cache store settings."
+      ],
+      "fields": [
+        {
+          "label": "Store factory",
+          "type": "dropdown-details",
+          "path": "cacheStoreFactory",
+          "model": "kind",
+          "placeholder": "Choose store factory",
+          "items": "cacheStoreFactories",
+          "tip": [
+            "Factory for persistent storage for cache data."
+          ],
+          "details": {
+            "CacheJdbcPojoStoreFactory": {
+              "expanded": true,
+              "fields": [
+                {
+                  "label": "Data source bean",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcPojoStoreFactory",
+                  "model": "dataSourceBean",
+                  "required": true,
+                  "placeholder": "Bean name in Spring context",
+                  "tip": [
+                    "Name of the data source bean in Spring context."
+                  ]
+                },
+                {
+                  "label": "Dialect",
+                  "type": "dropdown",
+                  "path": "cacheStoreFactory.CacheJdbcPojoStoreFactory",
+                  "model": "dialect",
+                  "required": true,
+                  "placeholder": "Choose JDBC dialect",
+                  "items": "cacheStoreJdbcDialects",
+                  "tip": [
+                    "Dialect of SQL implemented by a particular RDBMS:",
+                    "<ul>",
+                    "  <li>Generic JDBC dialect.</li>",
+                    "  <li>Oracle database.</li>",
+                    "  <li>IBM DB2.</li>",
+                    "  <li>Microsoft SQL Server.</li>",
+                    "  <li>My SQL.</li>",
+                    "  <li>H2 database.</li>",
+                    "</ul>"
+                  ]
+                }
+              ]
+            },
+            "CacheJdbcBlobStoreFactory": {
+              "expanded": true,
+              "fields": [
+                {
+                  "label": "user",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "user",
+                  "required": true,
+                  "tip": [
+                    "User name for database access."
+                  ]
+                },
+                {
+                  "label": "Data source bean",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "dataSourceBean",
+                  "required": true,
+                  "placeholder": "Bean name in Spring context",
+                  "tip": [
+                    "Name of the data source bean in Spring context."
+                  ]
+                },
+                {
+                  "label": "Init schema",
+                  "type": "check",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "initSchema",
+                  "tip": [
+                    "Flag indicating whether DB schema should be initialized 
by Ignite (default behaviour) or was explicitly created by user."
+                  ]
+                },
+                {
+                  "label": "Create query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "createTableQuery",
+                  "placeholder": "SQL for table creation",
+                  "tip": [
+                    "Query for table creation in underlying database.",
+                    "Default value: create table if not exists ENTRIES (key 
binary primary key, val binary)"
+                  ]
+                },
+                {
+                  "label": "Load query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "loadQuery",
+                  "placeholder": "SQL for load entry",
+                  "tip": [
+                    "Query for entry load from underlying database.",
+                    "Default value: select * from ENTRIES where key=?"
+                  ]
+                },
+                {
+                  "label": "Insert query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "insertQuery",
+                  "placeholder": "SQL for insert entry",
+                  "tip": [
+                    "Query for insert entry into underlying database.",
+                    "Default value: insert into ENTRIES (key, val) values (?, 
?)"
+                  ]
+                },
+                {
+                  "label": "Update query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "updateQuery",
+                  "placeholder": "SQL for update entry",
+                  "tip": [
+                    "Query fpr update entry in underlying database.",
+                    "Default value: update ENTRIES set val=? where key=?"
+                  ]
+                },
+                {
+                  "label": "Delete query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "deleteQuery",
+                  "placeholder": "SQL for delete entry",
+                  "tip": [
+                    "Query for delete entry from underlying database.",
+                    "Default value: delete from ENTRIES where key=?"
+                  ]
+                }
+              ]
+            },
+            "CacheHibernateBlobStoreFactory": {
+              "expanded": true,
+              "fields": [
+                {
+                  "label": "Hibernate properties",
+                  "type": "table-simple",
+                  "path": "cacheStoreFactory.CacheHibernateBlobStoreFactory",
+                  "model": "hibernateProperties",
+                  "editIdx": -1,
+                  "placeholder": "key=value",
+                  "addTip": "Add new Hibernate property.",
+                  "removeTip": "Remove Hibernate property.",
+                  "tip": [
+                    "List of Hibernate properties.",
+                    "For example: connection.url=jdbc:h2:mem:"
+                  ]
+                }
+              ]
+            }
+          }
+        },
+        {
+          "label": "Load previous value",
+          "type": "check",
+          "model": "loadPreviousValue",
+          "tip": [
+            "Flag indicating whether value should be loaded from store if it 
is not in the cache for following cache operations:",
+            "<ul>",
+            "  <li>IgniteCache.putIfAbsent()</li>",
+            "  <li>IgniteCache.replace()</li>",
+            "  <li>IgniteCache.replace()</li>",
+            "  <li>IgniteCache.remove()</li>",
+            "  <li>IgniteCache.getAndPut()</li>",
+            "  <li>IgniteCache.getAndRemove()</li>",
+            "  <li>IgniteCache.getAndReplace()</li>",
+            "  <li>IgniteCache.getAndPutIfAbsent()</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Read-through",
+          "type": "check",
+          "model": "readThrough",
+          "tip": [
+            "Flag indicating whether read-through caching should be used."
+          ]
+        },
+        {
+          "label": "Write-through",
+          "type": "check",
+          "model": "writeThrough",
+          "tip": [
+            "Flag indicating whether write-through caching should be used."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Write behind",
+      "tip": [
+        "Cache write behind settings.",
+        "Write-behind is a special mode when updates to cache accumulated and 
then asynchronously flushed to persistent store as a bulk operation."
+      ],
+      "fields": [
+        {
+          "label": "Enabled",
+          "type": "check",
+          "model": "writeBehindEnabled",
+          "tip": [
+            "Flag indicating whether Ignite should use write-behind behaviour 
for the cache store."
+          ]
+        },
+        {
+          "label": "Batch size",
+          "type": "number",
+          "model": "writeBehindBatchSize",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 512,
+          "tip": [
+            "Maximum batch size for write-behind cache store operations.",
+            "Store operations (get or remove) are combined in a batch of this 
size to be passed to cache store."
+          ]
+        },
+        {
+          "label": "Flush size",
+          "type": "number",
+          "model": "writeBehindFlushSize",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 10240,
+          "tip": [
+            "Maximum size of the write-behind cache.<br>",
+            "If cache size exceeds this value, all cached items are flushed to 
the cache store and write cache is cleared."
+          ]
+        },
+        {
+          "label": "Flush frequency",
+          "type": "number",
+          "model": "writeBehindFlushFrequency",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 5000,
+          "tip": [
+            "Frequency with which write-behind cache is flushed to the cache 
store in milliseconds."
+          ]
+        },
+        {
+          "label": "Flush threads count",
+          "type": "number",
+          "model": "writeBehindFlushThreadCount",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 1,
+          "tip": [
+            "Number of threads that will perform cache flushing."
+          ]
+        }
+      ]
+    }
+  ]
+}

Reply via email to