brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [07/10] brooklyn-server git commit: add CompositeEffector tests and improve its implementation
Date Wed, 15 Feb 2017 18:57:30 GMT
add CompositeEffector tests and improve its implementation


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b32581dd
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b32581dd
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b32581dd

Branch: refs/heads/master
Commit: b32581dd81a390d69ff63779465cd83520c7dcab
Parents: b0b83da
Author: Andrea Turli <andrea.turli@gmail.com>
Authored: Thu Feb 2 17:27:41 2017 +0100
Committer: Andrea Turli <andrea.turli@gmail.com>
Committed: Mon Feb 13 15:16:02 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/CompositeEffectorYamlTest.java     |  79 ++++++
 .../core/effector/CompositeEffector.java        |  68 ++---
 .../core/effector/http/HttpCommandEffector.java |  71 +++--
 .../CompositeEffectorIntegrationTest.java       |  27 +-
 .../core/effector/CompositeEffectorTest.java    | 262 +++++++++++++++++++
 .../effector/http/HttpCommandEffectorTest.java  |  88 ++++++-
 .../core/effector/http/int-response.json        |  16 ++
 .../core/effector/http/list-response.json       |  19 ++
 .../core/effector/http/map-response.json        |  16 ++
 .../org/apache/brooklyn/core/effector/test.json |  16 ++
 10 files changed, 595 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java
