changeset 2713:0765cd82bfec

Refactor HttpRequestService to not expose jetty client. Reviewed-by: jmatsuok Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-June/023885.html
author Severin Gehwolf <sgehwolf@redhat.com>
date Fri, 23 Jun 2017 15:16:13 +0200
parents 30ac0c82bc98
children cd2f41102214
files agent/core/src/main/java/com/redhat/thermostat/agent/http/HttpRequestService.java agent/core/src/test/java/com/redhat/thermostat/agent/http/HttpRequestServiceTest.java common/plugin/src/main/java/com/redhat/thermostat/common/plugin/PluginDAOBase.java plugins/host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatDAOTest.java plugins/host-memory/agent/src/test/java/com/redhat/thermostat/host/memory/agent/internal/MemoryStatDAOTest.java plugins/host-overview/agent/src/test/java/com/redhat/thermostat/host/overview/internal/models/HostInfoDAOImplTest.java plugins/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/models/VmGcStatDAOImpl.java plugins/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/models/VmGcStatDAOImplTest.java plugins/vm-memory/agent/src/main/java/com/redhat/thermostat/vm/memory/agent/internal/models/VmMemoryStatDAOImpl.java plugins/vm-memory/agent/src/test/java/com/redhat/thermostat/vm/memory/agent/internal/models/VmMemoryStatDAOImplTest.java plugins/vm-memory/agent/src/test/java/com/redhat/thermostat/vm/memory/agent/model/VmMemoryStatTest.java
diffstat 11 files changed, 189 insertions(+), 247 deletions(-) [+]
line wrap: on
line diff
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/http/HttpRequestService.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/http/HttpRequestService.java	Fri Jun 23 15:16:13 2017 +0200
@@ -38,7 +38,6 @@
 
 
 import java.io.IOException;
-import java.net.ConnectException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -65,6 +64,24 @@
 @Component
 @Service(value = HttpRequestService.class)
 public class HttpRequestService {
+    
+    /**
+     * GET request type.
+     */
+    public static final String GET = HttpMethod.GET.asString();
+    /**
+     * PUT request type.
+     */
+    public static final String PUT = HttpMethod.PUT.asString();
+    /**
+     * POST request type.
+     */
+    public static final String POST = HttpMethod.POST.asString();
+    /**
+     * DELETE request type.
+     */
+    public static final String DELETE = HttpMethod.DELETE.asString();
+    
     private static final Logger logger = LoggingUtils.getLogger(HttpRequestService.class);
 
     private static final String KEYCLOAK_TOKEN_SERVICE = "/auth/realms/__REALM__/protocol/openid-connect/token";
@@ -101,24 +118,32 @@
      * @param jsonPayload The payload to send, or null if no payload
      * @param url The complete url to send to
      * @param requestType The HTTP request type: GET, PUT, POST or DELETE
-     * @return
+     * @return The returned body for GET requests. {@code null} otherwise.
      */
-    public ContentResponse sendHttpRequest(String jsonPayload, String url, HttpMethod requestType) throws IOException {
+    public String sendHttpRequest(String jsonPayload, String url, String requestType) throws RequestFailedException {
+        HttpMethod requestMethod = HttpMethod.valueOf(requestType);
         Request request = client.newRequest(url);
         if (jsonPayload != null) {
             request.content(new StringContentProvider(jsonPayload), "application/json");
         }
-
-        request.method(requestType);
-
-        if (agentStartupConfiguration.isKeycloakEnabled()) {
-            request.header("Authorization", "Bearer " + getAccessToken());
-        }
+        request.method(requestMethod);
 
         try {
-            return request.send();
-        } catch (InterruptedException | TimeoutException | ExecutionException e) {
-            return null;
+            if (agentStartupConfiguration.isKeycloakEnabled()) {
+                request.header("Authorization", "Bearer " + getAccessToken());
+            }
+            ContentResponse response =  request.send();
+            int status = response.getStatus();
+            if (status != HttpStatus.OK_200) {
+                throw new RequestFailedException(status, "Request to gateway failed. Reason: " + response.getReason());
+            }
+            if (requestMethod == HttpMethod.GET) {
+                return response.getContentAsString();
+            } else {
+                return null;
+            }
+        } catch (InterruptedException | TimeoutException | IOException | ExecutionException e) {
+            throw new RequestFailedException(e);
         }
     }
 
@@ -191,4 +216,34 @@
         return "grant_type=refresh_token&client_id=" + agentStartupConfiguration.getKeycloakClient() +
                 "&refresh_token=" + keycloakAccessToken.getRefreshToken();
     }
+    
+    @SuppressWarnings("serial")
+    public static class RequestFailedException extends Exception {
+        
+        public static final int UNKNOWN_RESPONSE_CODE = -1;
+        private final int responseCode;
+        private final String reasonStr;
+        
+        private RequestFailedException(Throwable e) {
+            this(UNKNOWN_RESPONSE_CODE, e.getMessage(), e);
+        }
+        
+        private RequestFailedException(int responseCode, String reason) {
+            this(responseCode, reason, null);
+        }
+        
+        private RequestFailedException(int responseCode, String reason, Throwable cause) {
+            super(reason);
+            this.reasonStr = reason;
+            this.responseCode = responseCode;
+        }
+        
+        public int getResponseCode() {
+            return responseCode;
+        }
+        
+        public String getReason() {
+            return reasonStr;
+        }
+    }
 }
