changeset 222:52e4c97adcd7

Add isAlive property to jvm-info Reviewed-by: jkang Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-July/024321.html
author Alessandro Merola <amerola@redhat.com>
date Mon, 31 Jul 2017 19:14:29 +0200
parents 1a1e29c83c7b
children e233372c70ed
files common/core/src/main/java/com/redhat/thermostat/gateway/common/util/ArgumentRunnable.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/http/JvmsHttpHandler.java services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/mongo/JvmInfoMongoStorageHandler.java services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/mongo/StorageFields.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java
diffstat 7 files changed, 295 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/gateway/common/util/ArgumentRunnable.java	Mon Jul 31 19:14:29 2017 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.common.util;
+
+public interface ArgumentRunnable<T> {
+    void run(T arg);
+
+}
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java	Thu Jul 27 18:33:26 2017 +0200
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java	Mon Jul 31 19:14:29 2017 +0200
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.gateway.common.mongodb.response;
 
 import java.util.ArrayList;
+import java.util.List;
 
 import com.redhat.thermostat.gateway.common.mongodb.executor.MongoDataResultContainer;
 import org.bson.Document;
@@ -46,6 +47,7 @@
 import com.mongodb.Block;
 import com.mongodb.client.FindIterable;
 import com.redhat.thermostat.gateway.common.mongodb.keycloak.KeycloakFields;
+import com.redhat.thermostat.gateway.common.util.ArgumentRunnable;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -80,6 +82,22 @@
             return this;
         }
 
+        public Builder addQueryDocuments(FindIterable<Document> documents, final ArgumentRunnable<Document> runnable) {
+            queryDocuments = new ArrayList<>();
+            documents.forEach(new Block<Document>() {
+                @Override
+                public void apply(Document document) {
+                    if (document.containsKey(KeycloakFields.REALMS_KEY)) {
+                        document.remove(KeycloakFields.REALMS_KEY);
+                    }
+                    runnable.run(document);
+                    queryDocuments.add(document);
+                }
+            });
+            return this;
+        }
+
+
         public Builder addMetaData(MongoMetaDataResponseBuilder metaData) {
             this.metaData = metaData;
             return this;
--- a/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java	Thu Jul 27 18:33:26 2017 +0200
+++ b/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java	Mon Jul 31 19:14:29 2017 +0200
@@ -55,6 +55,7 @@
 import com.mongodb.client.FindIterable;
 import com.mongodb.client.MongoCursor;
 import com.mongodb.client.MongoIterable;
+import com.redhat.thermostat.gateway.common.util.ArgumentRunnable;
 
 public class MongoResponseBuilderTest {
 
@@ -104,6 +105,35 @@
         assertEquals(expected, output);
     }
 
+    @Test
+    public void testBuildResponseWithRunnable() {
+        Document d1 = Document.parse("{\"hello\" : \"blob\"}");
+        Document d2 = Document.parse("{\"a\" : {\"blob\" : [\"hi\"]}}");
+        final List<Document> list = new ArrayList<>();
+        list.add(d1);
+        list.add(d2);
+
+        final boolean[] b = {false, false};
+        FindIterable<Document> iterable = new TestFindIterable<>(list);
+        ArgumentRunnable<Document> argumentRunnable = new ArgumentRunnable<Document>() {
+            @Override
+            public void run(Document arg) {
+                if (arg.containsKey("hello")) {
+                    b[0] = true;
+                }
+                if (arg.containsKey("a")) {
+                    b[1] = true;
+                }
+            }
+        };
+
+        String output = mongoResponseBuilder.addQueryDocuments(iterable, argumentRunnable).build();
+        String expected = "{\"response\":[{\"hello\":\"blob\"},{\"a\":{\"blob\":[\"hi\"]}}]}";
+        assertEquals(expected, output);
+        assertEquals(true, b[0]);
+        assertEquals(true, b[1]);
+    }
+
     private class TestFindIterable<T> implements FindIterable<T> {
 
         private final List<T> list;
--- a/services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/http/JvmsHttpHandler.java	Thu Jul 27 18:33:26 2017 +0200
+++ b/services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/http/JvmsHttpHandler.java	Mon Jul 31 19:14:29 2017 +0200
@@ -63,8 +63,6 @@
     private final JvmInfoMongoStorageHandler mongoStorageHandler = new JvmInfoMongoStorageHandler();
     private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
-    private static final int LIMIT_1 = 1;
-    private static final int OFFSET_ZERO = 0;
 
     @GET
     @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
@@ -81,7 +79,13 @@
                                 @Context ServletContext context,
                                 @Context HttpServletRequest httpServletRequest
     ) {
-        return serviceHelper.handleGetWithSystemID(httpServletRequest, context, systemId, limit, offset, sort, queries, includes, excludes, metadata);
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            String message = mongoStorageHandler.getJvmInfos(storage.getDatabase().getCollection(collectionName), systemId, limit, offset, sort, queries, includes, excludes);
+            return Response.status(Response.Status.OK).entity(message).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
     }
 
     @POST
@@ -120,7 +124,13 @@
                                @Context ServletContext context,
                                @Context HttpServletRequest httpServletRequest
     ) {
-        return serviceHelper.handleGetWithJvmID(httpServletRequest, context, systemId, jvmId, LIMIT_1, OFFSET_ZERO, null, null, includes, excludes, metadata);
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            String message = mongoStorageHandler.getJvmInfo(storage.getDatabase().getCollection(collectionName), systemId, jvmId, includes, excludes);
+            return Response.status(Response.Status.OK).entity(message).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
     }
 
     @PUT