new file mode 100644
index 0000000..f114f23
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.effector.CompositeEffector;
+import org.apache.brooklyn.core.effector.http.HttpCommandEffector;
+import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class CompositeEffectorYamlTest extends AbstractYamlTest {
+    private static final Logger log = LoggerFactory.getLogger(CompositeEffectorYamlTest.class);
+
+    @Test
+    public void testCompositeEffector() throws Exception {
+        Entity app = createAndStartApplication(
+            "location: localhost",
+            "services:",
+            "- type: " + EmptySoftwareProcess.class.getName(),
+            "  brooklyn.config:",
+            "    onbox.base.dir.skipResolution: true",
+            "    softwareProcess.serviceProcessIsRunningPollPeriod: forever",
+            "  brooklyn.initializers:",
+            "  - type: " + HttpCommandEffector.class.getName(),
+            "    brooklyn.config:",
+            "      name: myEffector",
+            "      description: myDescription",
+            "      uri: https://httpbin.org/get?id=myId",
+            "      httpVerb: GET",
+            "      jsonPath: $.args.id",
+            "      publishSensor: results",
+            "  - type: " + CompositeEffector.class.getName(),
+            "    brooklyn.config:",
+            "      name: start",
+            "      override: true",
+            "      effectors:",
+            "      - myEffector"
+        );
+        waitForApplicationTasks(app);
+
+        EmptySoftwareProcess entity = (EmptySoftwareProcess) Iterables.getOnlyElement(app.getChildren());
+        Effector<?> effector = entity.getEntityType().getEffectorByName("start").get();
+
+        // Invoke without parameter
+        Object results = entity.invoke(effector, ImmutableMap.<String, Object>of()).get();
+        assertEquals(((List<Object>)results).get(0), "myId");
+    }
+
+    @Override
+    protected Logger getLogger() {
+        return log;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java b/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java
index 32f0f1d..5345b4a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java
+++ b/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java
@@ -18,11 +18,12 @@
  */
 package org.apache.brooklyn.core.effector;
 
+import static org.apache.brooklyn.core.entity.trait.Startable.START;
+import static org.apache.brooklyn.core.entity.trait.Startable.STOP;
+
 import java.util.List;
 import java.util.Map;
 
-import javax.annotation.Nullable;
-
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.config.ConfigKey;
@@ -36,11 +37,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.reflect.TypeToken;
 
@@ -48,11 +46,14 @@ import com.google.common.reflect.TypeToken;
 public class CompositeEffector extends AddEffector {
 
     private static final Logger LOG = LoggerFactory.getLogger(CompositeEffector.class);
+    private static final String ORIGINAL_PREFIX = "original-";
 
-    public static final ConfigKey<List<String>> EFFECTORS = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {}, "effectors",
+    public static final ConfigKey<List<String>> EFFECTORS = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {
+                                                                                    }, "effectors",
             "Effector names to be chained together in the composite effector", ImmutableList.<String>of());
     public static final ConfigKey<Boolean> OVERRIDE = ConfigKeys.newBooleanConfigKey("override",
             "Wheter additional defined effectors should override pre-existing effector with same name or not (default: false)", Boolean.FALSE);
+
     public CompositeEffector(ConfigBag params) {
         super(newEffectorBuilder(params).build());
     }
@@ -61,8 +62,8 @@ public class CompositeEffector extends AddEffector {
         this(ConfigBag.newInstance(params));
     }
 
-    public static EffectorBuilder<String> newEffectorBuilder(ConfigBag params) {
-        EffectorBuilder<String> eff = AddEffector.newEffectorBuilder(String.class, params);
+    public static EffectorBuilder<List> newEffectorBuilder(ConfigBag params) {
+        EffectorBuilder<List> eff = AddEffector.newEffectorBuilder(List.class, params);
         eff.impl(new Body(eff.buildAbstract(), params));
         return eff;
     }
@@ -71,13 +72,13 @@ public class CompositeEffector extends AddEffector {
     public void apply(EntityLocal entity) {
         Maybe<Effector<?>> effectorMaybe = entity.getEntityType().getEffectorByName(effector.getName());
         if (!effectorMaybe.isAbsentOrNull()) {
-            Effector<?> original = Effectors.effector(effectorMaybe.get()).name("original-" + effector.getName()).build();
-            ((EntityInternal)entity).getMutableEntityType().addEffector(original);
+            Effector<?> original = Effectors.effector(effectorMaybe.get()).name(ORIGINAL_PREFIX + effector.getName()).build();
+            ((EntityInternal) entity).getMutableEntityType().addEffector(original);
         }
         super.apply(entity);
     }
 
-    protected static class Body extends EffectorBody<String> {
+    protected static class Body extends EffectorBody<List> {
         private final Effector<?> effector;
         private final ConfigBag params;
 
@@ -88,46 +89,47 @@ public class CompositeEffector extends AddEffector {
         }
 
         @Override
-        public String call(final ConfigBag params) {
+        public List<Object> call(final ConfigBag params) {
             ConfigBag allConfig = ConfigBag.newInstanceCopying(this.params).putAll(params);
             final List<String> effectorNames = EntityInitializers.resolve(allConfig, EFFECTORS);
             final Boolean override = allConfig.get(OVERRIDE);
 
             List<Object> results = Lists.newArrayList();
-            if (!override) {
-                Optional<Effector<?>> effectorOptional = Iterables.tryFind(entity().getEntityType().getEffectors(), new Predicate<Effector<?>>() {
-                    @Override
-                    public boolean apply(@Nullable Effector<?> input) {
-                        return input.getName().equals("original-" + effector.getName());
-                    }
-                });
-                // if it is a stop effector, it has to be executed as last effector
-                if (effectorOptional.isPresent()) {
-                    if (effectorOptional.get().getName().endsWith("-stop")) {
-                        effectorNames.add(effectorOptional.get().getName());
-                    } else {
-                        effectorNames.add(0, effectorOptional.get().getName());
-                    }
-                }
-            }
 
+            if (!override && isStartRedefined()) {
+                results.add(invokeEffectorNamed(ORIGINAL_PREFIX + START.getName(), params));
+            }
             for (String eff : effectorNames) {
                 results.add(invokeEffectorNamed(eff, params));
             }
-            return Iterables.toString(results);
+            if (!override && isStopRedefined()) {
+                results.add(invokeEffectorNamed(ORIGINAL_PREFIX + STOP.getName(), params));
+            }
+            return results;
+        }
+
+        private boolean isStartRedefined() {
+            return isEffectorRedefined(ORIGINAL_PREFIX + START.getName());
+        }
+
+        private boolean isStopRedefined() {
+            return isEffectorRedefined(ORIGINAL_PREFIX + STOP.getName());
+        }
+
+        private boolean isEffectorRedefined(String effectorName) {
+            return entity().getEntityType().getEffectorByName(effectorName).isPresent();
         }
 
         private Object invokeEffectorNamed(String effectorName, ConfigBag params) {
-            LOG.debug("{} invoking effector on {}, effector={}, parameters={}",
+            LOG.info("{} invoking effector on {}, effector={}, parameters={}",
                     new Object[]{this, entity(), effectorName, params});
             Maybe<Effector<?>> effector = entity().getEntityType().getEffectorByName(effectorName);
             if (effector.isAbsent()) {
-                // TODO
+                throw new IllegalStateException("Cannot find effector " + effectorName);
             }
             return entity().invoke(effector.get(), params.getAllConfig()).getUnchecked();
-
         }
-    }
 
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java b/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
index 2d8266e..1388a926 100644
--- a/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
+++ b/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
@@ -19,6 +19,7 @@
 package org.apache.brooklyn.core.effector.http;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -49,28 +50,33 @@ import org.apache.brooklyn.util.http.executor.HttpRequest;
 import org.apache.brooklyn.util.http.executor.HttpResponse;
 import org.apache.brooklyn.util.http.executor.UsernamePassword;
 import org.apache.brooklyn.util.http.executor.apacheclient.HttpExecutorImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Enums;
 import com.google.common.base.Joiner;
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import com.google.common.io.ByteStreams;
 import com.google.common.net.HttpHeaders;
 import com.jayway.jsonpath.JsonPath;
 
 public final class HttpCommandEffector extends AddEffector {
 
+    private static final Logger LOG = LoggerFactory.getLogger(HttpCommandEffector.class);
+
     public static final ConfigKey<String> EFFECTOR_URI = ConfigKeys.newStringConfigKey("uri");
     public static final ConfigKey<String> EFFECTOR_HTTP_VERB = ConfigKeys.newStringConfigKey("httpVerb");
     public static final ConfigKey<String> EFFECTOR_HTTP_USERNAME = ConfigKeys.newStringConfigKey("httpUsername");
     public static final ConfigKey<String> EFFECTOR_HTTP_PASSWORD = ConfigKeys.newStringConfigKey("httpPassword");
     public static final ConfigKey<Map<String, String>> EFFECTOR_HTTP_HEADERS = new MapConfigKey(String.class, "headers");
-    public static final ConfigKey<Map<String, Object>> EFFECTOR_HTTP_PAYLOAD = new MapConfigKey(String.class, "httpPayload");
+    public static final ConfigKey<Object> EFFECTOR_HTTP_PAYLOAD = ConfigKeys.newConfigKey(Object.class, "httpPayload");
     public static final ConfigKey<String> JSON_PATH = ConfigKeys.newStringConfigKey("jsonPath", "JSON path to select in HTTP response");
     public static final ConfigKey<String> PUBLISH_SENSOR = ConfigKeys.newStringConfigKey("publishSensor", "Sensor name where to store json path extracted value");
 
+    public static final String APPLICATION_JSON = "application/json";
+
     private enum HttpVerb {
-        GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
+        GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
     }
 
     public HttpCommandEffector(ConfigBag params) {
@@ -89,29 +95,28 @@ public final class HttpCommandEffector extends AddEffector {
 
         public Body(Effector<?> eff, final ConfigBag params) {
             this.effector = eff;
-            Preconditions.checkNotNull(params.getAllConfigRaw().get(EFFECTOR_URI.getName()), "uri must be supplied when defining this effector");
-            Preconditions.checkNotNull(params.getAllConfigRaw().get(EFFECTOR_HTTP_VERB.getName()), "HTTP verb must be supplied when defining this effector");
+            checkNotNull(params.getAllConfigRaw().get(EFFECTOR_URI.getName()), "uri must be supplied when defining this effector");
+            checkNotNull(params.getAllConfigRaw().get(EFFECTOR_HTTP_VERB.getName()), "HTTP verb must be supplied when defining this effector");
             this.params = params;
         }
 
         @Override
         public String call(final ConfigBag params) {
             ConfigBag allConfig = ConfigBag.newInstanceCopying(this.params).putAll(params);
-            final String uri = EntityInitializers.resolve(allConfig, EFFECTOR_URI);
-            final String httpVerb = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_VERB);
+            final URI uri = convertToURI(EntityInitializers.resolve(allConfig, EFFECTOR_URI));
+            final String httpVerb = isValidHttpVerb(EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_VERB));
             final String httpUsername = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_USERNAME);
             final String httpPassword = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_PASSWORD);
             final Map<String, String> headers = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_HEADERS);
-            final Map<String, Object> payload = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_PAYLOAD);
+            final Object payload = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_PAYLOAD);
             final String jsonPath = EntityInitializers.resolve(allConfig, JSON_PATH);
             final String publishSensor = EntityInitializers.resolve(allConfig, PUBLISH_SENSOR);
+            final HttpExecutor httpExecutor = HttpExecutorImpl.newInstance();
+
+            final HttpRequest request = buildHttpRequest(httpVerb, uri, headers, httpUsername, httpPassword, payload);
             Task t = Tasks.builder().displayName(effector.getName()).body(new Callable<Object>() {
                 @Override
                 public Object call() throws Exception {
-                    HttpExecutor httpExecutor = HttpExecutorImpl.newInstance();
-
-                    String body = getBodyFromPayload(payload, headers);
-                    HttpRequest request = buildHttpRequest(httpVerb, uri, headers, httpUsername, httpPassword, body);
                     ByteArrayOutputStream out = new ByteArrayOutputStream();
                     try {
                         HttpResponse response = httpExecutor.execute(request);
@@ -127,6 +132,7 @@ public final class HttpCommandEffector extends AddEffector {
             String responseBody = (String) queue(t).getUnchecked();
 
             if (jsonPath == null) return responseBody;
+
             String extractedValue = JsonPath.parse(responseBody).read(jsonPath, String.class);
             if (publishSensor != null) {
                 entity().sensors().set(Sensors.newStringSensor(publishSensor), extractedValue);
@@ -134,6 +140,16 @@ public final class HttpCommandEffector extends AddEffector {
             return extractedValue;
         }
 
+        private URI convertToURI(String url) {
+            try {
+                return new URL(url).toURI();
+            } catch (MalformedURLException e) {
+                throw Exceptions.propagate(e);
+            } catch (URISyntaxException e) {
+                throw Exceptions.propagate(e);
+            }
+        }
+
         private void validateResponse(HttpResponse response) {
             int statusCode = response.code();
             if (statusCode == 401) {
@@ -145,13 +161,8 @@ public final class HttpCommandEffector extends AddEffector {
             }
         }
 
-        private HttpRequest buildHttpRequest(String httpVerb, String url, Map<String, String> headers, String httpUsername, String httpPassword, String body) throws MalformedURLException, URISyntaxException {
-            // validate url string
-            URI uri = new URL(url).toURI();
-            // validate HTTP verb
-            validateHttpVerb(httpVerb);
+        private HttpRequest buildHttpRequest(String httpVerb, URI uri, Map<String, String> headers, String httpUsername, String httpPassword, Object payload) {
             HttpRequest.Builder httpRequestBuilder = new HttpRequest.Builder()
-                    .body(body.getBytes())
                     .uri(uri)
                     .method(httpVerb)
                     .config(HttpConfig.builder()
@@ -164,6 +175,19 @@ public final class HttpCommandEffector extends AddEffector {
                 httpRequestBuilder.headers(headers);
             }
 
+            if (payload != null) {
+                String body = "";
+                String contentType = headers.get(HttpHeaders.CONTENT_TYPE);
+                if (contentType == null || contentType.equalsIgnoreCase(APPLICATION_JSON)) {
+                    LOG.warn("Content-Type not specified. Using {}, as default (continuing)", APPLICATION_JSON);
+                    body = toJsonString(payload);
+                } else if (!(payload instanceof String) && !contentType.equalsIgnoreCase(APPLICATION_JSON)) {
+                    LOG.warn("the http request may fail with payload {} and 'Content-Type= {}, (continuing)", payload, contentType);
+                    body = payload.toString();
+                }
+                httpRequestBuilder.body(body.getBytes());
+            }
+
             if (httpUsername != null && httpPassword != null) {
                 httpRequestBuilder.credentials(new UsernamePassword(httpUsername, httpPassword));
             }
@@ -171,17 +195,14 @@ public final class HttpCommandEffector extends AddEffector {
             return httpRequestBuilder.build();
         }
 
-        private void validateHttpVerb(String httpVerb) {
+        private String isValidHttpVerb(String httpVerb) {
             Optional<HttpVerb> state = Enums.getIfPresent(HttpVerb.class, httpVerb.toUpperCase());
             checkArgument(state.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(HttpVerb.values()), httpVerb);
+            return httpVerb;
         }
 
-        private String getBodyFromPayload(Map<String, Object> payload, Map<String, String> headers) {
-            String body = "";
-            if (payload != null && !payload.isEmpty() && headers.containsKey(HttpHeaders.CONTENT_TYPE)) {
-                body = Jsonya.newInstance().put(payload).toString();
-            }
-            return body;
+        private String toJsonString(Object payload) {
+            return Jsonya.newInstance().add(payload).toString();
         }
 
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java
index e8cc30e..dd168ed 100644
--- a/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java
@@ -18,6 +18,12 @@
  */
 package org.apache.brooklyn.core.effector;
 
+import static org.apache.brooklyn.test.Asserts.assertEquals;
+import static org.apache.brooklyn.test.Asserts.assertNull;
+import static org.apache.brooklyn.test.Asserts.assertTrue;
+
+import java.util.List;
+
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.entity.EntitySpec;
@@ -36,11 +42,11 @@ import com.google.common.collect.ImmutableList;
 
 public class CompositeEffectorIntegrationTest {
 
-    final static Effector<String> EFFECTOR_START = Effectors.effector(String.class, "start").buildAbstract();
+    final static Effector<List> EFFECTOR_START = Effectors.effector(List.class, "start").buildAbstract();
 
     private TestApplication app;
     private EntityLocal entity;
-    
+
     @BeforeMethod(alwaysRun=true)
     public void setUp() throws Exception {
         app = TestApplication.Factory.newManagedInstanceForTests();
@@ -58,21 +64,28 @@ public class CompositeEffectorIntegrationTest {
         new HttpCommandEffector(ConfigBag.newInstance()
                 .configure(HttpCommandEffector.EFFECTOR_NAME, "eff1")
                 .configure(HttpCommandEffector.EFFECTOR_URI, "https://api.github.com/users/apache")
-                .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET"))
+                .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+                .configure(HttpCommandEffector.JSON_PATH, "$.login"))
                 .apply(entity);
         new HttpCommandEffector(ConfigBag.newInstance()
                 .configure(HttpCommandEffector.EFFECTOR_NAME, "eff2")
                 .configure(HttpCommandEffector.EFFECTOR_URI, "https://api.github.com/users/brooklyncentral")
-                .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET"))
+                .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+                .configure(HttpCommandEffector.JSON_PATH, "$.login"))
                 .apply(entity);
         new CompositeEffector(ConfigBag.newInstance()
                 .configure(CompositeEffector.EFFECTOR_NAME, "start")
                 .configure(CompositeEffector.EFFECTORS, ImmutableList.of("eff1", "eff2")))
                 .apply(entity);
 
-        String val = entity.invoke(EFFECTOR_START, MutableMap.<String,String>of()).get();
-        // TODO
-        System.out.println(val);
+        List<Object> results = entity.invoke(EFFECTOR_START, MutableMap.<String,String>of()).get();
+
+        assertEquals(results.size(), 3);
+        assertNull(results.get(0));
+        assertTrue(results.get(1) instanceof String);
+        assertEquals(results.get(1), "apache");
+        assertTrue(results.get(2) instanceof String);
+        assertEquals(results.get(2), "brooklyncentral");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java
new file mode 100644
index 0000000..3bf0018
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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.brooklyn.core.effector;
+
+import static org.apache.brooklyn.core.effector.http.HttpCommandEffectorTest.EFFECTOR_HTTP_COMMAND;
+import static org.apache.brooklyn.test.Asserts.assertNotNull;
+import static org.apache.brooklyn.test.Asserts.assertNull;
+import static org.apache.brooklyn.test.Asserts.assertTrue;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.effector.http.HttpCommandEffector;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.http.BetterMockWebServer;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
+import org.apache.brooklyn.util.time.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Resources;
+import com.google.mockwebserver.MockResponse;
+
+public class CompositeEffectorTest extends BrooklynAppUnitTestSupport {
+
+    private static final Logger log = LoggerFactory.getLogger(CompositeEffectorTest.class);
+    private static final String DEFAULT_ENDPOINT = "/";
+
+    final static Effector<List> EFFECTOR_COMPOSITE = Effectors.effector(List.class, "CompositeEffector").buildAbstract();
+
+    protected BetterMockWebServer server;
+    protected URL baseUrl;
+
+    protected Location loc;
+    protected CompositeEffector compositeEffector;
+
+   @BeforeMethod
+   public void start() throws IOException {
+      server = BetterMockWebServer.newInstanceLocalhost();
+      server.play();
+   }
+
+   @AfterMethod(alwaysRun = true)
+   public void stop() throws IOException {
+      server.shutdown();
+   }
+
+   protected String url(String path) {
+      return server.getUrl(path).toString();
+   }
+
+   protected MockResponse jsonResponse(String resource) {
+      return new MockResponse().addHeader("Content-Type", "application/json").setBody(stringFromResource(resource));
+   }
+
+   protected MockResponse response404() {
+      return new MockResponse().setStatus("HTTP/1.1 404 Not Found");
+   }
+
+   protected MockResponse response204() {
+      return new MockResponse().setStatus("HTTP/1.1 204 No Content");
+   }
+
+   protected String stringFromResource(String resourceName) {
+      return stringFromResource("/org/apache/brooklyn/core/effector", resourceName);
+   }
+
+   private String stringFromResource(String prefix, String resourceName) {
+      try {
+         return Resources.toString(getClass().getResource(String.format("%s/%s", prefix, resourceName)), Charsets.UTF_8)
+                 .replace(DEFAULT_ENDPOINT, url(""));
+      } catch (IOException e) {
+         throw Throwables.propagate(e);
+      }
+   }
+
+   @Test
+   public void testCompositeEffectorWithNonExistingName() throws InterruptedException {
+      server.enqueue(jsonResponse("test.json"));
+
+      HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+              .configure(HttpCommandEffector.JSON_PATH, "$.args.login")
+      );
+      assertNotNull(httpCommandEffector);
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, EFFECTOR_COMPOSITE.getName())
+              .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName()))
+      );
+      assertNotNull(compositeEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector));
+      List<Object> results = testEntity.invoke(EFFECTOR_COMPOSITE, ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      Asserts.assertEquals(results.size(), 1);
+
+      assertTrue(results.get(0) instanceof String);
+      Asserts.assertEquals(results.get(0), "myLogin");
+   }
+
+   @Test
+   public void testCompositeEffectorWithStartName() throws InterruptedException {
+      server.enqueue(jsonResponse("test.json"));
+
+      HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+              .configure(HttpCommandEffector.JSON_PATH, "$.args.login")
+      );
+      assertNotNull(httpCommandEffector);
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, "start")
+              .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName()))
+      );
+      assertNotNull(compositeEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector));
+      List<Object> results = testEntity.invoke(Effectors.effector(List.class, "start").buildAbstract(), ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      Asserts.assertEquals(results.size(), 2);
+      assertNull(results.get(0));
+      assertTrue(results.get(1) instanceof String);
+      Asserts.assertEquals(results.get(1), "myLogin");
+   }
+
+   @Test
+   public void testCompositeEffectorWithStartNameAndOverriding() throws InterruptedException {
+      server.enqueue(jsonResponse("test.json"));
+
+      HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+              .configure(HttpCommandEffector.JSON_PATH, "$.args.login")
+      );
+      assertNotNull(httpCommandEffector);
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, "start")
+              .configure(CompositeEffector.OVERRIDE, true)
+              .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName()))
+      );
+      assertNotNull(compositeEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector));
+      List<Object> results = testEntity.invoke(Effectors.effector(List.class, "start").buildAbstract(), ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      Asserts.assertEquals(results.size(), 1);
+      assertTrue(results.get(0) instanceof String);
+      Asserts.assertEquals(results.get(0), "myLogin");
+   }
+
+   @Test
+   public void testCompositeEffectorWithStopName() throws InterruptedException {
+      server.enqueue(jsonResponse("test.json"));
+
+      HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+              .configure(HttpCommandEffector.JSON_PATH, "$.args.login")
+      );
+      assertNotNull(httpCommandEffector);
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, "stop")
+              .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName()))
+      );
+      assertNotNull(compositeEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector));
+      List<Object> results = testEntity.invoke(Effectors.effector(List.class, "stop").buildAbstract(), ImmutableMap.<String, Object>of()).getUnchecked(Duration.minutes(1));
+      Asserts.assertEquals(results.size(), 2);
+      assertTrue(results.get(0) instanceof String);
+      Asserts.assertEquals(results.get(0), "myLogin");
+      assertNull(results.get(1));
+   }
+
+   @Test
+   public void testCompositeEffectorWithStopNameAndOverriding() throws InterruptedException {
+      server.enqueue(jsonResponse("test.json"));
+
+      HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+              .configure(HttpCommandEffector.JSON_PATH, "$.args.login")
+      );
+      assertNotNull(httpCommandEffector);
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, "stop")
+              .configure(CompositeEffector.OVERRIDE, true)
+              .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName()))
+      );
+      assertNotNull(compositeEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector));
+      List<Object> results = testEntity.invoke(Effectors.effector(List.class, "stop").buildAbstract(), ImmutableMap.<String, Object>of()).getUnchecked(Duration.minutes(1));
+      Asserts.assertEquals(results.size(), 1);
+      assertTrue(results.get(0) instanceof String);
+      Asserts.assertEquals(results.get(0), "myLogin");
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testMissingEffectors() {
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, EFFECTOR_COMPOSITE.getName())
+              .configure(CompositeEffector.EFFECTORS, null)
+      );
+   }
+
+   @Test(expectedExceptions = PropagatedRuntimeException.class)
+   public void testWhenOneEffectorFails() throws InterruptedException {
+      server.enqueue(response404());
+
+      HttpCommandEffector eff1 = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, "eff1")
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")
+              .configure(HttpCommandEffector.JSON_PATH, "$.args.login"));
+      compositeEffector = new CompositeEffector(ConfigBag.newInstance()
+              .configure(CompositeEffector.EFFECTOR_NAME, EFFECTOR_COMPOSITE.getName())
+              .configure(CompositeEffector.EFFECTORS, ImmutableList.of("eff1", "eff2"))
+      );
+      assertNotNull(compositeEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(eff1, compositeEffector));
+      List<Object> results = testEntity.invoke(EFFECTOR_COMPOSITE, ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      Asserts.assertEquals(results.size(), 2);
+   }
+
+   private EntitySpec<TestEntity> buildEntitySpec(AddEffector... effectors) {
+      EntitySpec<TestEntity> testEntitySpec = EntitySpec.create(TestEntity.class);
+      for (AddEffector effector : effectors) {
+         testEntitySpec.addInitializer(effector);
+      }
+      return testEntitySpec;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java
index a4b8ee0..0580c39 100644
--- a/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java
@@ -44,8 +44,10 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.io.Resources;
+import com.google.common.net.HttpHeaders;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.RecordedRequest;
 
@@ -54,7 +56,7 @@ public class HttpCommandEffectorTest extends BrooklynAppUnitTestSupport {
     private static final Logger log = LoggerFactory.getLogger(HttpCommandEffectorTest.class);
     private static final String DEFAULT_ENDPOINT = "/";
 
-    final static Effector<String> EFFECTOR_HTTP_COMMAND = Effectors.effector(String.class, "http-command-effector").buildAbstract();
+    public final static Effector<String> EFFECTOR_HTTP_COMMAND = Effectors.effector(String.class, "http-command-effector").buildAbstract();
 
     protected BetterMockWebServer server;
     protected URL baseUrl;
@@ -78,7 +80,7 @@ public class HttpCommandEffectorTest extends BrooklynAppUnitTestSupport {
    }
 
    protected MockResponse jsonResponse(String resource) {
-      return new MockResponse().addHeader("Content-Type", "application/json").setBody(stringFromResource(resource));
+      return new MockResponse().addHeader(HttpHeaders.CONTENT_TYPE, "application/json").setBody(stringFromResource(resource));
    }
 
    protected MockResponse response404() {
@@ -144,6 +146,88 @@ public class HttpCommandEffectorTest extends BrooklynAppUnitTestSupport {
    }
 
    @Test
+   public void testPayloadWithContentTypeHeaderJson() throws InterruptedException {
+      server.enqueue(jsonResponse("map-response.json"));
+
+      httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/post"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST")
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, ImmutableMap.of("key", "value"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_HEADERS, ImmutableMap.of(HttpHeaders.CONTENT_TYPE, "application/json"))
+              .configure(HttpCommandEffector.JSON_PATH, "$.data")
+      );
+      assertNotNull(httpCommandEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector));
+      Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.<String, Object>of()).getUnchecked(Duration.minutes(1));
+      assertEquals(output, "{\"key\", \"value\"}");
+
+      assertEquals(server.getRequestCount(), 1);
+      assertSent(server, "POST", "/post");
+   }
+
+   @Test
+   public void testPayloadWithoutContentTypeHeader() throws InterruptedException {
+      server.enqueue(jsonResponse("map-response.json"));
+
+      httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/post"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST")
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, ImmutableMap.of("key", "value"))
+              .configure(HttpCommandEffector.JSON_PATH, "$.data")
+      );
+      assertNotNull(httpCommandEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector));
+      Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      assertEquals(output, "{\"key\", \"value\"}");
+
+      assertEquals(server.getRequestCount(), 1);
+      assertSent(server, "POST", "/post");
+   }
+
+   @Test
+   public void testListPayloadWithoutContentTypeHeader() throws InterruptedException {
+      server.enqueue(jsonResponse("list-response.json"));
+
+      httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/post"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST")
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, ImmutableList.of("key", "value"))
+              .configure(HttpCommandEffector.JSON_PATH, "$.data")
+      );
+      assertNotNull(httpCommandEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector));
+      Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      assertEquals(output, "[\"key\", \"value\"]");
+
+      assertEquals(server.getRequestCount(), "[\"key\", \"value\"]");
+      assertSent(server, "POST", "/post");
+   }
+
+   @Test
+   public void testPayloadWithContentTypeHeaderXml() throws InterruptedException {
+      server.enqueue(jsonResponse("int-response.json"));
+
+      httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance()
+              .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName())
+              .configure(HttpCommandEffector.EFFECTOR_URI, url("/post"))
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST")
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, 1)
+              .configure(HttpCommandEffector.EFFECTOR_HTTP_HEADERS, ImmutableMap.of(HttpHeaders.CONTENT_TYPE, "application/xml"))
+              .configure(HttpCommandEffector.JSON_PATH, "$.data")
+      );
+      assertNotNull(httpCommandEffector);
+      TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector));
+      Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.<String, Object>of()).getUnchecked(Duration.seconds(1));
+      assertEquals(output, "1");
+
+      assertEquals(server.getRequestCount(), 1);
+      assertSent(server, "POST", "/post");
+   }
+
+   @Test
    public void testHappyPath() throws InterruptedException {
       server.enqueue(jsonResponse("login.json"));
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json b/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json
new file mode 100644
index 0000000..9b133f7
--- /dev/null
+++ b/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json
@@ -0,0 +1,16 @@
+{
+  "args": {},
+  "data": "1",
+  "files": {},
+  "form": {},
+  "headers": {
+    "Accept": "*/*",
+    "Content-Length": "1",
+    "Content-Type": "application/json",
+    "Host": "httpbin.org",
+    "User-Agent": "curl/7.49.1"
+  },
+  "json": 1,
+  "origin": "93.61.99.89",
+  "url": "http://httpbin.org/post"
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json b/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json
new file mode 100644
index 0000000..88394ea
--- /dev/null
+++ b/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json
@@ -0,0 +1,19 @@
+{
+  "args": {},
+  "data": "[\"key\", \"value\"]",
+  "files": {},
+  "form": {},
+  "headers": {
+    "Accept": "*/*",
+    "Content-Length": "16",
+    "Content-Type": "application/json",
+    "Host": "httpbin.org",
+    "User-Agent": "curl/7.49.1"
+  },
+  "json": [
+    "key",
+    "value"
+  ],
+  "origin": "93.61.99.89",
+  "url": "http://httpbin.org/post"
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json b/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json
new file mode 100644
index 0000000..959b763
--- /dev/null
+++ b/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json
@@ -0,0 +1,16 @@
+{
+  "args": {},
+  "data": "{\"key\", \"value\"}",
+  "files": {},
+  "form": {},
+  "headers": {
+    "Accept": "*/*",
+    "Content-Length": "16",
+    "Content-Type": "application/json",
+    "Host": "httpbin.org",
+    "User-Agent": "curl/7.49.1"
+  },
+  "json": null,
+  "origin": "93.61.99.89",
+  "url": "http://httpbin.org/post"
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/test.json
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/test.json b/core/src/test/resources/org/apache/brooklyn/core/effector/test.json
new file mode 100644
index 0000000..b39889a
--- /dev/null
+++ b/core/src/test/resources/org/apache/brooklyn/core/effector/test.json
@@ -0,0 +1,16 @@
+{
+  "args": {
+    "login": "myLogin"
+  },
+  "headers": {
+    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
+    "Accept-Encoding": "gzip, deflate, sdch, br",
+    "Accept-Language": "en-US,en;q=0.8,it;q=0.6",
+    "Cookie": "_ga=GA1.2.1060288368.1484053495; _gat=1",
+    "Host": "httpbin.org",
+    "Upgrade-Insecure-Requests": "1",
+    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
+  },
+  "origin": "93.61.99.89",
+  "url": "https://httpbin.org/get?login=myLogin"
+}


Mime
View raw message