\ No newline at end of file
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/http/HttpRequestServiceTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/http/HttpRequestServiceTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -37,10 +37,12 @@
 package com.redhat.thermostat.agent.http;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -62,12 +64,14 @@
 import org.mockito.ArgumentCaptor;
 
 import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
+import com.redhat.thermostat.agent.http.HttpRequestService.RequestFailedException;
 
 public class HttpRequestServiceTest {
-    private String payload = "{}";
-    private String url = "http://127.0.0.1:30000/test";
-    private HttpMethod method = HttpMethod.POST;
-    private String keycloakUrl = "http://127.0.0.1:31000/keycloak";
+    private static final String POST_METHOD = HttpRequestService.POST;
+    private static final String URL = "http://127.0.0.1:30000/test";
+    private static final String GET_URL = URL + "?q=foo&l=3";
+    private static final String payload = "{}";
+    private static final String keycloakUrl = "http://127.0.0.1:31000/keycloak";
 
     private HttpClient client;
     private Request httpRequest;
@@ -76,25 +80,26 @@
     public void setup() throws InterruptedException, ExecutionException, TimeoutException {
         client = mock(HttpClient.class);
         httpRequest = mock(Request.class);
-        when(client.newRequest(eq(url))).thenReturn(httpRequest);
-        when(httpRequest.send()).thenReturn(mock(ContentResponse.class));
+        when(client.newRequest(eq(URL))).thenReturn(httpRequest);
+        ContentResponse response = mock(ContentResponse.class);
+        when(response.getStatus()).thenReturn(HttpStatus.OK_200);
+        when(httpRequest.send()).thenReturn(response);
     }
 
     @Test
-    public void testRequestWithoutKeycloak() throws InterruptedException, ExecutionException, TimeoutException, IOException {
-        AgentStartupConfiguration configuration = mock(AgentStartupConfiguration.class);
-        when(configuration.isKeycloakEnabled()).thenReturn(false);
+    public void testRequestWithoutKeycloak() throws Exception {
+        AgentStartupConfiguration configuration = createNoKeycloakConfig();
 
         HttpRequestService service = new HttpRequestService(client, configuration);
 
-        service.sendHttpRequest(payload, url, method);
+        service.sendHttpRequest(payload, URL, POST_METHOD);
 
         verify(configuration).isKeycloakEnabled();
-        verifyHttpRequest(httpRequest);
+        verifyHttpPostRequest(httpRequest);
     }
 
     @Test
-    public void testRequestWithKeycloak() throws InterruptedException, ExecutionException, TimeoutException, IOException {
+    public void testRequestWithKeycloak() throws Exception {
         AgentStartupConfiguration configuration = mock(AgentStartupConfiguration.class);
         setupKeycloakConfig(configuration);
 
@@ -103,17 +108,17 @@
         Request keycloakRequest = mock(Request.class);
         setupKeycloakRequest(keycloakRequest);
 
-        service.sendHttpRequest(payload, url, method);
+        service.sendHttpRequest(payload, URL, POST_METHOD);
 
         verify(configuration).isKeycloakEnabled();
-        verifyHttpRequest(httpRequest);
+        verifyHttpPostRequest(httpRequest);
 
         verify(httpRequest).header(eq("Authorization"), eq("Bearer access"));
         verifyKeycloakAcquire(keycloakRequest);
     }
 
     @Test
-    public void testRequestWithKeycloakRefresh() throws InterruptedException, ExecutionException, TimeoutException, IOException {
+    public void testRequestWithKeycloakRefresh() throws Exception {
         AgentStartupConfiguration configuration = mock(AgentStartupConfiguration.class);
         setupKeycloakConfig(configuration);
 
@@ -122,21 +127,21 @@
         Request keycloakRequest = mock(Request.class);
         setupKeycloakRequest(keycloakRequest);
 
-        service.sendHttpRequest(payload, url, method);
+        service.sendHttpRequest(payload, URL, POST_METHOD);
 
         verify(configuration).isKeycloakEnabled();
-        verifyHttpRequest(httpRequest);
+        verifyHttpPostRequest(httpRequest);
 
         verify(httpRequest).header(eq("Authorization"), eq("Bearer access"));
 
         verifyKeycloakAcquire(keycloakRequest);
 
-        service.sendHttpRequest(payload, url, method);
+        service.sendHttpRequest(payload, URL, POST_METHOD);
 
 
         ArgumentCaptor<StringContentProvider> payloadCaptor = ArgumentCaptor.forClass(StringContentProvider.class);
         verify(keycloakRequest, times(2)).content(payloadCaptor.capture(), eq("application/x-www-form-urlencoded"));
-        verify(keycloakRequest, times(2)).method(eq(method));
+        verify(keycloakRequest, times(2)).method(eq(HttpMethod.valueOf(POST_METHOD)));
         verify(keycloakRequest, times(2)).send();
 
         String expected = "grant_type=refresh_token&client_id=client&refresh_token=refresh";
@@ -150,26 +155,59 @@
     }
 
     @Test
-    public void testRequestWithNullPayload() throws InterruptedException, ExecutionException, TimeoutException, IOException {
-        AgentStartupConfiguration configuration = mock(AgentStartupConfiguration.class);
-        when(configuration.isKeycloakEnabled()).thenReturn(false);
+    public void testRequestWithNullPayload() throws Exception {
+        AgentStartupConfiguration configuration = createNoKeycloakConfig();
 
         HttpRequestService service = new HttpRequestService(client, configuration);
 
-        service.sendHttpRequest(null, url, method);
+        String response = service.sendHttpRequest(null, URL, POST_METHOD);
+        assertNull(response);
 
-        verify(client).newRequest(url);
+        verify(client).newRequest(URL);
         verify(configuration).isKeycloakEnabled();
 
         verify(httpRequest, times(0)).content(any(StringContentProvider.class), anyString());
-        verify(httpRequest).method(eq(method));
+        verify(httpRequest).method(eq(HttpMethod.valueOf(POST_METHOD)));
         verify(httpRequest).send();
     }
 
-    private void verifyHttpRequest(Request httpRequest) throws InterruptedException, ExecutionException, TimeoutException {
-        verify(client).newRequest(url);
+    @Test
+    public void testGetRequestWithResponse() throws Exception {
+        String getContent = "foo bar";
+        Request request = mock(Request.class);
+        ContentResponse contentResponse = mock(ContentResponse.class);
+        when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200);
+        when(contentResponse.getContentAsString()).thenReturn(getContent);
+        when(request.send()).thenReturn(contentResponse);
+        HttpClient getClient = mock(HttpClient.class);
+        when(getClient.newRequest(eq(GET_URL))).thenReturn(request);
+        
+        AgentStartupConfiguration configuration = createNoKeycloakConfig();
+        HttpRequestService service = new HttpRequestService(getClient, configuration);
+        String content = service.sendHttpRequest(null, GET_URL, HttpRequestService.GET);
+        assertEquals(getContent, content);
+    }
+    
+    @Test(expected = RequestFailedException.class)
+    public void failureThrowsRequestFailedException() throws Exception {
+        Request request = mock(Request.class);
+        when(client.newRequest(any(String.class))).thenReturn(request);
+        AgentStartupConfiguration configuration = createNoKeycloakConfig();
+        doThrow(IOException.class).when(request).send();
+        HttpRequestService service = new HttpRequestService(client, configuration);
+        service.sendHttpRequest("foo", "bar", HttpRequestService.DELETE /*any valid method*/);
+    }
+
+    private AgentStartupConfiguration createNoKeycloakConfig() {
+        AgentStartupConfiguration configuration = mock(AgentStartupConfiguration.class);
+        when(configuration.isKeycloakEnabled()).thenReturn(false);
+        return configuration;
+    }
+
+    private void verifyHttpPostRequest(Request httpRequest) throws InterruptedException, ExecutionException, TimeoutException {
+        verify(client).newRequest(URL);
         verify(httpRequest).content(any(StringContentProvider.class), eq("application/json"));
-        verify(httpRequest).method(eq(method));
+        verify(httpRequest).method(eq(HttpMethod.valueOf(POST_METHOD)));
         verify(httpRequest).send();
     }
 
@@ -206,7 +244,7 @@
     private void verifyKeycloakAcquire(Request keycloakRequest) throws InterruptedException, ExecutionException, TimeoutException {
         ArgumentCaptor<StringContentProvider> payloadCaptor = ArgumentCaptor.forClass(StringContentProvider.class);
         verify(keycloakRequest).content(payloadCaptor.capture(), eq("application/x-www-form-urlencoded"));
-        verify(keycloakRequest).method(eq(method));
+        verify(keycloakRequest).method(eq(HttpMethod.valueOf(POST_METHOD)));
         verify(keycloakRequest).send();
 
         String expected = "grant_type=password&client_id=client&username=username&password=password";
--- a/common/plugin/src/main/java/com/redhat/thermostat/common/plugin/PluginDAOBase.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/common/plugin/src/main/java/com/redhat/thermostat/common/plugin/PluginDAOBase.java	Fri Jun 23 15:16:13 2017 +0200
@@ -41,9 +41,7 @@
 import java.util.logging.Logger;
 
 import com.redhat.thermostat.agent.http.HttpRequestService;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
+import com.redhat.thermostat.agent.http.HttpRequestService.RequestFailedException;
 
 abstract public class PluginDAOBase<Tobj,Tdao> {
 
@@ -55,21 +53,13 @@
 
     public void put(final Tobj obj) {
         try {
-            if (null != getHttpRequestService()) {
-                String json = toJsonString(obj);
+            HttpRequestService httpRequestService = getHttpRequestService();
+            String json = toJsonString(obj);
 
-                final String gatewayURL = getConfig().getGatewayURL();
-                final String url = getURL(gatewayURL);
-                final ContentResponse response = getHttpRequestService().sendHttpRequest(json, url, HttpMethod.POST);
-                final int status = response.getStatus();
-                if (status != HttpStatus.OK_200) {
-                    throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + response.getReason());
-                }
-
-            } else {
-                getLogger().log(Level.WARNING, "Failed to send " + obj.getClass().getName() + " information to web gateway. Http service unavailable.");
-            }
-        } catch (Exception e) {
+            final String gatewayURL = getConfig().getGatewayURL();
+            final String url = getURL(gatewayURL);
+            httpRequestService.sendHttpRequest(json, url, HttpRequestService.POST);
+        } catch (IOException | RequestFailedException e) {
             getLogger().log(Level.WARNING, "Failed to send " + obj.getClass().getName() + " to web gateway", e);
         }
     }
--- a/plugins/host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatDAOTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatDAOTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.host.cpu.agent.internal;
 
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyListOf;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -45,10 +44,12 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import com.redhat.thermostat.agent.http.HttpRequestService;
 import com.redhat.thermostat.common.Clock;
 import com.redhat.thermostat.common.SystemClock;
@@ -57,20 +58,11 @@
 import com.redhat.thermostat.common.plugin.SystemID;
 import com.redhat.thermostat.host.cpu.model.CpuStat;
 
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
-import org.junit.Before;
-import org.junit.Test;
-
 public class CpuStatDAOTest {
 
     private static final String URL = "http://localhost:26000/api/system-cpu/0.0.1";
     private static final String SOME_JSON = "{\"some\" : \"json\"}";
     private static final double times[] = { 33., 44, };
-    private static final String CONTENT_TYPE = "application/json";
     private static final String HOST_NAME = "somehostname";
 
     private static final String URL_PROP = "gatewayURL";
@@ -88,13 +80,6 @@
         Clock clock = new SystemClock();
         info = new CpuStat("foo-agent", clock.getRealTimeMillis(), times);
 
-        Request request = mock(Request.class);
-        HttpClient httpClient = mock(HttpClient.class);
-        when(httpClient.newRequest(anyString())).thenReturn(request);
-        ContentResponse response = mock(ContentResponse.class);
-        when(response.getStatus()).thenReturn(HttpStatus.OK_200);
-        when(request.send()).thenReturn(response);
-
         jsonHelper = mock(CpuStatDAOImpl.JsonHelper.class);
         when(jsonHelper.toJson(anyListOf(CpuStat.class))).thenReturn(SOME_JSON);
 
@@ -107,11 +92,6 @@
         when(configCreator.create(eq(cfiSource))).thenReturn(new PluginConfiguration(cfiSource, CpuStatDAOImpl.PLUGIN_ID));
 
         httpRequestService = mock(HttpRequestService.class);
-        ContentResponse contentResponse = mock(ContentResponse.class);
-
-        when(httpRequestService.sendHttpRequest(anyString(), anyString(), any(HttpMethod.class))).thenReturn(contentResponse);
-        when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200);
-
         idservice = mock(SystemID.class);
         when(idservice.getSystemID()).thenReturn(HOST_NAME);
     }
@@ -126,7 +106,7 @@
         dao.activate();
         dao.put(info);
 
-        verify(httpRequestService, times(1)).sendHttpRequest(SOME_JSON, URL + "/systems/" + HOST_NAME, HttpMethod.POST);
+        verify(httpRequestService, times(1)).sendHttpRequest(SOME_JSON, URL + "/systems/" + HOST_NAME, HttpRequestService.POST);
     }
 
 }
--- a/plugins/host-memory/agent/src/test/java/com/redhat/thermostat/host/memory/agent/internal/MemoryStatDAOTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/host-memory/agent/src/test/java/com/redhat/thermostat/host/memory/agent/internal/MemoryStatDAOTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.host.memory.agent.internal;
 
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyListOf;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -45,33 +44,24 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import com.redhat.thermostat.agent.http.HttpRequestService;
 import com.redhat.thermostat.common.Clock;
 import com.redhat.thermostat.common.SystemClock;
 import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+import com.redhat.thermostat.common.plugin.PluginConfiguration;
 import com.redhat.thermostat.common.plugin.SystemID;
-import com.redhat.thermostat.common.plugin.PluginConfiguration;
-
 import com.redhat.thermostat.host.memory.model.MemoryStat;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.mockito.Matchers;
 
 public class MemoryStatDAOTest {
 
     private static final String URL = "http://localhost:26000/api/system-memory/0.0.1";
     private static final String SOME_JSON = "{\"some\" : \"json\"}";
-    private static final String CONTENT_TYPE = "application/json";
     private static final String HOST_NAME = "somehostname";
 
     private static final String URL_PROP = "gatewayURL";
@@ -91,22 +81,12 @@
         this.jsonHelper = mock(MemoryStatDAOImpl.JsonHelper.class);
         when(jsonHelper.toJson(anyListOf(MemoryStat.class))).thenReturn(SOME_JSON);
 
-        Request request = mock(Request.class);
-        HttpClient httpClient = mock(HttpClient.class);
-        when(httpClient.newRequest(anyString())).thenReturn(request);
-        ContentResponse response = mock(ContentResponse.class);
-        when(response.getStatus()).thenReturn(HttpStatus.OK_200);
-        when(request.send()).thenReturn(response);
-
         cfiSource = mock(ConfigurationInfoSource.class);
         Map<String, String> map = new HashMap<>();
         map.put(URL_PROP, URL);
         when(cfiSource.getConfiguration(anyString(), anyString())).thenReturn(map);
 
         httpRequestService = mock(HttpRequestService.class);
-        ContentResponse contentResponse = mock(ContentResponse.class);
-        when(httpRequestService.sendHttpRequest(anyString(), anyString(), any(HttpMethod.class))).thenReturn(contentResponse);
-        when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200);
 
         configCreator = mock(MemoryStatDAOImpl.ConfigurationCreator.class);
         when(configCreator.create(eq(cfiSource))).thenReturn(new PluginConfiguration(cfiSource, MemoryStatDAOImpl.PLUGIN_ID));
@@ -117,7 +97,6 @@
 
     @Test
     public void testPut() throws Exception {
-
         MemoryStatDAOImpl dao = new MemoryStatDAOImpl(jsonHelper, configCreator);
         dao.bindSystemID(idservice);
         dao.bindConfigurationInfoSource(cfiSource);
@@ -125,7 +104,7 @@
         dao.activate();
         dao.put(info);
 
-        verify(httpRequestService, times(1)).sendHttpRequest(SOME_JSON, URL + "/systems/" + HOST_NAME, HttpMethod.POST);
+        verify(httpRequestService, times(1)).sendHttpRequest(SOME_JSON, URL + "/systems/" + HOST_NAME, HttpRequestService.POST);
     }
 }
 
--- a/plugins/host-overview/agent/src/test/java/com/redhat/thermostat/host/overview/internal/models/HostInfoDAOImplTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/host-overview/agent/src/test/java/com/redhat/thermostat/host/overview/internal/models/HostInfoDAOImplTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.host.overview.internal.models;
 
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyListOf;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -45,26 +44,16 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.redhat.thermostat.agent.http.HttpRequestService;
-import com.redhat.thermostat.common.plugin.SystemID;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.ContentProvider;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.util.StringContentProvider;
-import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.Matchers;
 
+import com.redhat.thermostat.agent.http.HttpRequestService;
 import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
 import com.redhat.thermostat.common.plugin.PluginConfiguration;
+import com.redhat.thermostat.common.plugin.SystemID;
 import com.redhat.thermostat.host.overview.internal.models.HostInfoDAOImpl.ConfigurationCreator;
 import com.redhat.thermostat.host.overview.model.HostInfo;
 
@@ -92,19 +81,7 @@
     public void setup() throws Exception {
         info = new HostInfo("foo-agent", HOST_NAME, OS_NAME, OS_KERNEL, CPU_MODEL, CPU_NUM, MEMORY_TOTAL);
 
-        Request request = mock(Request.class);
-        HttpClient httpClient = mock(HttpClient.class);
-        request = mock(Request.class);
-        when(httpClient.newRequest(anyString())).thenReturn(request);
-        ContentResponse response = mock(ContentResponse.class);
-        when(response.getStatus()).thenReturn(HttpStatus.OK_200);
-        when(request.send()).thenReturn(response);
-
         httpRequestService = mock(HttpRequestService.class);
-        ContentResponse contentResponse = mock(ContentResponse.class);
-        when(httpRequestService.sendHttpRequest(anyString(), anyString(), any(HttpMethod.class))).thenReturn(contentResponse);
-        when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200);
-
         jsonHelper = mock(HostInfoDAOImpl.JsonHelper.class);
         when(jsonHelper.toJson(anyListOf(HostInfo.class))).thenReturn(SOME_JSON);
 
@@ -129,7 +106,7 @@
         dao.activate();
         
         dao.put(info);
-        verify(httpRequestService, times(1)).sendHttpRequest(SOME_JSON, URL + "/systems/" + HOST_NAME, HttpMethod.POST);
+        verify(httpRequestService, times(1)).sendHttpRequest(SOME_JSON, URL + "/systems/" + HOST_NAME, HttpRequestService.POST);
     }
 
 }
