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 2015/07/15 21:17:16 UTC

[28/45] incubator-ignite git commit: # ignite-843 Added client configuration generation.

# ignite-843 Added client configuration generation.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/6ee8f348
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/6ee8f348
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/6ee8f348

Branch: refs/heads/ignite-1121
Commit: 6ee8f3486954310a773a71f6800784104f601730
Parents: 3e59cb1
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 15 10:56:04 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 15 10:56:04 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/models/summary.json      | 145 +++++++++++++++++++
 .../nodejs/controllers/summary-controller.js    |  94 +++++++++---
 .../nodejs/routes/generator/java.js             |  56 ++++---
 .../nodejs/routes/generator/xml.js              |  20 ++-
 .../web-control-center/nodejs/routes/summary.js |  33 +++--
 .../nodejs/views/configuration/summary.jade     | 129 +++++++++++------
 .../nodejs/views/settings/admin.jade            |   2 +-
 7 files changed, 379 insertions(+), 100 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/controllers/models/summary.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/summary.json b/modules/web-control-center/nodejs/controllers/models/summary.json
index 63cc4a6..d0a2db1 100644
--- a/modules/web-control-center/nodejs/controllers/models/summary.json
+++ b/modules/web-control-center/nodejs/controllers/models/summary.json
@@ -1,5 +1,150 @@
 {
   "screenTip": [
     "Overview and download XML and java code for cluster configurations."
+  ],
+  "clientFields": [
+    {
+      "label": "Start size",
+      "type": "number",
+      "path": "nearConfiguration",
+      "model": "nearStartSize",
+      "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",
+      "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."
+              ]
+            }
+          ]
+        }
+      }
+    }
   ]
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/controllers/summary-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/summary-controller.js b/modules/web-control-center/nodejs/controllers/summary-controller.js
index e4f5039..c38a84f 100644
--- a/modules/web-control-center/nodejs/controllers/summary-controller.js
+++ b/modules/web-control-center/nodejs/controllers/summary-controller.js
@@ -17,14 +17,27 @@
 
 controlCenterModule.controller('summaryController', ['$scope', '$http', 'commonFunctions', function ($scope, $http, commonFunctions) {
     $scope.joinTip = commonFunctions.joinTip;
+    $scope.getModel = commonFunctions.getModel;
 
     $scope.javaClassItems = [
         { label: 'snippet',value: false},
         { label: 'factory class',value: true}
     ];
 
+    $scope.evictionPolicies = [
+        {value: 'LRU', label: 'LRU'},
+        {value: 'RND', label: 'Random'},
+        {value: 'FIFO', label: 'FIFO'},
+        {value: 'SORTED', label: 'Sorted'},
+        {value: undefined, label: 'Not set'}
+    ];
+
+    $scope.backupItem = {nearCacheEnabled: true};
+
     $http.get('/models/summary.json')
         .success(function (data) {
+            $scope.clientFields = data.clientFields;
+
             $scope.screenTip = data.screenTip;
         })
         .error(function (errMsg) {
@@ -33,46 +46,89 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', 'commonF
 
     $scope.oss = ['debian:8', 'ubuntu:14.10'];
 
-    $scope.cfgLang = 'xml';
+    $scope.cfgLangServer = 'xml';
+    $scope.cfgLangClient = 'xml';
+
+    $scope.javaClassServer = false;
+    $scope.javaClassClient = false;
 
-    $scope.javaClass = false;
     $scope.os = undefined;
 
     $scope.generated = undefined;
     $scope.clusters = [];
 
-    $scope.reload = function() {
-        $("<pre class='brush:java' />").text($scope.javaClass ? $scope.generated.javaClass : $scope.generated.javaSnippet).appendTo($('#javaResultDiv').empty());
+    $scope.reloadServer = function() {
+        if (!$scope.generated)
+            return;
+
+        $("<pre class='brush:xml'/>").text($scope.generated.xmlServer).appendTo($('#xmlServer').empty());
+        $("<pre class='brush:java'/>").text($scope.javaClassServer ? $scope.generated.javaClassServer : $scope.generated.javaSnippetServer).appendTo($('#javaServer').empty());
+
+        var os = $scope.os ? $scope.os : $scope.oss[0];
+
+        $("<pre class='brush:plain'/>").text($scope.generated.docker.replace(new RegExp('\%OS\%', 'g'), os)).appendTo($('#docker').empty());
+
+
+        $("<pre class='brush:xml'/>").text($scope.generated.xmlClient).appendTo($('#xmlClient').empty());
+        $("<pre class='brush:java'/>").text($scope.javaClassClient ? $scope.generated.javaClassClient : $scope.generated.javaSnippetClient).appendTo($('#javaClient').empty());
+
+        SyntaxHighlighter.highlight();
+    };
+
+    $scope.reloadServer = function() {
+        if (!$scope.generated)
+            return;
 
-        $("<pre class='brush:xml' />").text($scope.generated.xml).appendTo($('#xmlResultDiv').empty());
+        $("<pre class='brush:xml'/>").text($scope.generated.xmlServer).appendTo($('#xmlServer').empty());
+        $("<pre class='brush:java'/>").text($scope.javaClassServer ? $scope.generated.javaClassServer : $scope.generated.javaSnippetServer).appendTo($('#javaServer').empty());
 
         var os = $scope.os ? $scope.os : $scope.oss[0];
 
-        $("<pre class='brush:plain' />").text($scope.generated.docker.replace(new RegExp('\%OS\%', 'g'), os)).appendTo($('#dockerResultDiv').empty());
+        $("<pre class='brush:plain'/>").text($scope.generated.docker.replace(new RegExp('\%OS\%', 'g'), os)).appendTo($('#docker').empty());
 
         SyntaxHighlighter.highlight();
     };
 
-    $scope.generate = function(item) {
-        if (!item)
+    $scope.selectItem = function(cluster) {
+        if (!cluster)
             return;
 
-        $scope.selectedItem = item;
+        $scope.selectedItem = cluster;
 
-        $scope.loading = true;
+        $scope.$watch('javaClassServer', $scope.reloadServer);
+        $scope.$watch('os', $scope.reloadServer);
 
-        $http.post('summary/generator', {_id: $scope.selectedItem._id})
+        $scope.generateServer(cluster);
+
+        $scope.reloadServer();
+
+        $scope.$watch('backupItem', function() {
+            $scope.generateClient();
+        }, true);
+
+        $scope.$watch('javaClassClient', $scope.generateClient);
+    };
+
+    $scope.generateServer = function(cluster) {
+        $http.post('summary/generator', {_id: cluster._id})
             .success(function (data) {
                 $scope.generated = data;
 
-                $scope.$watch('javaClass', $scope.reload);
-                $scope.$watch('os', $scope.reload);
+                $scope.reloadServer();
+            }).error(function (errMsg) {
+                commonFunctions.showError('Failed to generate config: ' + errMsg);
+            });
+    };
 
-                $scope.loading = false;
-            }).error(function (data) {
-                $scope.generateError = "Failed to generate config: " + data;
+    $scope.generateClient = function() {
+        $http.post('summary/generator', {_id: $scope.selectedItem._id, javaClass: $scope.javaClassClient, clientTemplate: $scope.backupItem})
+            .success(function (data) {
+                $("<pre class='brush:xml'/>").text(data.xmlClient).appendTo($('#xmlClient').empty());
+                $("<pre class='brush:java'/>").text(data.javaClient).appendTo($('#javaClient').empty());
 
-                $scope.loading = false;
+                SyntaxHighlighter.highlight();
+            }).error(function (errMsg) {
+                commonFunctions.showError('Failed to generate config: ' + errMsg);
             });
     };
 
@@ -92,8 +148,8 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', 'commonF
 
                 document.body.removeChild(file);
             })
-            .error(function (data) {
-                $scope.generateError = "Failed to generate zip: " + data;
+            .error(function (errMsg) {
+                commonFunctions.showError('Failed to generate zip: ' + errMsg);
             });
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/routes/generator/java.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/java.js b/modules/web-control-center/nodejs/routes/generator/java.js
index b79ba66..47d7921 100644
--- a/modules/web-control-center/nodejs/routes/generator/java.js
+++ b/modules/web-control-center/nodejs/routes/generator/java.js
@@ -19,7 +19,7 @@ var _ = require('lodash');
 
 var generatorUtils = require("./common");
 
-exports.generateClusterConfiguration = function(cluster, javaClass) {
+exports.generateClusterConfiguration = function(cluster, javaClass, clientCache) {
     var res = generatorUtils.builder();
 
     res.datasourceBeans = [];
@@ -40,6 +40,12 @@ exports.generateClusterConfiguration = function(cluster, javaClass) {
     res.line('IgniteConfiguration cfg = new IgniteConfiguration();');
     res.line();
 
+    if (clientCache) {
+        res.line('cfg.setClientMode(true);');
+
+        res.line();
+    }
+
     if (cluster.discovery) {
         var d = cluster.discovery;
 
@@ -48,8 +54,10 @@ exports.generateClusterConfiguration = function(cluster, javaClass) {
 
         switch (d.kind) {
             case 'Multicast':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder');
+
                 addBeanWithProperties(res, d.Multicast, 'discovery', 'ipFinder', 'ipFinder',
-                    'org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder', {
+                    'TcpDiscoveryMulticastIpFinder', {
                         multicastGroup: null,
                         multicastPort: null,
                         responseWaitTime: null,
@@ -60,30 +68,29 @@ exports.generateClusterConfiguration = function(cluster, javaClass) {
                 break;
 
             case 'Vm':
-                addBeanWithProperties(res, d.Vm, 'discovery', 'ipFinder', 'ipFinder',
-                    'org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder', {
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder');
+
+                addBeanWithProperties(res, d.Vm, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryVmIpFinder', {
                         addresses: {type: 'list'}
                     }, true);
 
                 break;
 
             case 'S3':
-                if (d.S3) {
-                    addBeanWithProperties(res, d.S3, 'discovery', 'ipFinder', 'ipFinder',
-                        'org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder', {bucketName: null}, 
-                        true);
-                }
-                else {
-                    res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder');
-                    
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder');
+
+                if (d.S3)
+                    addBeanWithProperties(res, d.S3, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryS3IpFinder',
+                        {bucketName: null}, true);
+                else
                     res.line('discovery.setIpFinder(new TcpDiscoveryS3IpFinder());');
-                }
 
                 break;
 
             case 'Cloud':
-                addBeanWithProperties(res, d.Cloud, 'discovery', 'ipFinder', 'ipFinder',
-                    'org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder', {
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder');
+
+                addBeanWithProperties(res, d.Cloud, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryCloudIpFinder', {
                         credential: null,
                         credentialPath: null,
                         identity: null,
@@ -95,8 +102,10 @@ exports.generateClusterConfiguration = function(cluster, javaClass) {
                 break;
 
             case 'GoogleStorage':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder');
+
                 addBeanWithProperties(res, d.GoogleStorage, 'discovery', 'ipFinder', 'ipFinder',
-                    'org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder', {
+                    'TcpDiscoveryGoogleStorageIpFinder', {
                         projectName: null,
                         bucketName: null,
                         serviceAccountP12FilePath: null
@@ -119,9 +128,10 @@ exports.generateClusterConfiguration = function(cluster, javaClass) {
                 break;
 
             case 'SharedFs':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder');
+
                 addBeanWithProperties(res, d.SharedFs, 'discovery', 'ipFinder', 'ipFinder',
-                    'org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder', {path: null}, 
-                    true);
+                    'TcpDiscoverySharedFsIpFinder', {path: null}, true);
 
                 break;
 
@@ -150,6 +160,9 @@ exports.generateClusterConfiguration = function(cluster, javaClass) {
 
             names.push(cacheName);
 
+            if (clientCache)
+                _.merge(cache, clientCache);
+
             generateCacheConfiguration(cache, cacheName, res);
 
             res.needEmptyLine = true;
@@ -352,12 +365,13 @@ function generateCacheConfiguration(cacheCfg, varName, res) {
 
     createEvictionPolicy(res, cacheCfg.evictionPolicy, varName, 'evictionPolicy');
 
-    if (cacheCfg.nearConfiguration && (cacheCfg.nearConfiguration.nearStartSize || cacheCfg.nearConfiguration.nearEvictionPolicy.kind)) {
+    if (cacheCfg.nearCacheEnabled) {
         res.needEmptyLine = true;
 
+        res.importClass('org.apache.ignite.configuration.NearCacheConfiguration');
+
         addBeanWithProperties(res, cacheCfg.nearConfiguration, varName, 'nearConfiguration', 'nearConfiguration',
-            'org.apache.ignite.configuration.NearCacheConfiguration',
-            {nearStartSize: null, atomicSequenceReserveSize: null}, true);
+            'NearCacheConfiguration', {nearStartSize: null}, true);
 
         if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy && cacheCfg.nearConfiguration.nearEvictionPolicy.kind) {
             createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearConfiguration', 'nearEvictionPolicy');

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/routes/generator/xml.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/xml.js b/modules/web-control-center/nodejs/routes/generator/xml.js
index 07988ac..f01d136 100644
--- a/modules/web-control-center/nodejs/routes/generator/xml.js
+++ b/modules/web-control-center/nodejs/routes/generator/xml.js
@@ -20,7 +20,7 @@ var _ = require('lodash');
 var generatorUtils = require("./common");
 var dataStructures = require("../../helpers/data-structures.js");
 
-exports.generateClusterConfiguration = function(cluster) {
+exports.generateClusterConfiguration = function(cluster, clientCache) {
     var res = generatorUtils.builder();
 
     res.datasources = [];
@@ -29,6 +29,12 @@ exports.generateClusterConfiguration = function(cluster) {
     // Generate Ignite Configuration.
     res.startBlock('<bean class="org.apache.ignite.configuration.IgniteConfiguration">');
 
+    if (clientCache) {
+        res.line('<property name="clientMode" value="true" />');
+
+        res.line();
+    }
+
     // Generate discovery.
     if (cluster.discovery) {
         res.startBlock('<property name="discoverySpi">');
@@ -157,9 +163,8 @@ exports.generateClusterConfiguration = function(cluster) {
         
         res.startBlock('<property name="includeEventTypes">');
         
-        if (cluster.includeEventTypes.length == 1) {
-            res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + cluster.includeEventTypes[0] + '"/>')
-        }
+        if (cluster.includeEventTypes.length == 1)
+            res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + cluster.includeEventTypes[0] + '"/>');
         else {
             res.startBlock('<array>');
 
@@ -253,7 +258,12 @@ exports.generateClusterConfiguration = function(cluster) {
             if (i > 0)
                 res.line();
 
-            generateCacheConfiguration(cluster.caches[i], res);
+            var cache = cluster.caches[i];
+
+            if (clientCache)
+                _.merge(cache, clientCache);
+
+            generateCacheConfiguration(cache, res);
         }
 
         res.endBlock('</list>');

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/routes/summary.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/summary.js b/modules/web-control-center/nodejs/routes/summary.js
index a4554f0..8e56c81 100644
--- a/modules/web-control-center/nodejs/routes/summary.js
+++ b/modules/web-control-center/nodejs/routes/summary.js
@@ -37,10 +37,18 @@ router.post('/generator', function (req, res) {
         if (!cluster)
             return res.sendStatus(404);
 
+        var clientTemplate = req.body.clientTemplate;
+
+        if (clientTemplate)
+            return res.send({
+                xmlClient: generatorXml.generateClusterConfiguration(cluster, clientTemplate),
+                javaClient: generatorJava.generateClusterConfiguration(cluster, req.body.javaClass, clientTemplate)
+            });
+
         return res.send({
-            xml: generatorXml.generateClusterConfiguration(cluster),
-            javaSnippet: generatorJava.generateClusterConfiguration(cluster, false),
-            javaClass: generatorJava.generateClusterConfiguration(cluster, true),
+            xmlServer: generatorXml.generateClusterConfiguration(cluster),
+            javaSnippetServer: generatorJava.generateClusterConfiguration(cluster, false),
+            javaClassServer: generatorJava.generateClusterConfiguration(cluster, true),
             docker: generatorDocker.generateClusterConfiguration(cluster, '%OS%')
         });
     });
@@ -55,6 +63,8 @@ router.post('/download', function (req, res) {
         if (!cluster)
             return res.sendStatus(404);
 
+        var client = req.body.type == 'client';
+
         var archiver = require('archiver');
 
         // creating archives
@@ -81,15 +91,18 @@ router.post('/download', function (req, res) {
         // Send the file to the page output.
         zip.pipe(res);
 
-        var props = generatorCommon.generateProperties(cluster);
+        if (!client) {
+            zip.append(generatorDocker.generateClusterConfiguration(cluster, req.body.os), {name: "Dockerfile"});
+
+            var props = generatorCommon.generateProperties(cluster, client);
 
-        if (props)
-            zip.append(props, {name: "secret.properties"});
+            if (props)
+                zip.append(props, {name: "secret.properties"});
+        }
 
-        zip.append(generatorXml.generateClusterConfiguration(cluster), {name: cluster.name + ".xml"})
-            .append(generatorJava.generateClusterConfiguration(cluster, req.body.javaClass),
-            {name: javaClass ? 'ConfigurationFactory.java' : cluster.name + '.snipplet.java'})
-            .append(generatorDocker.generateClusterConfiguration(cluster, req.body.os), {name: "Dockerfile"})
+        zip.append(generatorXml.generateClusterConfiguration(cluster, client), {name: cluster.name + ".xml"})
+            .append(generatorJava.generateClusterConfiguration(cluster, client, req.body.javaClass),
+                {name: javaClass ? 'ConfigurationFactory.java' : cluster.name + '.snipplet.java'})
             .finalize();
     });
 });

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/summary.jade b/modules/web-control-center/nodejs/views/configuration/summary.jade
index a827511..8e43441 100644
--- a/modules/web-control-center/nodejs/views/configuration/summary.jade
+++ b/modules/web-control-center/nodejs/views/configuration/summary.jade
@@ -30,6 +30,8 @@ append css
     link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/styles/shCore.css')
     link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/styles/shThemeDefault.css')
 
+include ../includes/controls
+
 block content
     .docs-header
         h1 Configurations summary
@@ -48,50 +50,89 @@ block content
                     tbody
                         tr(ng-repeat='row in clusters track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='generate(row)') {{$index + 1}}) {{row.name}}
-            #cfgResult.configBox(ng-show='selectedItem && !generateError && !loading', style='margin-top: 20px')
-                ul.nav.nav-tabs
-                    li(ng-class='{active: cfgLang == "xml"}')
-                        a(href, ng-click='cfgLang = "xml"')
-                            img(src='/images/xml.png', width='16px' height='16px')
-                            |  XML
-                    li(ng-class='{active: cfgLang=="java"}')
-                        a(href, ng-click='cfgLang = "java"')
-                            img(src='/images/java.png', width='16px' height='16px')
-                            |  Java
-                    li(ng-class="{active: cfgLang=='docker'}")
-                        a(href, ng-click='cfgLang = "docker"')
-                            img(src='/images/docker.png', width='16px' height='16px')
-                            |  Dockerfile
-                form.settings-row(method='post' action='summary/download')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+        hr
+        panel-group(bs-collapse ng-show='selectedItem && !generateError' data-allow-multiple="true")
+            .panel.panel-default
+                form.panel-heading(role="tab")(method='post' action='summary/download')
                     input(type="hidden" name="_id" value="{{selectedItem._id}}")
-                    input(type="hidden" name="javaClass" value="{{javaClass}}")
+                    input(type="hidden" name="javaClassServer" value="{{javaClassServer}}")
                     input(type="hidden" name="os" value="{{os}}")
 
-                    #xmlResult(ng-show="cfgLang == 'xml'")
-                        button.btn.btn-primary.pull-right(style='margin-right: 0px;margin-top: -45px' type='submit') Download
-                        #xmlResultDiv
-                    #javaResult(ng-show="cfgLang == 'java'")
-                        .col-sm-1
-                            label Generate:
-                        .col-sm-3
-                            button.form-control(type='button' ng-model='javaClass' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
-                        button.btn.btn-primary.pull-right(style='margin-right: 0px;margin-top: -40px' type='submit') Download
-                        #javaResultDiv
-                    #dockerResult(ng-show="cfgLang == 'docker'")
-                        button.btn.btn-primary.pull-right(style='margin-right: 0px;margin-top: -40px' type='submit') Download
-                        p
-                            a(style='color:#ec1c24' href='https://docs.docker.com/reference/builder' target="_blank") Docker
-                            | &nbsp;file is a text file with instructions to create Docker image.<br/>
-                            | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
-                            | Also you could use predefined&nbsp;
-                            a(style='color:#ec1c24' href='https://ignite.incubator.apache.org/download.html#docker' target="_blank") Apache Ignite docker image
-                            | . For more information about using Ignite with Docker please read&nbsp;
-                            a(style='color:#ec1c24' href='http://apacheignite.readme.io/docs/docker-deployment' target="_blank") documentation
-                            |.
-                        .col-sm-2
-                            label(for='os') Operation System:
-                        .col-sm-4
-                            input#os.form-control(type='text', ng-model='os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
-                        .settings-row#dockerResultDiv(style='margin-top: 15px')
-                div(ng-show='generateError') {{generateError}}
+                    h3
+                        a(bs-collapse-toggle) Server
+                        button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+                .panel-collapse(role="tabpanel" bs-collapse-target)
+                    .panel-body
+                        .configBox(ng-show='selectedItem && !generateError')
+                            ul.nav.nav-tabs
+                                li(ng-class='{active: cfgLangServer == "xml"}')
+                                    a(href, ng-click='cfgLangServer = "xml"')
+                                        img(src='/images/xml.png', width='16px' height='16px')
+                                        |  XML
+                                li(ng-class='{active: cfgLangServer =="java"}')
+                                    a(href, ng-click='cfgLangServer = "java"')
+                                        img(src='/images/java.png', width='16px' height='16px')
+                                        |  Java
+                                li(ng-class="{active: cfgLangServer =='docker'}")
+                                    a(href, ng-click='cfgLangServer = "docker"')
+                                        img(src='/images/docker.png', width='16px' height='16px')
+                                        |  Dockerfile
+                            .settings-row
+                                div(ng-show="cfgLangServer == 'xml'")
+                                    #xmlServer
+                                div(ng-show="cfgLangServer == 'java'")
+                                    .col-sm-1
+                                        label Generate:
+                                    .col-sm-3
+                                        button.form-control(type='button' ng-model='javaClassServer' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                    #javaServer
+                                div(ng-show="cfgLangServer == 'docker'")
+                                    p
+                                        a(style='color:#ec1c24' href='https://docs.docker.com/reference/builder' target="_blank") Docker
+                                        | &nbsp;file is a text file with instructions to create Docker image.<br/>
+                                        | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
+                                        | Also you could use predefined&nbsp;
+                                        a(style='color:#ec1c24' href='https://ignite.incubator.apache.org/download.html#docker' target="_blank") Apache Ignite docker image
+                                        | . For more information about using Ignite with Docker please read&nbsp;
+                                        a(style='color:#ec1c24' href='http://apacheignite.readme.io/docs/docker-deployment' target="_blank") documentation
+                                        |.
+                                    .col-sm-2
+                                        label(for='os') Operation System:
+                                    .col-sm-4
+                                        input#os.form-control(type='text', ng-model='os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
+                                    .settings-row#docker(style='margin-top: 15px')
+                                div(ng-show='generateError') {{generateError}}
+            .panel.panel-default
+                form.panel-heading(role="tab")
+                    input(type="hidden" name="_id" value="{{selectedItem._id}}")
+                    input(type="hidden" name="javaClassClient" value="{{javaClassClient}}")
+                    input(type="hidden" name="clientSettings" value="{{backupItem}}")
+
+                    h3
+                        a(bs-collapse-toggle) Client
+                        button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+                .panel-collapse(role="tabpanel" bs-collapse-target)
+                    .panel-body
+                        .configBox(ng-show='selectedItem && !generateError')
+                            .settings-row(ng-repeat='field in clientFields')
+                                +form-row
+                            ul.nav.nav-tabs
+                                li(ng-class='{active: cfgLangClient == "xml"}')
+                                    a(href, ng-click='cfgLangClient = "xml"')
+                                        img(src='/images/xml.png', width='16px' height='16px')
+                                        |  XML
+                                li(ng-class='{active: cfgLangClient =="java"}')
+                                    a(href, ng-click='cfgLangClient = "java"')
+                                        img(src='/images/java.png', width='16px' height='16px')
+                                        |  Java
+                            .settings-row
+                                div(ng-show="cfgLangClient == 'xml'")
+                                    #xmlClient
+                                div(ng-show="cfgLangClient == 'java'")
+                                    .col-sm-1
+                                        label Generate:
+                                    .col-sm-4
+                                        button.form-control(type='button' ng-model='javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                    #javaClient
+                            div(ng-show='generateError') {{generateError}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ee8f348/modules/web-control-center/nodejs/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/admin.jade b/modules/web-control-center/nodejs/views/settings/admin.jade
index 608634b..f8ced1c 100644
--- a/modules/web-control-center/nodejs/views/settings/admin.jade
+++ b/modules/web-control-center/nodejs/views/settings/admin.jade
@@ -49,5 +49,5 @@ block container
                             td(style='text-align: center;')
                                 a(ng-click='removeUser(row)' ng-show='row._id != user._id' title='Remove user')
                                     i.fa.fa-remove
-                                a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' title='View user\'s configurations')
+                                a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' title='Become this user')
                                     i.fa.fa-eye