@@ -162,7 +172,6 @@
             mongoStorageHandler.updateTimestamps(storage.getDatabase().getCollection(collectionName), body, systemId, timeStamp);
             return Response.status(Response.Status.OK).build();
         } catch (Exception e) {
-            e.printStackTrace();
             return Response.status(Response.Status.BAD_REQUEST).build();
         }
     }
@@ -183,7 +192,6 @@
             String message = mongoStorageHandler.getJvmsTree(storage.getDatabase().getCollection(collectionName), aliveOnly, excludes, includes, limit, offset);
             return Response.status(Response.Status.OK).entity(message).build();
         } catch (Exception e) {
-            e.printStackTrace();
             return Response.status(Response.Status.BAD_REQUEST).build();
         }
     }
--- a/services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/mongo/JvmInfoMongoStorageHandler.java	Thu Jul 27 18:33:26 2017 +0200
+++ b/services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/mongo/JvmInfoMongoStorageHandler.java	Mon Jul 31 19:14:29 2017 +0200
@@ -56,13 +56,19 @@
 import org.bson.conversions.Bson;
 
 import com.mongodb.Block;
+import com.mongodb.CursorType;
 import com.mongodb.client.FindIterable;
 import com.mongodb.client.MongoCollection;
 import com.mongodb.util.JSON;
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters;
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoSortFilters;
+import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
+import com.redhat.thermostat.gateway.common.util.ArgumentRunnable;
 
 public class JvmInfoMongoStorageHandler  {
 
     private static final String SET_KEY = "$set";
+    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
 
     public void updateTimestamps(MongoCollection<Document> collection, String body, String systemId, Long timeStamp) {
         final Bson filter;
@@ -82,6 +88,75 @@
         collection.updateMany(filter, update);
     }
 
+    private void setIsAlive(Document document) {
+        if(document.getLong(StorageFields.STOP_TIME) != null && document.getLong(StorageFields.STOP_TIME) > 0) {
+            document.append(StorageFields.IS_ALIVE, false);
+        } else {
+            document.append(StorageFields.IS_ALIVE, true);
+        }
+    }
+
+    public String getJvmInfo(MongoCollection<Document> collection, String systemId, String jvmId, String includes, String excludes) {
+        Bson baseQuery = and(eq(StorageFields.SYSTEM_ID, systemId), eq(StorageFields.JVM_ID, jvmId));
+
+        FindIterable<Document> documents = collection.find(baseQuery).limit(1).skip(0);
+
+        if (excludes != null) {
+            List<String> excludesList = Arrays.asList(excludes.split(","));
+            documents = documents.projection(fields(exclude(excludesList), excludeId()));
+        } else if (includes != null) {
+            List<String> includesList = Arrays.asList(includes.split(","));
+            documents = documents.projection(fields(include(includesList), excludeId()));
+        } else {
+            documents = documents.projection(excludeId());
+        }
+
+        ArgumentRunnable<Document> runnable = new ArgumentRunnable<Document>() {
+            @Override
+            public void run(Document arg) {
+                setIsAlive(arg);
+            }
+        };
+
+        return mongoResponseBuilder.addQueryDocuments(documents, runnable).build();
+    }
+
+    public String getJvmInfos(MongoCollection<Document> collection, String systemId, Integer limit, Integer offset, String sort, String queries, String includes, String excludes) {
+        final Bson baseQuery;
+        baseQuery = eq(StorageFields.SYSTEM_ID, systemId);
+        FindIterable<Document> documents;
+
+        if (queries != null) {
+            List<String> queriesList = Arrays.asList(queries.split(","));
+            final Bson query = MongoRequestFilters.buildQueriesFilter(queriesList);
+            documents = collection.find(and(baseQuery, query));
+        } else {
+            documents = collection.find(baseQuery);
+        }
+
+        ArgumentRunnable<Document> runnable = new ArgumentRunnable<Document>() {
+            @Override
+            public void run(Document arg) {
+                setIsAlive(arg);
+            }
+        };
+
+        if (excludes != null) {
+            List<String> excludesList = Arrays.asList(excludes.split(","));
+            documents = documents.projection(fields(exclude(excludesList), excludeId()));
+        } else if (includes != null) {
+            List<String> includesList = Arrays.asList(includes.split(","));
+            documents = documents.projection(fields(include(includesList), excludeId()));
+        } else {
+            documents = documents.projection(excludeId());
+        }
+
+        final Bson sortObject = MongoSortFilters.createSortObject(sort);
+        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
+
+        return mongoResponseBuilder.addQueryDocuments(documents, runnable).build();
+    }
+
     public String getJvmsTree(MongoCollection<Document> collection, boolean aliveOnly, String excludes, String includes, int limit, int offset) {
         FindIterable<Document> documents;
 
@@ -122,6 +197,8 @@
         documents.forEach(new Block<Document>() {
             @Override
             public void apply(Document document) {
+                setIsAlive(document);
+
                 String systemId = document.getString(StorageFields.SYSTEM_ID);
                 if (!finalIncludeSystemId) {
                     document.remove(StorageFields.SYSTEM_ID);
--- a/services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/mongo/StorageFields.java	Thu Jul 27 18:33:26 2017 +0200
+++ b/services/jvms/src/main/java/com/redhat/thermostat/gateway/service/jvms/mongo/StorageFields.java	Mon Jul 31 19:14:29 2017 +0200
@@ -42,6 +42,7 @@
 
     String LAST_UPDATED = "lastUpdated";
     String STOP_TIME = "stopTime";
+    String IS_ALIVE = "isAlive";
 
     String RESPONSE = "response";
     String JVMS = "jvms";
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java	Thu Jul 27 18:33:26 2017 +0200
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java	Mon Jul 31 19:14:29 2017 +0200
@@ -98,6 +98,100 @@
     }
 
     @Test
+    public void testIsAliveFalseGetJvmInfo() throws InterruptedException, ExecutionException, TimeoutException {
+        String postUrl = jvmsUrl + "/systems/1";
+        String getUrl = jvmsUrl + "/systems/1/jvms/jid2";
+
+        ContentResponse postResponse = client.newRequest(postUrl).method(HttpMethod.POST)
+                .content(new StringContentProvider(postData), "application/json").send();
+        assertEquals(200, postResponse.getStatus());
+
+        ContentResponse getResponse = client.newRequest(getUrl).method(HttpMethod.GET).send();
+        assertEquals(200, getResponse.getStatus());
+
+        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
+                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\",\"javaHome\":" +
+                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
+                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
+                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
+                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
+                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\"," +
+                "\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
+                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
+                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
+                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
+                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
+                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
+                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
+        assertEquals(expected, getResponse.getContentAsString());
+    }
+
+    @Test
+    public void testIsAliveFalseGetJvmTree() throws InterruptedException, ExecutionException, TimeoutException {
+        String postUrl = jvmsUrl + "/systems/1";
+        String treeUrl = jvmsUrl + "/tree";
+
+        ContentResponse postResponse = client.newRequest(postUrl).method(HttpMethod.POST)
+                .content(new StringContentProvider(postData), "application/json").send();
+        assertEquals(200, postResponse.getStatus());
+
+        String query = "?aliveOnly=false&offset=1";
+        ContentResponse response = client.newRequest(treeUrl + query).method(HttpMethod.GET).send();
+        assertEquals(200, response.getStatus());
+        String expected = "{ \"response\" : [{\"systemId\":\"1\", " +
+                "\"jvms\":[{ \"agentId\" : \"aid\", \"jvmId\" : \"jid2\", \"jvmPid\" : 2, " +
+                "\"startTime\" : { \"$numberLong\" : \"1495727607481\" }, " +
+                "\"stopTime\" : { \"$numberLong\" : \"1495727607482\" }, " +
+                "\"javaVersion\" : \"1.8.0_131\", " +
+                "\"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", " +
+                "\"mainClass\" : \"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", " +
+                "\"vmArguments\" : \"-Djline.log.jul=true\", \"jvmInfo\" : \"mixed mode\", " +
+                "\"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" : \"25.131-b12\", " +
+                "\"environment\" : [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, " +
+                "{ \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, " +
+                "{ \"key\" : \"GDMSESSION\", \"value\" : \"i3\" }, { \"key\" : \"fish_greeting\", \"value\" : \"\" }, " +
+                "{ \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, { \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, " +
+                "{ \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, " +
+                "{ \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }, " +
+                "{ \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, " +
+                "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
+                "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
+                "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
+                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : false }]}]}";
+        assertEquals(expected, response.getContentAsString());
+    }
+
+    @Test
+    public void testIsAliveTrueGetJvmInfos() throws InterruptedException, ExecutionException, TimeoutException {
+        String url = jvmsUrl + "/systems/1";
+
+        ContentResponse postResponse = client.newRequest(url).method(HttpMethod.POST)
+                .content(new StringContentProvider(postData), "application/json").send();
+        assertEquals(200, postResponse.getStatus());
+
+        String query = "/jvms/jid1";
+        ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
+
+        assertEquals(200, getResponse.getStatus());
+        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1," +
+                "\"startTime\":1495727607481,\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\"," +
+                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
+                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":" +
+                "\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":" +
+                "\"25.131-b12\",\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
+                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
+                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\"," +
+                "\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"},{\"key\":\"DBUS_SESSION_BUS_ADDRESS\"," +
+                "\"value\":\"unix:path\\u003d/run/user/1000/bus\"},{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"}," +
+                "{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"}," +
+                "{\"key\":\"DISPLAY\",\"value\":\":0\"},{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\"," +
+                "\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
+        assertEquals(expected, getResponse.getContentAsString());
+    }
+
+    @Test
     public void testPost() throws InterruptedException, ExecutionException, TimeoutException {
         String url = jvmsUrl + "/systems/1";
 
@@ -122,7 +216,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -154,7 +248,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -186,7 +280,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"},{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true},{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
                 "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\"," +
                 "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
                 "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
@@ -201,7 +295,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
 
         assertEquals(expected, getResponse.getContentAsString());
     }