--- a/plugins/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/models/VmGcStatDAOImpl.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/models/VmGcStatDAOImpl.java	Fri Jun 23 15:16:13 2017 +0200
@@ -46,11 +46,9 @@
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
 
 import com.redhat.thermostat.agent.http.HttpRequestService;
+import com.redhat.thermostat.agent.http.HttpRequestService.RequestFailedException;
 import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
 import com.redhat.thermostat.common.plugin.PluginConfiguration;
 import com.redhat.thermostat.common.utils.LoggingUtils;
@@ -62,7 +60,6 @@
     
     private static final Logger logger = LoggingUtils.getLogger(VmGcStatDAOImpl.class);
     private static final String PLUGIN_ID = "vm-gc";
-    static final String CONTENT_TYPE = "application/json";
     
     private final JsonHelper jsonHelper;
     private final ConfigurationCreator configCreator;
@@ -96,25 +93,15 @@
 
     protected void unbindHttpRequestService(HttpRequestService httpRequestService) {
         this.httpRequestService = null;
+        logger.log(Level.INFO, "Unbound HTTP service. Further attempts to store data will fail until bound again.");
     }
 
     @Override
     public void putVmGcStat(final VmGcStat stat) {
         try {
             String json = jsonHelper.toJson(Arrays.asList(stat));
-
-            if (null != httpRequestService) {
-                ContentResponse response = httpRequestService.sendHttpRequest(json, gatewayURL, HttpMethod.POST);
-
-                int status = response.getStatus();
-                if (status != HttpStatus.OK_200) {
-                    throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + response.getReason());
-                }
-
-            } else {
-                logger.log(Level.WARNING, "Failed to send VmGcStat information to web gateway. Http service unavailable.");
-            }
-        } catch (Exception e) {
+            httpRequestService.sendHttpRequest(json, gatewayURL, HttpRequestService.POST);
+        } catch (RequestFailedException | IOException e) {
             logger.log(Level.WARNING, "Failed to send VmGcStat information to web gateway", e);
         }
     }
