You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by av...@apache.org on 2016/06/21 16:26:49 UTC

[3/8] ignite git commit: IGNITE-3277 Replaced outdated json-lib 2.4 to modern Jackson 2.7.5.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1c3e408b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
index 4b1d47c..ad667ed 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
@@ -17,42 +17,98 @@
 
 package org.apache.ignite.internal.processors.rest;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.LineNumberReader;
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
+import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Pattern;
-import net.sf.json.JSONNull;
-import net.sf.json.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.query.SqlQuery;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.FileSystemConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.igfs.IgfsGroupDataBlocksKeyMapper;
+import org.apache.ignite.igfs.IgfsIpcEndpointConfiguration;
 import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
 import org.apache.ignite.internal.processors.cache.query.GridCacheSqlIndexMetadata;
 import org.apache.ignite.internal.processors.cache.query.GridCacheSqlMetadata;
 import org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandler;
+import org.apache.ignite.internal.processors.rest.protocols.http.jetty.GridJettyObjectMapper;
+import org.apache.ignite.internal.util.lang.GridTuple3;
+import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.internal.util.typedef.P1;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.visor.cache.VisorCacheClearTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheConfigurationCollectorTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheLoadTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheMetadataTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheMetricsCollectorTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheNodesTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheRebalanceTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheResetMetricsTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheStartTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheStopTask;
+import org.apache.ignite.internal.visor.cache.VisorCacheSwapBackupsTask;
+import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionsTask;
+import org.apache.ignite.internal.visor.compute.VisorComputeResetMetricsTask;
+import org.apache.ignite.internal.visor.compute.VisorComputeToggleMonitoringTask;
+import org.apache.ignite.internal.visor.compute.VisorGatewayTask;
+import org.apache.ignite.internal.visor.debug.VisorThreadDumpTask;
+import org.apache.ignite.internal.visor.file.VisorFileBlockTask;
+import org.apache.ignite.internal.visor.file.VisorLatestTextFilesTask;
+import org.apache.ignite.internal.visor.igfs.VisorIgfsFormatTask;
+import org.apache.ignite.internal.visor.igfs.VisorIgfsProfilerClearTask;
+import org.apache.ignite.internal.visor.igfs.VisorIgfsProfilerTask;
+import org.apache.ignite.internal.visor.igfs.VisorIgfsResetMetricsTask;
+import org.apache.ignite.internal.visor.igfs.VisorIgfsSamplingStateTask;
+import org.apache.ignite.internal.visor.log.VisorLogSearchTask;
+import org.apache.ignite.internal.visor.misc.VisorAckTask;
+import org.apache.ignite.internal.visor.misc.VisorLatestVersionTask;
+import org.apache.ignite.internal.visor.misc.VisorResolveHostNameTask;
+import org.apache.ignite.internal.visor.node.VisorNodeConfigurationCollectorTask;
+import org.apache.ignite.internal.visor.node.VisorNodeDataCollectorTask;
+import org.apache.ignite.internal.visor.node.VisorNodeDataCollectorTaskArg;
+import org.apache.ignite.internal.visor.node.VisorNodeEventsCollectorTask;
+import org.apache.ignite.internal.visor.node.VisorNodeGcTask;
+import org.apache.ignite.internal.visor.node.VisorNodePingTask;
+import org.apache.ignite.internal.visor.node.VisorNodeSuppressedErrorsTask;
+import org.apache.ignite.internal.visor.query.VisorQueryArg;
+import org.apache.ignite.internal.visor.query.VisorQueryCleanupTask;
+import org.apache.ignite.internal.visor.query.VisorQueryNextPageTask;
+import org.apache.ignite.internal.visor.query.VisorQueryTask;
 import org.apache.ignite.lang.IgniteBiPredicate;
+import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.testframework.GridTestUtils;
 
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_JETTY_PORT;
+import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR;
 
 /**
  * Tests for Jetty REST protocol.
@@ -62,6 +118,15 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     /** Grid count. */
     private static final int GRID_CNT = 3;
 
+    /** Url address to send HTTP request. */
+    private final String TEST_URL = "http://" + LOC_HOST + ":" + restPort() + "/ignite?";
+
+    /** Used to sent request charset. */
+    private static final String CHARSET = StandardCharsets.UTF_8.name();
+
+    /** JSON to java mapper. */
+    private static final ObjectMapper JSON_MAPPER = new GridJettyObjectMapper();
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         System.setProperty(IGNITE_JETTY_PORT, Integer.toString(restPort()));
@@ -107,12 +172,12 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
      * @throws Exception If failed.
      */
     protected String content(Map<String, String> params) throws Exception {
-        String addr = "http://" + LOC_HOST + ":" + restPort() + "/ignite?";
+        SB sb = new SB(TEST_URL);
 
         for (Map.Entry<String, String> e : params.entrySet())
-            addr += e.getKey() + '=' + e.getValue() + '&';
+            sb.a(e.getKey()).a('=').a(e.getValue()).a('&');
 
-        URL url = new URL(addr);
+        URL url = new URL(sb.toString());
 
         URLConnection conn = url.openConnection();
 
@@ -123,165 +188,255 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         InputStream in = conn.getInputStream();
 
-        LineNumberReader rdr = new LineNumberReader(new InputStreamReader(in));
-
         StringBuilder buf = new StringBuilder(256);
 
-        for (String line = rdr.readLine(); line != null; line = rdr.readLine())
-            buf.append(line);
+        try (LineNumberReader rdr = new LineNumberReader(new InputStreamReader(in, "UTF-8"))) {
+            for (String line = rdr.readLine(); line != null; line = rdr.readLine())
+                buf.append(line);
+        }
 
         return buf.toString();
     }
 
     /**
-     * @param json JSON response.
-     * @param ptrn Pattern to match.
+     * @param content Content to check.
      */