@@ -232,7 +326,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}" +
                 ",{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -260,7 +354,7 @@
                 "{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"}," +
                 "{\"key\":\"DISPLAY\",\"value\":\":0\"},{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\"," +
                 "\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
 
         assertEquals(expected, getResponse.getContentAsString());
     }
@@ -289,7 +383,7 @@
                 "{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"}," +
                 "{\"key\":\"DISPLAY\",\"value\":\":0\"},{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\"," +
                 "\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
 
         assertEquals(expected, getResponse.getContentAsString());
     }
@@ -305,7 +399,7 @@
         String query = "?include=agentId,jvmId";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\"}]}";
+        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"isAlive\":true}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -334,7 +428,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -385,7 +479,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -426,7 +520,7 @@
                 "\"unix:path\\u003d/run/user/1000/bus\"},{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\"," +
                 "\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":" +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}],\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}],\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -458,7 +552,7 @@
                 "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
                 "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
                 "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\"}]}";
+                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -478,7 +572,7 @@
         ContentResponse response = client.newRequest(url).method(HttpMethod.GET)
                 .param("include", "lastUpdated").send();
         assertEquals(200, response.getStatus());
-        String expected = "{\"response\":[{\"lastUpdated\":2000}]}";
+        String expected = "{\"response\":[{\"lastUpdated\":2000,\"isAlive\":true}]}";
         assertEquals(expected, response.getContentAsString());
 
     }