--- a/plugins/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/models/VmGcStatDAOImplTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/models/VmGcStatDAOImplTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -36,20 +36,14 @@
 
 package com.redhat.thermostat.vm.gc.agent.internal.models;
 
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.util.Arrays;
 
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -92,10 +86,6 @@
         when(creator.create(source)).thenReturn(config);
 
         httpRequestService = mock(HttpRequestService.class);
-        ContentResponse contentResponse = mock(ContentResponse.class);
-        when(httpRequestService.sendHttpRequest(anyString(), anyString(), any(HttpMethod.class))).thenReturn(contentResponse);
-        when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200);
-
         dao = new VmGcStatDAOImpl(jsonHelper, creator, source);
         dao.bindHttpRequestService(httpRequestService);
     }
@@ -107,7 +97,7 @@
 
         verify(jsonHelper).toJson(eq(Arrays.asList(stat)));
 
-        verify(httpRequestService, times(1)).sendHttpRequest(JSON, GATEWAY_URL, HttpMethod.POST);
+        verify(httpRequestService).sendHttpRequest(JSON, GATEWAY_URL, HttpRequestService.POST);
     }
 
 }
--- a/plugins/vm-memory/agent/src/main/java/com/redhat/thermostat/vm/memory/agent/internal/models/VmMemoryStatDAOImpl.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/vm-memory/agent/src/main/java/com/redhat/thermostat/vm/memory/agent/internal/models/VmMemoryStatDAOImpl.java	Fri Jun 23 15:16:13 2017 +0200
@@ -39,26 +39,20 @@
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
-import com.redhat.thermostat.common.plugin.PluginConfiguration;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.vm.memory.agent.model.VmMemoryStat;
-
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.util.StringContentProvider;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
+
+import com.redhat.thermostat.agent.http.HttpRequestService;
+import com.redhat.thermostat.agent.http.HttpRequestService.RequestFailedException;
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+import com.redhat.thermostat.common.plugin.PluginConfiguration;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.vm.memory.agent.model.VmMemoryStat;
 
 @Component
 @Service(value = VmMemoryStatDAO.class)