-    @SuppressWarnings("TypeMayBeWeakened")
-    private void jsonEquals(String json, String ptrn) {
-        assertTrue("JSON mismatch [json=" + json + ", ptrn=" + ptrn + ']', Pattern.matches(ptrn, json));
+    private void assertResponseContainsError(String content) throws IOException {
+        assertNotNull(content);
+        assertFalse(content.isEmpty());
+
+        JsonNode node = JSON_MAPPER.readTree(content);
+
+        assertEquals(1, node.get("successStatus").asInt());
+        assertFalse(node.get("error").asText().isEmpty());
+        assertTrue(node.get("response").isNull());
+        assertTrue(node.get("sessionToken").asText().isEmpty());
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @param content Content to check.
+     * @param err Error message.
      */
-    private String cachePattern(String res, boolean success) {
-        return "\\{\\\"affinityNodeId\\\":\\\"\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}\\\"\\," +
-            "\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":\\\"" + res + "\\\"\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    private void assertResponseContainsError(String content, String err) throws IOException {
+        assertNotNull(content);
+        assertFalse(content.isEmpty());
+
+        assertNotNull(err);
+
+        JsonNode node = JSON_MAPPER.readTree(content);
+
+        assertEquals(1, node.get("successStatus").asInt());
+
+        assertTrue(node.get("response").isNull());
+        assertEquals(err, node.get("error").asText());
     }
 
     /**
-     * @param err Error.
-     * @return Regex pattern for JSON.
+     * @param content Content to check.
      */
-    private String errorPattern(String err) {
-        return "\\{" +
-            "\\\"error\\\":\\\"" + err + "\\\"\\," +
-            "\\\"response\\\":null\\," +
-            "\\\"sessionToken\\\":\\\"\\\"," +
-            "\\\"successStatus\\\":" + 1 + "\\}";
+    private JsonNode jsonCacheOperationResponse(String content, boolean bulk) throws IOException {
+        assertNotNull(content);
+        assertFalse(content.isEmpty());
+
+        JsonNode node = JSON_MAPPER.readTree(content);
+
+        assertEquals(bulk, node.get("affinityNodeId").asText().isEmpty());
+        assertEquals(0, node.get("successStatus").asInt());
+        assertTrue(node.get("error").asText().isEmpty());
+
+        assertNotSame(securityEnabled(), node.get("sessionToken").asText().isEmpty());
+
+        return node.get("response");
     }
 
     /**
+     * @param content Content to check.
      * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
      */
-    private String integerPattern(int res, boolean success) {
-        return "\\{\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    private void assertCacheOperation(String content, Object res) throws IOException {
+        JsonNode ret = jsonCacheOperationResponse(content, false);
+
+        assertEquals(String.valueOf(res), ret.asText());
     }
 
     /**
+     * @param content Content to check.
      * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
      */
-    private String cacheBulkPattern(String res, boolean success) {
-        return "\\{\\\"affinityNodeId\\\":\\\"\\\"\\," +
-            "\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    private void assertCacheBulkOperation(String content, Object res) throws IOException {
+        JsonNode ret = jsonCacheOperationResponse(content, true);
+
+        assertEquals(String.valueOf(res), ret.asText());
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @param content Content to check.
      */
-    private String cacheBulkPattern(int res, boolean success) {
-        return "\\{\\\"affinityNodeId\\\":\\\"\\\"\\," +
-            "\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    private void assertCacheMetrics(String content) throws IOException {
+        JsonNode ret = jsonCacheOperationResponse(content, true);
+
+        assertTrue(ret.isObject());
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @param content Content to check.
+     * @return REST result.
      */
-    private String cachePattern(boolean res, boolean success) {
-        return "\\{\\\"affinityNodeId\\\":\\\"\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}\\\"\\," +
-            "\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    protected JsonNode jsonResponse(String content) throws IOException {
+        assertNotNull(content);
+        assertFalse(content.isEmpty());
+
+        JsonNode node = JSON_MAPPER.readTree(content);
+
+        assertEquals(0, node.get("successStatus").asInt());
+        assertTrue(node.get("error").asText().isEmpty());
+
+        assertNotSame(securityEnabled(), node.get("sessionToken").asText().isEmpty());
+
+        return node.get("response");
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @param content Content to check.
+     * @return Task result.
      */
-    private String cacheBulkPattern(boolean res, boolean success) {
-        return "\\{\\\"affinityNodeId\\\":\\\"\\\"\\," +
-            "\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    protected JsonNode jsonTaskResult(String content) throws IOException {
+        assertNotNull(content);
+        assertFalse(content.isEmpty());
+
+        JsonNode node = JSON_MAPPER.readTree(content);
+
+        assertEquals(0, node.get("successStatus").asInt());
+        assertTrue(node.get("error").asText().isEmpty());
+        assertFalse(node.get("response").isNull());
+
+        assertEquals(securityEnabled(), !node.get("sessionToken").asText().isEmpty());
+
+        JsonNode res = node.get("response");
+
+        assertTrue(res.isObject());
+
+        assertFalse(res.get("id").asText().isEmpty());
+        assertTrue(res.get("finished").asBoolean());
+        assertTrue(res.get("error").asText().isEmpty());
+
+        return res.get("result");
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @throws Exception If failed.
      */
-    private String cacheMetricsPattern(String res, boolean success) {
-        return "\\{\\\"affinityNodeId\\\":\\\"(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})?\\\"\\," +
-            "\\\"error\\\":\\\"\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    public void testGet() throws Exception {
+        jcache().put("getKey", "getVal");
+
+        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "getKey"));
+
+        info("Get command result: " + ret);
+
+        assertCacheOperation(ret, "getVal");
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @throws Exception If failed.
+     */
+    public void testSimpleObject()  throws Exception {
+        SimplePerson p = new SimplePerson(1, "Test", java.sql.Date.valueOf("1977-01-26"), 1000.55, 39, "CIO", 25);
+
+        jcache().put("simplePersonKey", p);
+
+        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "simplePersonKey"));
+
+        info("Get command result: " + ret);
+
+        JsonNode res = jsonCacheOperationResponse(ret, false);
+
+        assertEquals(res.get("id").asInt(), p.id);
+        assertEquals(res.get("name").asText(), p.name);
+        assertEquals(res.get("birthday").asText(), p.birthday.toString());
+        assertEquals(res.get("salary").asDouble(), p.salary);
+        assertNull(res.get("age"));
+        assertNull(res.get("post"));
+        assertNull(res.get("bonus"));
+    }
+
+    /**
+     * @throws Exception If failed.
      */
-    private String pattern(String res, boolean success) {
-        return "\\{\\\"error\\\":\\\"" + (!success ? ".+" : "") + "\\\"\\," +
-            "\\\"response\\\":" + res + "\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    public void testDate() throws Exception {
+        java.util.Date utilDate = new java.util.Date();
+
+        DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);
+
+        String date = formatter.format(utilDate);
+
+        jcache().put("utilDateKey", utilDate);
+
+        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "utilDateKey"));
+
+        info("Get command result: " + ret);
+
+        assertCacheOperation(ret, date);
+
+        java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
+
+        jcache().put("sqlDateKey", sqlDate);
+
+        ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "sqlDateKey"));
+
+        info("Get SQL result: " + ret);
+
+        assertCacheOperation(ret, sqlDate.toString());
+
+        jcache().put("timestampKey", new java.sql.Timestamp(utilDate.getTime()));
+
+        ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "timestampKey"));
+
+        info("Get timestamp: " + ret);
+
+        assertCacheOperation(ret, date);
     }
 
     /**
-     * @param res Response.
-     * @param success Success flag.
-     * @return Regex pattern for JSON.
+     * @throws Exception If failed.
      */
-    private String stringPattern(String res, boolean success) {
-        return "\\{\\\"error\\\":\\\"" + (!success ? ".+" : "") + "\\\"\\," +
-            "\\\"response\\\":\\\"" + res + "\\\"\\," +
-            "\\\"sessionToken\\\":\\\"" + (securityEnabled() && success ? ".+" : "") + "\\\"," +
-            "\\\"successStatus\\\":" + (success ? 0 : 1) + "\\}";
+    public void testUUID() throws Exception {
+        UUID uuid = UUID.randomUUID();
+
+        jcache().put("uuidKey", uuid);
+
+        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "uuidKey"));
+
+        info("Get command result: " + ret);
+
+        assertCacheOperation(ret, uuid.toString());
+
+        IgniteUuid igniteUuid = IgniteUuid.fromUuid(uuid);
+
+        jcache().put("igniteUuidKey", igniteUuid);
+
+        ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "igniteUuidKey"));
+
+        info("Get command result: " + ret);
+
+        assertCacheOperation(ret, igniteUuid.toString());
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testGet() throws Exception {
-        jcache().put("getKey", "getVal");
+    public void testTuple() throws Exception {
+        T2 t = new T2("key", "value");
 
-        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "getKey"));
+        jcache().put("tupleKey", t);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET.key(), "key", "tupleKey"));
 
         info("Get command result: " + ret);
 