@@ -511,7 +605,7 @@
                 "\"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, { \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, " +
                 "{ \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, { \"key\" : \"_\", \"value\" : " +
                 "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], \"uid\" : " +
-                "1000, \"username\" : \"user\", \"systemId\" : \"1\" }]}]}";
+                "1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : true }]}]}";
         assertEquals(expected, response.getContentAsString());
     }
 
@@ -527,7 +621,7 @@
         String query = "?include=jvmId";
         ContentResponse response = client.newRequest(treeUrl + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", \"jvms\":[{ \"jvmId\" : \"jid1\" }]}]}";
+        String expected = "{ \"response\" : [{\"systemId\":\"1\", \"jvms\":[{ \"jvmId\" : \"jid1\", \"isAlive\" : true }]}]}";
         assertEquals(expected, response.getContentAsString());
     }
 
@@ -559,7 +653,7 @@
                 "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
                 "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
                 "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\" }]}]}";
+                "\"uid\" : 1000, \"username\" : \"user\", \"isAlive\" : true }]}]}";
         assertEquals(expected, response.getContentAsString());
     }
 
@@ -590,7 +684,7 @@
                 "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
                 "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
                 "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\" }," +
+                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : true }," +
                 "{ \"agentId\" : \"aid\", \"jvmId\" : \"jid2\", \"jvmPid\" : 2, \"startTime\" : " +
                 "{ \"$numberLong\" : \"1495727607481\" }, \"stopTime\" : { \"$numberLong\" : \"1495727607482\" }, " +
                 "\"javaVersion\" : \"1.8.0_131\", \"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", " +
@@ -605,7 +699,7 @@
                 "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
                 "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
                 "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\" }]}]}";
+                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : false }]}]}";
         assertEquals(expected, response.getContentAsString());
     }
 
@@ -640,7 +734,7 @@
                 "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
                 "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
                 "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\" }]}]}";
+                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : false }]}]}";
         assertEquals(expected, response.getContentAsString());
     }
 }