@@ -66,10 +60,7 @@
 
     private static final Logger logger = LoggingUtils.getLogger(VmMemoryStatDAOImpl.class);
     private static final String PLUGIN_ID = "vm-memory";
-    private static final String CONTENT_TYPE = "application/json";
 
-    private final HttpClient client;
-    private final HttpHelper httpHelper;
     private final JsonHelper jsonHelper;
     private final ConfigurationCreator configCreator;
 
@@ -77,16 +68,15 @@
 
     @Reference
     private ConfigurationInfoSource configInfoSource;
+    
+    @Reference
+    private HttpRequestService httpRequestService;
 
     public VmMemoryStatDAOImpl() {
-        this(new HttpClient(), new JsonHelper(new VmMemoryStatTypeAdapter()), new HttpHelper(),
-                new ConfigurationCreator(), null);
+        this(new JsonHelper(new VmMemoryStatTypeAdapter()), new ConfigurationCreator(), null);
     }
 
-    VmMemoryStatDAOImpl(HttpClient client, JsonHelper jh, HttpHelper hh, ConfigurationCreator creator,
-            ConfigurationInfoSource source) {
-        this.client = client;
-        this.httpHelper = hh;
+    VmMemoryStatDAOImpl(JsonHelper jh, ConfigurationCreator creator, ConfigurationInfoSource source) {
         this.jsonHelper = jh;
         this.configCreator = creator;
         this.configInfoSource = source;
@@ -96,37 +86,30 @@
     void activate() throws Exception {
         PluginConfiguration config = configCreator.create(configInfoSource);
         this.gatewayURL = config.getGatewayURL();
-
-        httpHelper.startClient(client);
     }
 
     @Override
     public void putVmMemoryStat(final VmMemoryStat stat) {
         try {
             String json = jsonHelper.toJson(Arrays.asList(stat));
-            StringContentProvider provider = httpHelper.createContentProvider(json);
-
-            Request httpRequest = client.newRequest(gatewayURL);
-            httpRequest.method(HttpMethod.POST);
-            httpRequest.content(provider, CONTENT_TYPE);
-            sendRequest(httpRequest);
-        } catch (Exception e) {
+            httpRequestService.sendHttpRequest(json, gatewayURL, HttpRequestService.POST);
+        } catch (RequestFailedException | IOException e) {
             logger.log(Level.WARNING, "Failed to send VmMemoryStat to Web Gateway", e);
         }
     }
 
-    private void sendRequest(Request httpRequest)
-            throws InterruptedException, TimeoutException, ExecutionException, IOException {
-        ContentResponse resp = httpRequest.send();
-        int status = resp.getStatus();
-        if (status != HttpStatus.OK_200) {
-            throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + resp.getReason());
-        }
-    }
-
     protected Logger getLogger() {
         return logger;
     }
+    
+    protected void bindHttpRequestService(HttpRequestService httpRequestService) {
+        this.httpRequestService = httpRequestService;
+    }
+
+    protected void unbindHttpRequestService(HttpRequestService httpRequestService) {
+        this.httpRequestService = null;
+        logger.log(Level.INFO, "Unbound HTTP service. Further attempts to store data will fail until bound again.");
+    }
 
     // For testing purposes
     static class JsonHelper {
@@ -142,19 +125,6 @@
         }
     }
 