-        jsonEquals(ret, cachePattern("getVal", true));
+        JsonNode res = jsonCacheOperationResponse(ret, false);
+
+        assertEquals(t.getKey(), res.get("key").asText());
+        assertEquals(t.getValue(), res.get("value").asText());
     }
 
     /**
@@ -294,12 +449,9 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_SIZE.key()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Size command result: " + ret);
 
-        jsonEquals(ret, cacheBulkPattern(1, true));
+        assertCacheBulkOperation(ret, 1);
     }
 
     /**
@@ -308,12 +460,9 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testIgniteName() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.NAME.key()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Name command result: " + ret);
 
-        jsonEquals(ret, stringPattern(getTestGridName(0), true));
+        assertEquals(getTestGridName(0), jsonResponse(ret).asText());
     }
 
     /**
@@ -322,17 +471,13 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testGetOrCreateCache() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.GET_OR_CREATE_CACHE.key(), "cacheName", "testCache"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Name command result: " + ret);
 
         grid(0).cache("testCache").put("1", "1");
 
         ret = content(F.asMap("cmd", GridRestCommand.DESTROY_CACHE.key(), "cacheName", "testCache"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        assertTrue(jsonResponse(ret).isNull());
 
         assertNull(grid(0).cache("testCache"));
     }
@@ -341,20 +486,19 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
      * @throws Exception If failed.
      */
     public void testGetAll() throws Exception {
-        jcache().put("getKey1", "getVal1");
-        jcache().put("getKey2", "getVal2");
+        final Map<String, String> entries = F.asMap("getKey1", "getVal1", "getKey2", "getVal2");
 
-        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET_ALL.key(), "k1", "getKey1", "k2", "getKey2"));
+        jcache().putAll(entries);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET_ALL.key(), "k1", "getKey1", "k2", "getKey2"));
 
         info("Get all command result: " + ret);
 