-    // For testing purposes
-    static class HttpHelper {
-
-        void startClient(HttpClient httpClient) throws Exception {
-            httpClient.start();
-        }
-
-        StringContentProvider createContentProvider(String content) {
-            return new StringContentProvider(content);
-        }
-
-    }
-
     // For Testing purposes
     static class ConfigurationCreator {
 
--- a/plugins/vm-memory/agent/src/test/java/com/redhat/thermostat/vm/memory/agent/internal/models/VmMemoryStatDAOImplTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/vm-memory/agent/src/test/java/com/redhat/thermostat/vm/memory/agent/internal/models/VmMemoryStatDAOImplTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -37,7 +37,6 @@
 package com.redhat.thermostat.vm.memory.agent.internal.models;
 
 import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -46,18 +45,12 @@
 import java.util.Arrays;
 import java.util.List;
 
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.util.StringContentProvider;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.redhat.thermostat.agent.http.HttpRequestService;
 import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
 import com.redhat.thermostat.common.plugin.PluginConfiguration;
-import com.redhat.thermostat.vm.memory.agent.internal.models.VmMemoryStatDAOImpl.HttpHelper;
 import com.redhat.thermostat.vm.memory.agent.internal.models.VmMemoryStatDAOImpl.JsonHelper;
 import com.redhat.thermostat.vm.memory.agent.model.VmMemoryStat;
 import com.redhat.thermostat.vm.memory.agent.model.VmMemoryStat.Generation;
@@ -66,31 +59,16 @@
 public class VmMemoryStatDAOImplTest {
 
     private static final String JSON = "{\"this\":\"is\",\"test\":\"JSON\"}";
-    private static final String CONTENT_TYPE = "application/json";
     private static final String GATEWAY_URL = "http://example.com/jvm-memory/0.0.2/";
     
-    private HttpClient httpClient;
-    private HttpHelper httpHelper;
     private JsonHelper jsonHelper;
-    private StringContentProvider contentProvider;
-    private Request request;
-    private ContentResponse response;
     private PluginConfiguration config;
     VmMemoryStatDAOImpl.ConfigurationCreator creator;
     ConfigurationInfoSource source;
+    private HttpRequestService httpRequestService;
 
     @Before
     public void setUp() throws Exception {
-        httpClient = mock(HttpClient.class);
-        request = mock(Request.class);
-        when(httpClient.newRequest(anyString())).thenReturn(request);
-        response = mock(ContentResponse.class);
-        when(response.getStatus()).thenReturn(HttpStatus.OK_200);
-        when(request.send()).thenReturn(response);
-
-        httpHelper = mock(HttpHelper.class);
-        contentProvider = mock(StringContentProvider.class);
-        when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider);
         jsonHelper = mock(JsonHelper.class);
         when(jsonHelper.toJson(anyListOf(VmMemoryStat.class))).thenReturn(JSON);
         
@@ -101,6 +79,7 @@
 
         creator = mock(VmMemoryStatDAOImpl.ConfigurationCreator.class);
         when(creator.create(source)).thenReturn(config);
+        httpRequestService = mock(HttpRequestService.class);
     }
 
     @Test
@@ -136,17 +115,14 @@
         VmMemoryStat stat = new VmMemoryStat("foo-agent", 1, "vmId", generations.toArray(new Generation[generations.size()]),
                 2, 3, 4, 5);
 
-        VmMemoryStatDAOImpl dao = new VmMemoryStatDAOImpl(httpClient, jsonHelper, httpHelper, creator, source);
+        VmMemoryStatDAOImpl dao = new VmMemoryStatDAOImpl(jsonHelper, creator, source);
+        dao.bindHttpRequestService(httpRequestService);
         dao.activate();
+        
         dao.putVmMemoryStat(stat);
 
-        verify(httpClient).newRequest(GATEWAY_URL);
-        verify(request).method(HttpMethod.POST);
         verify(jsonHelper).toJson(Arrays.asList(stat));
-        verify(httpHelper).createContentProvider(JSON);
-        verify(request).content(contentProvider, CONTENT_TYPE);
-        verify(request).send();
-        verify(response).getStatus();
+        verify(httpRequestService).sendHttpRequest(JSON, GATEWAY_URL, HttpRequestService.POST);
     }
     
 }
--- a/plugins/vm-memory/agent/src/test/java/com/redhat/thermostat/vm/memory/agent/model/VmMemoryStatTest.java	Tue Jun 27 19:25:23 2017 +0200
+++ b/plugins/vm-memory/agent/src/test/java/com/redhat/thermostat/vm/memory/agent/model/VmMemoryStatTest.java	Fri Jun 23 15:16:13 2017 +0200
@@ -34,7 +34,7 @@
  * to do so, delete this exception statement from your version.
  */
 
-package com.redhat.thermostat.vm.memory.common.model;
+package com.redhat.thermostat.vm.memory.agent.model;
 
 import com.redhat.thermostat.testutils.DataObjectTest;