-        jsonEquals(ret,
-            // getKey[12] is used since the order is not determined.
-            cacheBulkPattern("\\{\\\"getKey[12]\\\":\\\"getVal[12]\\\"\\,\\\"getKey[12]\\\":\\\"getVal[12]\\\"\\}",
-                true));
+        JsonNode res = jsonCacheOperationResponse(ret, true);
+
+        assertTrue(res.isObject());
+
+        assertTrue(entries.equals(JSON_MAPPER.treeToValue(res, Map.class)));
     }
 
     /**
@@ -363,9 +507,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testIncorrectPut() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_PUT.key(), "key", "key0"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-        jsonEquals(ret, errorPattern("Failed to find mandatory parameter in request: val"));
+        assertResponseContainsError(ret, "Failed to find mandatory parameter in request: val");
     }
 
     /**
@@ -376,10 +518,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_CONTAINS_KEY.key(), "key", "key0"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -392,10 +531,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_CONTAINS_KEYS.key(),
             "k1", "key0", "k2", "key1"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cacheBulkPattern(true, true));
+        assertCacheBulkOperation(ret, true);
     }
 
     /**
@@ -406,10 +542,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET_AND_PUT.key(), "key", "key0", "val", "val1"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern("val0", true));
+        assertCacheOperation(ret, "val0");
 
         assertEquals("val1", grid(0).cache(null).get("key0"));
     }
@@ -423,10 +556,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET_AND_PUT_IF_ABSENT.key(),
             "key", "key0", "val", "val1"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern("val0", true));
+        assertCacheOperation(ret, "val0");
 
         assertEquals("val0", grid(0).cache(null).get("key0"));
     }
@@ -438,10 +568,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_PUT_IF_ABSENT.key(),
             "key", "key0", "val", "val1"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("val1", grid(0).cache(null).get("key0"));
     }
@@ -455,20 +582,14 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_REMOVE_VALUE.key(),
             "key", "key0", "val", "val1"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(false, true));
+        assertCacheOperation(ret, false);
 
         assertEquals("val0", grid(0).cache(null).get("key0"));
 
         ret = content(F.asMap("cmd", GridRestCommand.CACHE_REMOVE_VALUE.key(),
             "key", "key0", "val", "val0"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertNull(grid(0).cache(null).get("key0"));
     }
@@ -482,10 +603,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET_AND_REMOVE.key(),
             "key", "key0"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern("val0", true));
+        assertCacheOperation(ret, "val0");
 
         assertNull(grid(0).cache(null).get("key0"));
     }
@@ -499,20 +617,14 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_REPLACE_VALUE.key(),
             "key", "key0", "val", "val1", "val2", "val2"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(false, true));
+        assertCacheOperation(ret, false);
 
         assertEquals("val0", grid(0).cache(null).get("key0"));
 
         ret = content(F.asMap("cmd", GridRestCommand.CACHE_REPLACE_VALUE.key(),
             "key", "key0", "val", "val1", "val2", "val0"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("val1", grid(0).cache(null).get("key0"));
     }
@@ -526,10 +638,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_GET_AND_REPLACE.key(),
             "key", "key0", "val", "val1"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern("val0", true));
+        assertCacheOperation(ret, "val0");
 
         assertEquals("val1", grid(0).cache(null).get("key0"));
     }
@@ -541,14 +650,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_PUT.key(),
             "key", "putKey", "val", "putVal"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Put command result: " + ret);
 
         assertEquals("putVal", jcache().localPeek("putKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -558,10 +664,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_PUT.key(),
             "key", "putKey", "val", "putVal", "exp", "2000"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("putVal", jcache().get("putKey"));
 
@@ -579,10 +682,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_ADD.key(),
             "key", "addKey2", "val", "addVal2"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("addVal1", jcache().localPeek("addKey1", CachePeekMode.ONHEAP));
         assertEquals("addVal2", jcache().localPeek("addKey2", CachePeekMode.ONHEAP));
@@ -595,10 +695,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_ADD.key(),
             "key", "addKey", "val", "addVal", "exp", "2000"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("addVal", jcache().get("addKey"));
 
@@ -615,15 +712,12 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
             "k1", "putKey1", "k2", "putKey2",
             "v1", "putVal1", "v2", "putVal2"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Put all command result: " + ret);
 
         assertEquals("putVal1", jcache().localPeek("putKey1", CachePeekMode.ONHEAP));
         assertEquals("putVal2", jcache().localPeek("putKey2", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cacheBulkPattern(true, true));
+        assertCacheBulkOperation(ret, true);
     }
 
     /**
@@ -637,14 +731,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_REMOVE.key(),
             "key", "rmvKey"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Remove command result: " + ret);
 
         assertNull(jcache().localPeek("rmvKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -664,9 +755,6 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_REMOVE_ALL.key(),
             "k1", "rmvKey1", "k2", "rmvKey2"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Remove all command result: " + ret);
 
         assertNull(jcache().localPeek("rmvKey1", CachePeekMode.ONHEAP));
@@ -674,13 +762,10 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         assertEquals("rmvVal3", jcache().localPeek("rmvKey3", CachePeekMode.ONHEAP));
         assertEquals("rmvVal4", jcache().localPeek("rmvKey4", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cacheBulkPattern(true, true));
+        assertCacheBulkOperation(ret, true);
 
         ret = content(F.asMap("cmd", GridRestCommand.CACHE_REMOVE_ALL.key()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Remove all command result: " + ret);
 
         assertNull(jcache().localPeek("rmvKey1", CachePeekMode.ONHEAP));
@@ -689,7 +774,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         assertNull(jcache().localPeek("rmvKey4", CachePeekMode.ONHEAP));
         assertTrue(jcache().localSize() == 0);
 
-        jsonEquals(ret, cacheBulkPattern(true, true));
+        assertCacheBulkOperation(ret, true);
     }
 
     /**
@@ -703,14 +788,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_CAS.key(),
             "key", "casKey", "val2", "casOldVal", "val1", "casNewVal"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("CAS command result: " + ret);
 
         assertEquals("casNewVal", jcache().localPeek("casKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         jcache().remove("casKey");
     }
@@ -726,14 +808,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_REPLACE.key(),
             "key", "repKey", "val", "repVal"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Replace command result: " + ret);
 
         assertEquals("repVal", jcache().localPeek("repKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -747,10 +826,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_REPLACE.key(),
             "key", "replaceKey", "val", "replaceValNew", "exp", "2000"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("replaceValNew", jcache().get("replaceKey"));
 
@@ -769,10 +845,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_APPEND.key(),
             "key", "appendKey", "val", "_suffix"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("appendVal_suffix", jcache().get("appendKey"));
     }
@@ -786,10 +859,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_PREPEND.key(),
             "key", "prependKey", "val", "prefix_"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
 
         assertEquals("prefix_prependVal", jcache().get("prependKey"));
     }
@@ -801,20 +871,16 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.ATOMIC_INCREMENT.key(),
             "key", "incrKey", "init", "2", "delta", "3"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, integerPattern(5, true));
+        JsonNode res = jsonResponse(ret);
 
+        assertEquals(5, res.asInt());
         assertEquals(5, grid(0).atomicLong("incrKey", 0, true).get());
 
         ret = content(F.asMap("cmd", GridRestCommand.ATOMIC_INCREMENT.key(), "key", "incrKey", "delta", "10"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, integerPattern(15, true));
+        res = jsonResponse(ret);
 
+        assertEquals(15, res.asInt());
         assertEquals(15, grid(0).atomicLong("incrKey", 0, true).get());
     }
 
@@ -825,21 +891,17 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.ATOMIC_DECREMENT.key(),
             "key", "decrKey", "init", "15", "delta", "10"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, integerPattern(5, true));
+        JsonNode res = jsonResponse(ret);
 
+        assertEquals(5, res.asInt());
         assertEquals(5, grid(0).atomicLong("decrKey", 0, true).get());
 
         ret = content(F.asMap("cmd", GridRestCommand.ATOMIC_DECREMENT.key(),
             "key", "decrKey", "delta", "3"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        jsonEquals(ret, integerPattern(2, true));
+        res = jsonResponse(ret);
 
+        assertEquals(2, res.asInt());
         assertEquals(2, grid(0).atomicLong("decrKey", 0, true).get());
     }
 
@@ -854,14 +916,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_CAS.key(),
             "key", "casKey", "val2", "casOldVal"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("CAR command result: " + ret);
 
         assertNull(jcache().localPeek("casKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -873,14 +932,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_CAS.key(),
             "key", "casKey", "val1", "casNewVal"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("PutIfAbsent command result: " + ret);
 
         assertEquals("casNewVal", jcache().localPeek("casKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -893,14 +949,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_CAS.key(), "key", "casKey"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("CAS Remove command result: " + ret);
 
         assertNull(jcache().localPeek("casKey", CachePeekMode.ONHEAP));
 
-        jsonEquals(ret, cachePattern(true, true));
+        assertCacheOperation(ret, true);
     }
 
     /**
@@ -909,12 +962,9 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testMetrics() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.CACHE_METRICS.key()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Cache metrics command result: " + ret);
 
-        jsonEquals(ret, cacheMetricsPattern("\\{.+\\}", true));
+        assertCacheMetrics(ret);
     }
 
     /**
@@ -931,20 +981,16 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Cache metadata result: " + ret);
 
-        jsonEquals(ret, pattern("\\[.+\\]", true));
-
-        Collection<Map> results = (Collection)JSONObject.fromObject(ret).get("response");
+        JsonNode arr = jsonResponse(ret);
 
-        assertEquals(metas.size(), results.size());
-        assertEquals(cacheNameArg, F.first(results).get("cacheName"));
+        assertTrue(arr.isArray());
+        assertEquals(metas.size(), arr.size());
 
-        for (Map res : results) {
-            final Object cacheName = res.get("cacheName");
+        for (JsonNode item : arr) {
+            JsonNode cacheNameNode = item.get("cacheName");
+            final String cacheName = cacheNameNode != null ? cacheNameNode.asText() : null;
 
             GridCacheSqlMetadata meta = F.find(metas, null, new P1<GridCacheSqlMetadata>() {
                 @Override public boolean apply(GridCacheSqlMetadata meta) {
@@ -954,49 +1000,60 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
             assertNotNull("REST return metadata for unexpected cache: " + cacheName, meta);
 
-            Collection types = (Collection)res.get("types");
+            JsonNode types = item.get("types");
 
             assertNotNull(types);
-            assertEqualsCollections(meta.types(), types);
+            assertFalse(types.isNull());
+
+            assertEqualsCollections(meta.types(), JSON_MAPPER.treeToValue(types, Collection.class));
 
-            Map keyClasses = (Map)res.get("keyClasses");
+            JsonNode keyClasses = item.get("keyClasses");
 
             assertNotNull(keyClasses);
-            assertTrue(meta.keyClasses().equals(keyClasses));
+            assertFalse(keyClasses.isNull());
 
-            Map valClasses = (Map)res.get("valClasses");
+            assertTrue(meta.keyClasses().equals(JSON_MAPPER.treeToValue(keyClasses, Map.class)));
+
+            JsonNode valClasses = item.get("valClasses");
 
             assertNotNull(valClasses);
-            assertTrue(meta.valClasses().equals(valClasses));
+            assertFalse(valClasses.isNull());
+
+            assertTrue(meta.valClasses().equals(JSON_MAPPER.treeToValue(valClasses, Map.class)));
 
-            Map fields = (Map)res.get("fields");
+            JsonNode fields = item.get("fields");
 
             assertNotNull(fields);
-            assertTrue(meta.fields().equals(fields));
+            assertFalse(fields.isNull());
+            assertTrue(meta.fields().equals(JSON_MAPPER.treeToValue(fields, Map.class)));
 
-            Map indexesByType = (Map)res.get("indexes");
+            JsonNode indexesByType = item.get("indexes");
 
             assertNotNull(indexesByType);
+            assertFalse(indexesByType.isNull());
             assertEquals(meta.indexes().size(), indexesByType.size());
 
             for (Map.Entry<String, Collection<GridCacheSqlIndexMetadata>> metaIndexes : meta.indexes().entrySet()) {
-                Collection<Map> indexes = (Collection<Map>)indexesByType.get(metaIndexes.getKey());
+                JsonNode indexes = indexesByType.get(metaIndexes.getKey());
 
                 assertNotNull(indexes);
+                assertFalse(indexes.isNull());
                 assertEquals(metaIndexes.getValue().size(), indexes.size());
 
                 for (final GridCacheSqlIndexMetadata metaIdx : metaIndexes.getValue()) {
-                    Map idx = F.find(indexes, null, new P1<Map>() {
-                        @Override public boolean apply(Map map) {
-                            return metaIdx.name().equals(map.get("name"));
+                    JsonNode idx = F.find(indexes, null, new P1<JsonNode>() {
+                        @Override public boolean apply(JsonNode idx) {
+                            return metaIdx.name().equals(idx.get("name").asText());
                         }
                     });
 
                     assertNotNull(idx);
 
-                    assertEqualsCollections(metaIdx.fields(), (Collection)idx.get("fields"));
-                    assertEqualsCollections(metaIdx.descendings(), (Collection)idx.get("descendings"));
-                    assertEquals(metaIdx.unique(), idx.get("unique"));
+                    assertEqualsCollections(metaIdx.fields(),
+                        JSON_MAPPER.treeToValue(idx.get("fields"), Collection.class));
+                    assertEqualsCollections(metaIdx.descendings(),
+                        JSON_MAPPER.treeToValue(idx.get("descendings"), Collection.class));
+                    assertEquals(metaIdx.unique(), idx.get("unique").asBoolean());
                 }
             }
         }
@@ -1037,32 +1094,28 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testTopology() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.TOPOLOGY.key(), "attr", "false", "mtr", "false"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Topology command result: " + ret);
 
-        jsonEquals(ret, pattern("\\[\\{.+\\}\\]", true));
+        JsonNode res = jsonResponse(ret);
 
-        JSONObject json = JSONObject.fromObject(ret);
+        assertEquals(GRID_CNT, res.size());
 
-        Collection<Map> nodes = (Collection)json.get("response");
+        for (JsonNode node : res) {
+            assertTrue(node.get("attributes").isNull());
+            assertTrue(node.get("metrics").isNull());
 
-        assertEquals(GRID_CNT, nodes.size());
+            JsonNode caches = node.get("caches");
 
-        for (Map node : nodes) {
-            assertEquals(JSONNull.getInstance(), node.get("attributes"));
-            assertEquals(JSONNull.getInstance(), node.get("metrics"));
-
-            Collection<Map> caches = (Collection)node.get("caches");
+            assertFalse(caches.isNull());
 
             Collection<IgniteCacheProxy<?, ?>> publicCaches = grid(0).context().cache().publicCaches();
 
-            assertNotNull(caches);
             assertEquals(publicCaches.size(), caches.size());
 
-            for (Map cache : caches) {
-                final String cacheName = cache.get("name").equals("") ? null : (String)cache.get("name");
+            for (JsonNode cache : caches) {
+                String cacheName0 = cache.get("name").asText();
+
+                final String cacheName = cacheName0.equals("") ? null : cacheName0;
 
                 IgniteCacheProxy<?, ?> publicCache = F.find(publicCaches, null, new P1<IgniteCacheProxy<?, ?>>() {
                     @Override public boolean apply(IgniteCacheProxy<?, ?> c) {
@@ -1072,9 +1125,9 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
                 assertNotNull(publicCache);
 
-                CacheMode cacheMode = CacheMode.valueOf((String)cache.get("mode"));
+                CacheMode cacheMode = CacheMode.valueOf(cache.get("mode").asText());
 
-                assertEquals(publicCache.getConfiguration(CacheConfiguration.class).getCacheMode(),cacheMode);
+                assertEquals(publicCache.getConfiguration(CacheConfiguration.class).getCacheMode(), cacheMode);
             }
         }
     }
@@ -1086,31 +1139,30 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String ret = content(F.asMap("cmd", GridRestCommand.NODE.key(), "attr", "true", "mtr", "true", "id",
             grid(0).localNode().id().toString()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Topology command result: " + ret);
 
-        jsonEquals(ret, pattern("\\{.+\\}", true));
+        JsonNode res = jsonResponse(ret);
 
-        ret = content(F.asMap("cmd", GridRestCommand.NODE.key(), "attr", "false", "mtr", "false", "ip", LOC_HOST));
+        assertTrue(res.get("attributes").isObject());
+        assertTrue(res.get("metrics").isObject());
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        ret = content(F.asMap("cmd", GridRestCommand.NODE.key(), "attr", "false", "mtr", "false", "ip", LOC_HOST));
 
         info("Topology command result: " + ret);
 
-        jsonEquals(ret, pattern("\\{.+\\}", true));
+        res = jsonResponse(ret);
+
+        assertTrue(res.get("attributes").isNull());
+        assertTrue(res.get("metrics").isNull());
 
         ret = content(F.asMap("cmd", GridRestCommand.NODE.key(), "attr", "false", "mtr", "false", "ip", LOC_HOST, "id",
             UUID.randomUUID().toString()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Topology command result: " + ret);
 
-        jsonEquals(ret, pattern("null", true));
+        res = jsonResponse(ret);
+
+        assertTrue(res.isNull());
     }
 
     /**
@@ -1123,52 +1175,340 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testExe() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.EXE.key()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Exe command result: " + ret);
 
-        jsonEquals(ret, pattern("null", false));
+        assertResponseContainsError(ret);
 
         // Attempt to execute unknown task (UNKNOWN_TASK) will result in exception on server.
         ret = content(F.asMap("cmd", GridRestCommand.EXE.key(), "name", "UNKNOWN_TASK"));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Exe command result: " + ret);
 
-        jsonEquals(ret, pattern("null", false));
+        assertResponseContainsError(ret);
 
         grid(0).compute().localDeployTask(TestTask1.class, TestTask1.class.getClassLoader());
         grid(0).compute().localDeployTask(TestTask2.class, TestTask2.class.getClassLoader());
 
         ret = content(F.asMap("cmd", GridRestCommand.EXE.key(), "name", TestTask1.class.getName()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
         info("Exe command result: " + ret);
 
-        jsonEquals(ret, pattern("\\{.+\\}", true));
+        JsonNode res = jsonTaskResult(ret);
 
-        ret = content(F.asMap("cmd", GridRestCommand.EXE.key(), "name", TestTask2.class.getName()));
+        assertTrue(res.isNull());
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        ret = content(F.asMap("cmd", GridRestCommand.EXE.key(), "name", TestTask2.class.getName()));
 
         info("Exe command result: " + ret);
 
-        jsonEquals(ret, pattern("\\{.+" + TestTask2.RES + ".+\\}", true));
+        res = jsonTaskResult(ret);
 
-        ret = content(F.asMap("cmd", GridRestCommand.RESULT.key()));
+        assertEquals(TestTask2.RES, res.asText());
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        ret = content(F.asMap("cmd", GridRestCommand.RESULT.key()));
 
         info("Exe command result: " + ret);
 
-        jsonEquals(ret, pattern("null", false));
+        assertResponseContainsError(ret);
+    }
+
+    /**
+     * Tests execution of Visor tasks via {@link VisorGatewayTask}.
+     *
+     * @throws Exception If failed.
+     */
+    public void testVisorGateway() throws Exception {
+        ClusterNode locNode = grid(1).localNode();
+
+        final IgniteUuid cid = grid(1).context().cache().internalCache("person").context().dynamicDeploymentId();
+
+        String ret = content(new VisorGatewayArgument(VisorCacheConfigurationCollectorTask.class)
+            .forNode(locNode)
+            .collection(IgniteUuid.class, cid));
+
+        info("VisorCacheConfigurationCollectorTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheNodesTask.class)
+            .forNode(locNode)
+            .argument("person"));
+
+        info("VisorCacheNodesTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheLoadTask.class)
+            .forNode(locNode)
+            .tuple3(Set.class, Long.class, Object[].class, "person", 0, "null"));
+
+        info("VisorCacheLoadTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheSwapBackupsTask.class)
+            .forNode(locNode)
+            .set(String.class, "person"));
+
+        info("VisorCacheSwapBackupsTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheRebalanceTask.class)
+            .forNode(locNode)
+            .set(String.class, "person"));
+
+        info("VisorCacheRebalanceTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheMetadataTask.class)
+            .forNode(locNode)
+            .argument("person"));
+
+        info("VisorCacheMetadataTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheResetMetricsTask.class)
+            .forNode(locNode)
+            .argument("person"));
+
+        info("VisorCacheResetMetricsTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorIgfsSamplingStateTask.class)
+            .forNode(locNode)
+            .pair(String.class, Boolean.class, "igfs", false));
+
+        info("VisorIgfsSamplingStateTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorIgfsProfilerClearTask.class)
+            .forNode(locNode)
+            .argument("igfs"));
+
+        info("VisorIgfsProfilerClearTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorIgfsProfilerTask.class)
+            .forNode(locNode)
+            .argument("igfs"));
+
+        info("VisorIgfsProfilerTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorIgfsFormatTask.class)
+            .forNode(locNode)
+            .argument("igfs"));
+
+        info("VisorIgfsFormatTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorIgfsResetMetricsTask.class)
+            .forNode(locNode)
+            .set(String.class, "igfs"));
+
+        info("VisorIgfsResetMetricsTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorThreadDumpTask.class)
+            .forNode(locNode));
+
+        info("VisorThreadDumpTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorLatestTextFilesTask.class)
+            .forNode(locNode)
+            .pair(String.class, String.class, "", ""));
+
+        info("VisorLatestTextFilesTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorLatestVersionTask.class)
+            .forNode(locNode));
+
+        info("VisorLatestVersionTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorFileBlockTask.class)
+            .forNode(locNode)
+            .argument(VisorFileBlockTask.VisorFileBlockArg.class, "", 0L, 1, 0L));
+
+        info("VisorFileBlockTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorNodePingTask.class)
+            .forNode(locNode)
+            .argument(UUID.class, locNode.id()));
+
+        info("VisorNodePingTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorNodeConfigurationCollectorTask.class)
+            .forNode(locNode));
+
+        info("VisorNodeConfigurationCollectorTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorComputeResetMetricsTask.class)
+            .forNode(locNode));
+
+        info("VisorComputeResetMetricsTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorQueryTask.class)
+            .forNode(locNode)
+            .argument(VisorQueryArg.class, "person", URLEncoder.encode("select * from Person", CHARSET), false, 1));
+
+        info("VisorQueryTask result: " + ret);
+
+        JsonNode res = jsonTaskResult(ret);
+
+        final String qryId = res.get("value").get("queryId").asText();
+
+        ret = content(new VisorGatewayArgument(VisorQueryNextPageTask.class)
+            .forNode(locNode)
+            .pair(String.class, Integer.class, qryId, 1));
+
+        info("VisorQueryNextPageTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorQueryCleanupTask.class)
+            .map(UUID.class, Set.class, F.asMap(locNode.id(), qryId)));
+
+        info("VisorQueryCleanupTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorResolveHostNameTask.class)
+            .forNode(locNode));
+
+        info("VisorResolveHostNameTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        // Multinode tasks
+
+        ret = content(new VisorGatewayArgument(VisorComputeCancelSessionsTask.class)
+            .map(UUID.class, Set.class, new HashMap()));
+
+        info("VisorComputeCancelSessionsTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheMetricsCollectorTask.class)
+            .pair(Boolean.class, Set.class, false, "person"));
+
+        info("VisorCacheMetricsCollectorTask result: " + ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheMetricsCollectorTask.class)
+            .forNodes(grid(1).cluster().nodes())
+            .pair(Boolean.class, Set.class, false, "person"));
+
+        info("VisorCacheMetricsCollectorTask (with nodes) result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorLogSearchTask.class)
+            .argument(VisorLogSearchTask.VisorLogSearchArg.class, ".", ".", "abrakodabra.txt", 1));
+
+        info("VisorLogSearchTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorNodeGcTask.class));
+
+        info("VisorNodeGcTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorAckTask.class)
+            .argument("MSG"));
+
+        info("VisorAckTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorNodeEventsCollectorTask.class)
+            .argument(VisorNodeEventsCollectorTask.VisorNodeEventsCollectorTaskArg.class,
+                "null", "null", "null", "taskName", "null"));
+
+        info("VisorNodeEventsCollectorTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorNodeDataCollectorTask.class)
+            .argument(VisorNodeDataCollectorTaskArg.class, false,
+                "CONSOLE_" + UUID.randomUUID(), UUID.randomUUID(), 10, false));
+
+        info("VisorNodeDataCollectorTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorComputeToggleMonitoringTask.class)
+            .pair(String.class, Boolean.class, UUID.randomUUID(), false));
+
+        info("VisorComputeToggleMonitoringTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorNodeSuppressedErrorsTask.class)
+            .map(UUID.class, Long.class, new HashMap()));
+
+        info("VisorNodeSuppressedErrorsTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheClearTask.class)
+            .forNode(locNode)
+            .argument("person"));
+
+        info("VisorCacheClearTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        /** Spring XML to start cache via Visor task. */
+        final String START_CACHE =
+            "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n" +
+                    "    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
+                    "    xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n" +
+                    "        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\">\n" +
+                    "    <bean id=\"cacheConfiguration\" class=\"org.apache.ignite.configuration.CacheConfiguration\">\n" +
+                    "        <property name=\"cacheMode\" value=\"PARTITIONED\"/>\n" +
+                    "        <property name=\"name\" value=\"c\"/>\n" +
+                    "   </bean>\n" +
+                    "</beans>";
+
+        ret = content(new VisorGatewayArgument(VisorCacheStartTask.class)
+            .argument(VisorCacheStartTask.VisorCacheStartArg.class, false, "person2",
+                URLEncoder.encode(START_CACHE, CHARSET)));
+
+        info("VisorCacheStartTask result: " + ret);
+
+        jsonTaskResult(ret);
+
+        ret = content(new VisorGatewayArgument(VisorCacheStopTask.class)
+            .forNode(locNode)
+            .argument(String.class, "c"));
+
+        info("VisorCacheStopTask result: " + ret);
+
+        jsonTaskResult(ret);
     }
 
     /**
@@ -1177,10 +1517,9 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     public void testVersion() throws Exception {
         String ret = content(F.asMap("cmd", GridRestCommand.VERSION.key()));
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        JsonNode res = jsonResponse(ret);
 
-        jsonEquals(ret, stringPattern(".+", true));
+        assertEquals(VER_STR, res.asText());
     }
 
     /**
@@ -1194,18 +1533,13 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         params.put("type", "Person");
         params.put("pageSize", "10");
         params.put("cacheName", "person");
-        params.put("qry", URLEncoder.encode(qry));
+        params.put("qry", URLEncoder.encode(qry, CHARSET));
         params.put("arg1", "1000");
         params.put("arg2", "2000");
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
-
-        List items = (List)((Map)json.get("response")).get("items");
+        JsonNode items = jsonResponse(ret).get("items");
 
         assertEquals(2, items.size());
 
@@ -1223,12 +1557,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
-
-        List items = (List)((Map)json.get("response")).get("items");
+        JsonNode items = jsonResponse(ret).get("items");
 
         assertEquals(4, items.size());
 
@@ -1247,12 +1576,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
-
-        List items = (List)((Map)json.get("response")).get("items");
+        JsonNode items = jsonResponse(ret).get("items");
 
         assertEquals(2, items.size());
 
@@ -1263,22 +1587,17 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
      * @throws Exception If failed.
      */
     public void testIncorrectFilterQueryScan() throws Exception {
+        String clsName = ScanFilter.class.getName() + 1;
+
         Map<String, String> params = new HashMap<>();
         params.put("cmd", GridRestCommand.EXECUTE_SCAN_QUERY.key());
         params.put("pageSize", "10");
         params.put("cacheName", "person");
-        params.put("className", ScanFilter.class.getName() + 1);
+        params.put("className", clsName);
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
-
-        String err = (String)json.get("error");
-
-        assertTrue(err.contains("Failed to find target class"));
+        assertResponseContainsError(ret, "Failed to find target class: " + clsName);
     }
 
     /**
@@ -1293,42 +1612,33 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         params.put("cmd", GridRestCommand.EXECUTE_SQL_QUERY.key());
         params.put("type", "String");
         params.put("pageSize", "1");
-        params.put("qry", URLEncoder.encode("select * from String"));
+        params.put("qry", URLEncoder.encode("select * from String", CHARSET));
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
+        JsonNode qryId = jsonResponse(ret).get("queryId");
 
-        Integer qryId = (Integer)((Map)json.get("response")).get("queryId");
-
-        assertNotNull(qryId);
+        assertFalse(jsonResponse(ret).get("queryId").isNull());
 
         ret = content(F.asMap("cmd", GridRestCommand.FETCH_SQL_QUERY.key(),
-            "pageSize", "1", "qryId", String.valueOf(qryId)));
-
-        json = JSONObject.fromObject(ret);
+            "pageSize", "1", "qryId", qryId.asText()));
 
-        Integer qryId0 = (Integer)((Map)json.get("response")).get("queryId");
+        JsonNode res = jsonResponse(ret);
 
-        Boolean last = (Boolean)((Map)json.get("response")).get("last");
+        JsonNode qryId0 = jsonResponse(ret).get("queryId");
 
         assertEquals(qryId0, qryId);
-        assertFalse(last);
+        assertFalse(res.get("last").asBoolean());
 
         ret = content(F.asMap("cmd", GridRestCommand.FETCH_SQL_QUERY.key(),
-            "pageSize", "1", "qryId", String.valueOf(qryId)));
-
-        json = JSONObject.fromObject(ret);
+            "pageSize", "1", "qryId", qryId.asText()));
 
-        qryId0 = (Integer)((Map)json.get("response")).get("queryId");
+        res = jsonResponse(ret);
 
-        last = (Boolean)((Map)json.get("response")).get("last");
+        qryId0 = jsonResponse(ret).get("queryId");
 
         assertEquals(qryId0, qryId);
-        assertTrue(last);
+        assertTrue(res.get("last").asBoolean());
 
         assertFalse(queryCursorFound());
     }
@@ -1343,16 +1653,11 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         params.put("cmd", GridRestCommand.EXECUTE_SQL_FIELDS_QUERY.key());
         params.put("pageSize", "10");
         params.put("cacheName", "person");
-        params.put("qry", URLEncoder.encode(qry));
+        params.put("qry", URLEncoder.encode(qry, CHARSET));
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
-
-        List items = (List)((Map)json.get("response")).get("items");
+        JsonNode items = jsonResponse(ret).get("items");
 
         assertEquals(4, items.size());
 
@@ -1369,29 +1674,25 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         params.put("cmd", GridRestCommand.EXECUTE_SQL_FIELDS_QUERY.key());
         params.put("pageSize", "10");
         params.put("cacheName", "person");
-        params.put("qry", URLEncoder.encode(qry));
+        params.put("qry", URLEncoder.encode(qry, CHARSET));
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
+        JsonNode res = jsonResponse(ret);
 
-        List items = (List)((Map)json.get("response")).get("items");
+        JsonNode items = res.get("items");
 
-        List meta = (List)((Map)json.get("response")).get("fieldsMetadata");
+        JsonNode meta = res.get("fieldsMetadata");
 
         assertEquals(4, items.size());
-
         assertEquals(2, meta.size());
 
-        JSONObject o = (JSONObject)meta.get(0);
+        JsonNode o = meta.get(0);
 
-        assertEquals("FIRSTNAME", o.get("fieldName"));
-        assertEquals("java.lang.String", o.get("fieldTypeName"));
-        assertEquals("person", o.get("schemaName"));
-        assertEquals("PERSON", o.get("typeName"));
+        assertEquals("FIRSTNAME", o.get("fieldName").asText());
+        assertEquals("java.lang.String", o.get("fieldTypeName").asText());
+        assertEquals("person", o.get("schemaName").asText());
+        assertEquals("PERSON", o.get("typeName").asText());
 
         assertFalse(queryCursorFound());
     }
@@ -1407,32 +1708,23 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         params.put("type", "Person");
         params.put("pageSize", "1");
         params.put("cacheName", "person");
-        params.put("qry", URLEncoder.encode(qry));
+        params.put("qry", URLEncoder.encode(qry, CHARSET));
         params.put("arg1", "1000");
         params.put("arg2", "2000");
 
         String ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
+        JsonNode res = jsonResponse(ret);
 
-        List items = (List)((Map)json.get("response")).get("items");
-
-        assertEquals(1, items.size());
+        assertEquals(1, res.get("items").size());
 
         assertTrue(queryCursorFound());
 
-        Integer qryId = (Integer)((Map)json.get("response")).get("queryId");
-
-        assertNotNull(qryId);
+        assertFalse(res.get("queryId").isNull());
 
-        ret = content(F.asMap("cmd", GridRestCommand.CLOSE_SQL_QUERY.key(),
-            "cacheName", "person", "qryId", String.valueOf(qryId)));
+        String qryId = res.get("queryId").asText();
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
+        content(F.asMap("cmd", GridRestCommand.CLOSE_SQL_QUERY.key(), "cacheName", "person", "qryId", qryId));
 
         assertFalse(queryCursorFound());
     }
@@ -1448,7 +1740,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         params.put("type", "Person");
         params.put("pageSize", "1");
         params.put("cacheName", "person");
-        params.put("qry", URLEncoder.encode(qry));
+        params.put("qry", URLEncoder.encode(qry, CHARSET));
         params.put("arg1", "1000");
         params.put("arg2", "2000");
 
@@ -1457,12 +1749,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         for (int i = 0; i < 10; ++i)
             ret = content(params);
 
-        assertNotNull(ret);
-        assertTrue(!ret.isEmpty());
-
-        JSONObject json = JSONObject.fromObject(ret);
-
-        List items = (List)((Map)json.get("response")).get("items");
+        JsonNode items = jsonResponse(ret).get("items");
 
         assertEquals(1, items.size());
 
@@ -1473,6 +1760,10 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         assertFalse(queryCursorFound());
     }
 
+    /**
+     * @return Signature.
+     * @throws Exception If failed.
+     */
     protected abstract String signature() throws Exception;
 
     /**
@@ -1500,6 +1791,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
      */
     private void initCache() {
         CacheConfiguration<Integer, Person> personCacheCfg = new CacheConfiguration<>("person");
+
         personCacheCfg.setIndexedTypes(Integer.class, Person.class);
 
         IgniteCache<Integer, Person> personCache = grid(0).getOrCreateCache(personCacheCfg);
@@ -1615,4 +1907,251 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
             return n.id().equals(nid);
         }
     }
+
+    /**
+     * Helper for build {@link VisorGatewayTask} arguments.
+     */
+    public static class VisorGatewayArgument extends HashMap<String, String> {
+        /** Latest argument index. */
+        private int idx = 3;
+
+        /**
+         * Construct helper object.
+         *
+         * @param cls Class of executed task.
+         */
+        public VisorGatewayArgument(Class cls) {
+            super(F.asMap(
+                "cmd", GridRestCommand.EXE.key(),
+                "name", VisorGatewayTask.class.getName(),
+                "p1", "null",
+                "p2", cls.getName()
+            ));
+        }
+
+        /**
+         * Execute task on node.
+         *
+         * @param node Node.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument forNode(ClusterNode node) {
+            put("p1", node.id().toString());
+
+            return this;
+        }
+
+        /**
+         * Prepare list of node IDs.
+         *
+         * @param nodes Collection of nodes.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument forNodes(Collection<ClusterNode> nodes) {
+            put("p1", concat(F.transform(nodes, new C1<ClusterNode, UUID>() {
+                /** {@inheritDoc} */
+                @Override public UUID apply(ClusterNode node) {
+                    return node.id();
+                }
+            }).toArray(), ";"));
+
+            return this;
+        }
+
+        /**
+         * Add string argument.
+         *
+         * @param val Value.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument argument(String val) {
+            put("p" + idx++, String.class.getName());
+            put("p" + idx++, val);
+
+            return this;
+        }
+
+        /**
+         * Add custom class argument.
+         *
+         * @param cls Class.
+         * @param vals Values.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument argument(Class cls, Object ... vals) {
+            put("p" + idx++, cls.getName());
+
+            for (Object val : vals)
+                put("p" + idx++, val != null ? val.toString() : null);
+
+            return this;
+        }
+
+        /**
+         * Add collection argument.
+         *
+         * @param cls Class.
+         * @param vals Values.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument collection(Class cls, Object ... vals) {
+            put("p" + idx++, Collection.class.getName());
+            put("p" + idx++, cls.getName());
+            put("p" + idx++, concat(vals, ";"));
+
+            return this;
+        }
+
+        /**
+         * Add tuple argument.
+         *
+         * @param keyCls Key class.
+         * @param valCls Values class.
+         * @param key Key.
+         * @param val Value.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument pair(Class keyCls, Class valCls, Object key, Object val) {
+            put("p" + idx++, IgniteBiTuple.class.getName());
+            put("p" + idx++, keyCls.getName());
+            put("p" + idx++, valCls.getName());
+            put("p" + idx++, key != null ? key.toString() : "null");
+            put("p" + idx++, val != null ? val.toString() : "null");
+
+            return this;
+        }
+
+        /**
+         * Add tuple argument.
+         *
+         * @param firstCls Class of first argument.
+         * @param secondCls Class of second argument.
+         * @param thirdCls Class of third argument.
+         * @param first First argument.
+         * @param second Second argument.
+         * @param third Third argument.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument tuple3(Class firstCls, Class secondCls, Class thirdCls,
+            Object first, Object second, Object third) {
+            put("p" + idx++, GridTuple3.class.getName());
+            put("p" + idx++, firstCls.getName());
+            put("p" + idx++, secondCls.getName());
+            put("p" + idx++, thirdCls.getName());
+            put("p" + idx++, first != null ? first.toString() : "null");
+            put("p" + idx++, second != null ? second.toString() : "null");
+            put("p" + idx++, third != null ? third.toString() : "null");
+
+            return this;
+        }
+
+        /**
+         * Add set argument.
+         *
+         * @param cls Class.
+         * @param vals Values.
+         * @return This helper for chaining method calls.
+         */
+        public VisorGatewayArgument set(Class cls, Object ... vals) {
+            put("p" + idx++, Set.class.getName());
+            put("p" + idx++, cls.getName());
+            put("p" + idx++, concat(vals, ";"));
+
+            return this;
+        }
+
+        /**
+         * Add map argument.
+         *
+         * @param keyCls Key class.
+         * @param valCls Value class.
+         * @param map Map.
+         */
+        public VisorGatewayArgument map(Class keyCls, Class valCls, Map<?, ?> map) throws UnsupportedEncodingException {
+            put("p" + idx++, Map.class.getName());
+            put("p" + idx++, keyCls.getName());
+            put("p" + idx++, valCls.getName());
+
+            SB sb = new SB();
+
+            boolean first = true;
+
+            for (Map.Entry<?, ?> entry : map.entrySet()) {
+                if (!first)
+                    sb.a(";");
+
+                sb.a(entry.getKey());
+
+                if (entry.getValue() != null)
+                    sb.a("=").a(entry.getValue());
+
+                first = false;
+            }
+
+            put("p" + idx++, URLEncoder.encode(sb.toString(), CHARSET));
+
+            return this;
+        }
+
+        /**
+         * Concat object with delimiter.
+         *
+         * @param vals Values.
+         * @param delim Delimiter.
+         */
+        private static String concat(Object[] vals, String delim) {
+            SB sb = new SB();
+
+            boolean first = true;
+
+            for (Object val : vals) {
+                if (!first)
+                    sb.a(delim);
+
+                sb.a(val);
+
+                first = false;
+            }
+
+            return sb.toString();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        CacheConfiguration cacheIgfs_data = new CacheConfiguration();
+
+        cacheIgfs_data.setName("igfs-data");
+        cacheIgfs_data.setCacheMode(CacheMode.PARTITIONED);
+        cacheIgfs_data.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
+        cacheIgfs_data.setBackups(0);
+
+        cacheIgfs_data.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+
+        cacheIgfs_data.setAffinityMapper(new IgfsGroupDataBlocksKeyMapper(512));
+
+        CacheConfiguration cacheIgfs_meta = new CacheConfiguration();
+
+        cacheIgfs_meta.setName("igfs-meta");
+        cacheIgfs_meta.setCacheMode(CacheMode.REPLICATED);
+        cacheIgfs_meta.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
+
+        cacheIgfs_meta.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+
+        cfg.setCacheConfiguration(cfg.getCacheConfiguration()[0], cacheIgfs_data, cacheIgfs_meta);
+
+        FileSystemConfiguration igfs = new FileSystemConfiguration();
+
+        igfs.setName("igfs");
+        igfs.setDataCacheName("igfs-data");
+        igfs.setMetaCacheName("igfs-meta");
+
+        igfs.setIpcEndpointConfiguration(new IgfsIpcEndpointConfiguration());
+
+        cfg.setFileSystemConfiguration(igfs);
+
+        return cfg;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1c3e408b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/SimplePerson.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/SimplePerson.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/SimplePerson.java
new file mode 100644
index 0000000..0185213
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/SimplePerson.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest;
+
+import java.sql.Date;
+
+/**
+ * Test class with public fields and without getters and setters.
+ */
+public class SimplePerson {
+    /** Person ID. */
+    public int id;
+
+    /** Person name. */
+    public String name;
+
+    /** Person birthday. */
+    public Date birthday;
+
+    /** Person salary. */
+    public double salary;
+
+    /** Must be excluded on serialization. */
+    public transient int age;
+
+    /** Must be excluded on serialization. */
+    protected String post;
+
+    /** Must be excluded on serialization. */
+    private int bonus;
+
+    /**
+     * Default constructor.
+     */
+    public SimplePerson() {
+        // No-op.
+    }
+
+    /**
+     * Full constructor.
+     *
+     * @param id Person ID.
+     * @param name Person name.
+     * @param birthday Person birthday.
+     * @param salary Person salary.
+     * @param age Person age.
+     * @param post Person post.
+     * @param bonus Person bonus.
+     */
+    public SimplePerson(int id, String name, Date birthday, double salary, int age, String post, int bonus) {
+        this.id = id;
+        this.name = name;
+        this.birthday = birthday;
+        this.salary = salary;
+        this.age = age;
+        this.post = post;
+        this.bonus = bonus;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1c3e408b/modules/core/pom.xml
----------------------------------------------------------------------
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index 3c16366..b80a924 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -76,6 +76,13 @@
         </dependency>
 
         <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.2</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
             <groupId>commons-dbcp</groupId>
             <artifactId>commons-dbcp</artifactId>
             <version>1.4</version>
@@ -153,14 +160,6 @@
         </dependency>
 
         <dependency>
-            <groupId>net.sf.json-lib</groupId>
-            <artifactId>json-lib</artifactId>
-            <version>${jsonlib.version}</version>
-            <classifier>jdk15</classifier>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
             <groupId>org.gridgain</groupId>
             <artifactId>ignite-shmem</artifactId>
             <version>1.0.0</version>

http://git-wip-us.apache.org/repos/asf/ignite/blob/1c3e408b/modules/core/src/main/java/org/apache/ignite/internal/LessNamingBean.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/LessNamingBean.java b/modules/core/src/main/java/org/apache/ignite/internal/LessNamingBean.java
new file mode 100644
index 0000000..3b885f9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/LessNamingBean.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal;
+
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+
+/**
+ * Marker interface for beans with less naming conventions i.e., without "get" and "set" prefixes.
+ */
+@GridToStringExclude
+public interface LessNamingBean {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1c3e408b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlIndexMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlIndexMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlIndexMetadata.java
index 539a156..94602f7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlIndexMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlIndexMetadata.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.query;
 
 import java.io.Externalizable;
 import java.util.Collection;
+import org.apache.ignite.internal.LessNamingBean;
 
 /**
  * Ignite index descriptor.
@@ -27,7 +28,7 @@ import java.util.Collection;
  * {@link GridCacheSqlMetadata#indexes(String)} method.
  * @see GridCacheSqlMetadata
  */
-public interface GridCacheSqlIndexMetadata extends Externalizable {
+public interface GridCacheSqlIndexMetadata extends Externalizable, LessNamingBean {
     /**
      * Gets name of the index.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/1c3e408b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
index 724962e..c82d2cb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlMetadata.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache.query;
 import java.io.Externalizable;
 import java.util.Collection;
 import java.util.Map;
+import org.apache.ignite.internal.LessNamingBean;
 import org.apache.ignite.spi.indexing.IndexingSpi;
 import org.jetbrains.annotations.Nullable;
 
@@ -30,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
  * can be used to gather information about what can
  * be queried using Ignite cache queries feature.
  */
-public interface GridCacheSqlMetadata extends Externalizable {
+public interface GridCacheSqlMetadata extends Externalizable, LessNamingBean {
     /**
      * Cache name.
      *