You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ud...@apache.org on 2016/03/15 19:54:03 UTC
[2/2] incubator-geode git commit: GEODE-1053: Adding "filter" on
Function Rest Invoction Refactoring of
RestAPIOnRegionFunctionExecutionDUnitTest.java
RestAPIsOnGroupsFunctionExecutionDUnitTest.java
RestAPIsOnMembersFunctionExecutionDUnitTest.java. Updat
GEODE-1053: Adding "filter" on Function Rest Invoction
Refactoring of RestAPIOnRegionFunctionExecutionDUnitTest.java RestAPIsOnGroupsFunctionExecutionDUnitTest.java RestAPIsOnMembersFunctionExecutionDUnitTest.java.
Updating dependency-versions.properties http-core and http-client
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/f2175524
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/f2175524
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/f2175524
Branch: refs/heads/develop
Commit: f2175524491fcab3206b718d6de0164d4fed8906
Parents: 22ab270
Author: Udo Kohlmeyer <uk...@pivotal.io>
Authored: Wed Mar 9 19:58:06 2016 +1100
Committer: Udo Kohlmeyer <uk...@pivotal.io>
Committed: Wed Mar 16 05:53:57 2016 +1100
----------------------------------------------------------------------
.../rest/internal/web/RestFunctionTemplate.java | 23 +
...stAPIOnRegionFunctionExecutionDUnitTest.java | 488 +++++--------------
.../web/controllers/RestAPITestBase.java | 182 +++++--
...tAPIsOnGroupsFunctionExecutionDUnitTest.java | 334 ++++---------
...APIsOnMembersFunctionExecutionDUnitTest.java | 314 +++---------
.../controllers/FunctionAccessController.java | 195 ++++----
.../rest/internal/web/util/ArrayUtils.java | 12 +-
gradle/dependency-versions.properties | 4 +-
8 files changed, 554 insertions(+), 998 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/RestFunctionTemplate.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/RestFunctionTemplate.java b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/RestFunctionTemplate.java
new file mode 100644
index 0000000..8cd0638
--- /dev/null
+++ b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/RestFunctionTemplate.java
@@ -0,0 +1,23 @@
+/*
+ * 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 com.gemstone.gemfire.rest.internal.web;
+
+import com.gemstone.gemfire.cache.execute.FunctionAdapter;
+
+public abstract class RestFunctionTemplate extends FunctionAdapter {
+ public int invocationCount = 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIOnRegionFunctionExecutionDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIOnRegionFunctionExecutionDUnitTest.java b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIOnRegionFunctionExecutionDUnitTest.java
index 4a958ce..63bd9fa 100644
--- a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIOnRegionFunctionExecutionDUnitTest.java
+++ b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIOnRegionFunctionExecutionDUnitTest.java
@@ -16,28 +16,8 @@
*/
package com.gemstone.gemfire.rest.internal.web.controllers;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-
import com.gemstone.gemfire.LogWriter;
-import com.gemstone.gemfire.cache.AttributesFactory;
-import com.gemstone.gemfire.cache.DataPolicy;
-import com.gemstone.gemfire.cache.Region;
-import com.gemstone.gemfire.cache.RegionAttributes;
-import com.gemstone.gemfire.cache.Scope;
-import com.gemstone.gemfire.cache.execute.Function;
+import com.gemstone.gemfire.cache.*;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
@@ -47,44 +27,24 @@ import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.cache.PartitionAttributesImpl;
import com.gemstone.gemfire.internal.cache.PartitionedRegion;
import com.gemstone.gemfire.internal.cache.PartitionedRegionTestHelper;
-import com.gemstone.gemfire.internal.cache.functions.DistributedRegionFunction;
-import com.gemstone.gemfire.test.dunit.Host;
-import com.gemstone.gemfire.test.dunit.IgnoredException;
-import com.gemstone.gemfire.test.dunit.SerializableCallable;
-import com.gemstone.gemfire.test.dunit.VM;
+import com.gemstone.gemfire.rest.internal.web.RestFunctionTemplate;
+import org.apache.http.client.methods.CloseableHttpResponse;
+
+import java.io.Serializable;
+import java.util.*;
/**
* Dunit Test to validate OnRegion function execution with REST APIs
- *
+ *
* @author Nilkanth Patel
* @since 8.0
*/
public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
- private static final long serialVersionUID = 1L;
-
- public static final String REGION_NAME = "DistributedRegionFunctionExecutionDUnitTest";
-
- public static final String PR_REGION_NAME = "samplePRRegion";
-
- public static Region region = null;
-
- public static List<String> restURLs = new ArrayList<String>();
-
- public static String restEndPoint = null;
-
- public static String getRestEndPoint() {
- return restEndPoint;
- }
-
- public static void setRestEndPoint(String restEndPoint) {
- RestAPIOnRegionFunctionExecutionDUnitTest.restEndPoint = restEndPoint;
- }
-
- public static final Function function = new DistributedRegionFunction();
+ private final String REPLICATE_REGION_NAME = "sampleRRegion";
- public static final Function functionWithNoResultThrowsException = new MyFunctionException();
+ private final String PR_REGION_NAME = "samplePRRegion";
public RestAPIOnRegionFunctionExecutionDUnitTest(String name) {
super(name);
@@ -92,52 +52,10 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
public void setUp() throws Exception {
super.setUp();
- final Host host = Host.getHost(0);
- }
-
- static class FunctionWithNoLastResult implements Function {
- private static final long serialVersionUID = -1032915440862585532L;
- public static final String Id = "FunctionWithNoLastResult";
- public static int invocationCount;
-
- @Override
- public void execute(FunctionContext context) {
- invocationCount++;
- InternalDistributedSystem
- .getConnectedInstance()
- .getLogWriter()
- .info(
- "<ExpectedException action=add>did not send last result"
- + "</ExpectedException>");
- context.getResultSender().sendResult(
- (Serializable) context.getArguments());
- }
-
- @Override
- public String getId() {
- return Id;
- }
-
- @Override
- public boolean hasResult() {
- return true;
- }
-
- @Override
- public boolean optimizeForWrite() {
- return false;
- }
-
- @Override
- public boolean isHA() {
- return false;
- }
}
- static class SampleFunction implements Function {
- private static final long serialVersionUID = -1032915440862585534L;
+ private class SampleFunction extends RestFunctionTemplate {
public static final String Id = "SampleFunction";
- public static int invocationCount;
@Override
public void execute(FunctionContext context) {
@@ -145,7 +63,7 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
if (context instanceof RegionFunctionContext) {
RegionFunctionContext rfContext = (RegionFunctionContext) context;
rfContext.getDataSet().getCache().getLogger()
- .info("Executing function : TestFunction2.execute " + rfContext);
+ .info("Executing function : SampleFunction.execute(hasResult=true) with filter: " + rfContext.getFilter() + " " + rfContext);
if (rfContext.getArguments() instanceof Boolean) {
/* return rfContext.getArguments(); */
if (hasResult()) {
@@ -157,7 +75,7 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
.getCache()
.getLogger()
.info(
- "Executing function : TestFunction2.execute " + rfContext);
+ "Executing function : SampleFunction.execute(hasResult=false) " + rfContext);
while (true && !rfContext.getDataSet().isDestroyed()) {
rfContext.getDataSet().getCache().getLogger()
.info("For Bug43513 ");
@@ -172,7 +90,7 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
} else if (rfContext.getArguments() instanceof String) {
String key = (String) rfContext.getArguments();
if (key.equals("TestingTimeOut")) { // for test
- // PRFunctionExecutionDUnitTest#testRemoteMultiKeyExecution_timeout
+ // PRFunctionExecutionDUnitTest#testRemoteMultiKeyExecution_timeout
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
@@ -208,7 +126,7 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
/* return vals; */
} else if (rfContext.getArguments() instanceof HashMap) {
HashMap putData = (HashMap) rfContext.getArguments();
- for (Iterator i = putData.entrySet().iterator(); i.hasNext();) {
+ for (Iterator i = putData.entrySet().iterator(); i.hasNext(); ) {
Map.Entry me = (Map.Entry) i.next();
rfContext.getDataSet().put(me.getKey(), me.getValue());
}
@@ -222,7 +140,7 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
} else {
DistributedSystem ds = InternalDistributedSystem.getAnyInstance();
LogWriter logger = ds.getLogWriter();
- logger.info("Executing in TestFunction on Server : "
+ logger.info("Executing in SampleFunction on Server : "
+ ds.getDistributedMember() + "with Context : " + context);
while (ds.isConnected()) {
logger
@@ -249,7 +167,7 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
@Override
public boolean optimizeForWrite() {
- return false;
+ return true;
}
@Override
@@ -258,54 +176,22 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
}
}
- private int getInvocationCount(VM vm) {
- return (Integer) vm.invoke(new SerializableCallable() {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- @Override
- public Object call() throws Exception {
- SampleFunction f = (SampleFunction) FunctionService
- .getFunction(SampleFunction.Id);
- int count = f.invocationCount;
- f.invocationCount = 0;
- return count;
- }
- });
- }
-
- private void verifyAndResetInvocationCount(VM vm, final int count) {
- vm.invoke(new SerializableCallable() {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- @Override
- public Object call() throws Exception {
- SampleFunction f = (SampleFunction) FunctionService
- .getFunction(SampleFunction.Id);
- assertEquals(count, f.invocationCount);
- // assert succeeded, reset count
- f.invocationCount = 0;
- return null;
- }
- });
+ private void verifyAndResetInvocationCount(final int count) {
+ SampleFunction f = (SampleFunction) FunctionService
+ .getFunction(SampleFunction.Id);
+ assertEquals(count, f.invocationCount);
}
- public static void createPeer(DataPolicy policy) {
+ private void createPeer(DataPolicy policy) {
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK);
factory.setDataPolicy(policy);
- assertNotNull(cache);
- region = cache.createRegion(REGION_NAME, factory.create());
+ Region region = CacheFactory.getAnyInstance().createRegion(REPLICATE_REGION_NAME, factory.create());
com.gemstone.gemfire.test.dunit.LogWriterUtils.getLogWriter().info("Region Created :" + region);
assertNotNull(region);
}
- public static boolean createPeerWithPR() {
+ private boolean createPeerWithPR() {
RegionAttributes ra = PartitionedRegionTestHelper.createRegionAttrsForPR(0,
10);
AttributesFactory raf = new AttributesFactory(ra);
@@ -314,41 +200,19 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
pa.setTotalNumBuckets(17);
raf.setPartitionAttributes(pa);
- if (cache == null || cache.isClosed()) {
- // Cache not available
- }
- assertNotNull(cache);
-
- region = cache.createRegion(PR_REGION_NAME, raf.create());
+ Region region = CacheFactory.getAnyInstance().createRegion(PR_REGION_NAME, raf.create());
com.gemstone.gemfire.test.dunit.LogWriterUtils.getLogWriter().info("Region Created :" + region);
assertNotNull(region);
return Boolean.TRUE;
}
- public static void populateRegion() {
- assertNotNull(cache);
- region = cache.getRegion(REGION_NAME);
- assertNotNull(region);
- for (int i = 1; i <= 200; i++) {
- region.put("execKey-" + i, new Integer(i));
- }
- }
-
- public static void populatePRRegion() {
- assertNotNull(cache);
- region = cache.getRegion(REGION_NAME);
-
- PartitionedRegion pr = (PartitionedRegion) cache.getRegion(PR_REGION_NAME);
+ private void populatePRRegion() {
+ PartitionedRegion pr = (PartitionedRegion) CacheFactory.getAnyInstance().getRegion(PR_REGION_NAME);
DistributedSystem.setThreadsSocketPolicy(false);
- final HashSet testKeys = new HashSet();
for (int i = (pr.getTotalNumberOfBuckets() * 3); i > 0; i--) {
- testKeys.add("execKey-" + i);
- }
- int j = 0;
- for (Iterator i = testKeys.iterator(); i.hasNext();) {
- Integer val = new Integer(j++);
- pr.put(i.next(), val);
+ Integer val = new Integer(i + 1);
+ pr.put("execKey-" + i, val);
}
// Assert there is data in each bucket
for (int bid = 0; bid < pr.getTotalNumberOfBuckets(); bid++) {
@@ -356,9 +220,8 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
}
}
- public static void populateRRRegion() {
- assertNotNull(cache);
- region = cache.getRegion(REGION_NAME);
+ private void populateRRRegion() {
+ Region region = CacheFactory.getAnyInstance().getRegion(REPLICATE_REGION_NAME);
assertNotNull(region);
final HashSet testKeys = new HashSet();
@@ -366,163 +229,48 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
testKeys.add("execKey-" + i);
}
int j = 0;
- for (Iterator i = testKeys.iterator(); i.hasNext();) {
+ for (Iterator i = testKeys.iterator(); i.hasNext(); ) {
Integer val = new Integer(j++);
region.put(i.next(), val);
}
}
- public static void executeFunction_NoLastResult(String regionName) {
-
- try {
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- Random randomGenerator = new Random();
- int index = randomGenerator.nextInt(restURLs.size());
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/"
- + "FunctionWithNoLastResult" + "?onRegion=" + regionName);
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
- response = httpclient.execute(post);
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
- }
-
- }
-
- public static void executeFunctionThroughRestCall(String regionName) {
- com.gemstone.gemfire.test.dunit.LogWriterUtils.getLogWriter().info("Entering executeFunctionThroughRestCall");
- try {
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- Random randomGenerator = new Random();
- int index = randomGenerator.nextInt(restURLs.size());
-
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/"
- + "SampleFunction" + "?onRegion=" + regionName);
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
-
- com.gemstone.gemfire.test.dunit.LogWriterUtils.getLogWriter().info("Request: POST " + post.toString());
- response = httpclient.execute(post);
- com.gemstone.gemfire.test.dunit.LogWriterUtils.getLogWriter().info("Response: POST " + response.toString());
-
- assertEquals(response.getStatusLine().getStatusCode(), 200);
- assertNotNull(response.getEntity());
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
- }
- com.gemstone.gemfire.test.dunit.LogWriterUtils.getLogWriter().info("Exiting executeFunctionThroughRestCall");
-
- }
-
- private void registerFunction(VM vm) {
- vm.invoke(new SerializableCallable() {
- private static final long serialVersionUID = 1L;
- @Override
- public Object call() throws Exception {
- FunctionService.registerFunction(new FunctionWithNoLastResult());
- return null;
- }
- });
- }
-
- private void registerSampleFunction(VM vm) {
- vm.invoke(new SerializableCallable() {
- private static final long serialVersionUID = 1L;
-
- @Override
- public Object call() throws Exception {
- FunctionService.registerFunction(new SampleFunction());
- return null;
- }
- });
+ @Override
+ protected String getFunctionID() {
+ return SampleFunction.Id;
}
- public void __testOnRegionExecutionOnDataPolicyEmpty_NoLastResult() {
- // Step-1 : create cache on each VM, this will start HTTP service in
- // embedded mode and deploy REST APIs web app on it.
-
- fail("This test is trying to invoke non existent methods");
-// String url1 = (String) vm3.invoke(() -> createCacheInVm( vm3 ));
-// restURLs.add(url1);
-//
-// String url2 = (String) vm0.invoke(() -> createCacheInVm( vm0 ));
-// restURLs.add(url2);
-//
-// String url3 = (String) vm1.invoke(() -> createCacheInVm( vm1 ));
-// restURLs.add(url3);
-//
-// String url4 = (String) vm2.invoke(() -> createCacheInVm( vm2 ));
-// restURLs.add(url4);
-
- // Step-2: Register function in all VMs
- registerFunction(vm3);
- registerFunction(vm0);
- registerFunction(vm1);
- registerFunction(vm2);
-
- // Step-3: Create and configure Region on all VMs
- vm3.invoke(() -> createPeer( DataPolicy.EMPTY ));
- vm0.invoke(() -> createPeer( DataPolicy.REPLICATE ));
- vm1.invoke(() -> createPeer( DataPolicy.REPLICATE ));
- vm2.invoke(() -> createPeer( DataPolicy.REPLICATE ));
-
- // Step-4 : Do some puts on region created earlier
- vm3.invoke(() -> populateRegion());
-
- // add expected exception to avoid suspect strings
- final IgnoredException ex = IgnoredException.addIgnoredException("did not send last result");
-
- // Step-5 : Execute function randomly (in iteration) on all available (per
- // VM) REST end-points and verify its result
- for (int i = 0; i < 10; i++) {
- executeFunction_NoLastResult(REGION_NAME);
- }
- ex.remove();
+ private void createCacheAndRegisterFunction() {
+ restURLs.add(vm0.invoke(() -> createCacheWithGroups(vm0, null)));
+ restURLs.add(vm1.invoke(() -> createCacheWithGroups(vm1, null)));
+ restURLs.add(vm2.invoke(() -> createCacheWithGroups(vm2, null)));
+ restURLs.add(vm3.invoke(() -> createCacheWithGroups(vm3, null)));
- restURLs.clear();
+ vm0.invoke(() -> FunctionService.registerFunction(new SampleFunction()));
+ vm1.invoke(() -> FunctionService.registerFunction(new SampleFunction()));
+ vm2.invoke(() -> FunctionService.registerFunction(new SampleFunction()));
+ vm3.invoke(() -> FunctionService.registerFunction(new SampleFunction()));
}
- public void testOnRegionExecutionWithRR() {
- // Step-1 : create cache on each VM, this will start HTTP service in
- // embedded mode and deploy REST APIs web app on it.
- //
- String url1 = (String) vm3.invoke(() -> RestAPITestBase.createCache( vm3 ));
- restURLs.add(url1);
+ public void testOnRegionExecutionWithReplicateRegion() {
+ createCacheAndRegisterFunction();
- String url2 = (String) vm0.invoke(() -> RestAPITestBase.createCache( vm0 ));
- restURLs.add(url2);
+ vm3.invoke(() -> createPeer(DataPolicy.EMPTY));
+ vm0.invoke(() -> createPeer(DataPolicy.REPLICATE));
+ vm1.invoke(() -> createPeer(DataPolicy.REPLICATE));
+ vm2.invoke(() -> createPeer(DataPolicy.REPLICATE));
- String url3 = (String) vm1.invoke(() -> RestAPITestBase.createCache( vm1 ));
- restURLs.add(url3);
-
- String url4 = (String) vm2.invoke(() -> RestAPITestBase.createCache( vm2 ));
- restURLs.add(url4);
-
- // Step-2: Register function in all VMs
- registerSampleFunction(vm3);
- registerSampleFunction(vm0);
- registerSampleFunction(vm1);
- registerSampleFunction(vm2);
-
- // Step-3: Create and configure PR on all VMs
- vm3.invoke(() -> createPeer( DataPolicy.EMPTY ));
- vm0.invoke(() -> createPeer( DataPolicy.REPLICATE ));
- vm1.invoke(() -> createPeer( DataPolicy.REPLICATE ));
- vm2.invoke(() -> createPeer( DataPolicy.REPLICATE ));
-
- // Step-4 : Do some puts in Replicated region on vm3
vm3.invoke(() -> populateRRRegion());
- // Step-5 : Execute function randomly (in iteration) on all available (per
- // VM) REST end-points and verify its result
- executeFunctionThroughRestCall(REGION_NAME);
- int c0 = getInvocationCount(vm0);
- int c1 = getInvocationCount(vm1);
- int c2 = getInvocationCount(vm2);
- int c3 = getInvocationCount(vm3);
+ CloseableHttpResponse response = executeFunctionThroughRestCall("SampleFunction", REPLICATE_REGION_NAME, null, null, null, null);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertNotNull(response.getEntity());
+
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+ int c3 = vm3.invoke(() -> getInvocationCount());
assertEquals(1, c0 + c1 + c2 + c3);
@@ -530,88 +278,84 @@ public class RestAPIOnRegionFunctionExecutionDUnitTest extends RestAPITestBase {
restURLs.clear();
}
- public void testOnRegionExecutionWithPR() throws Exception {
- final String rName = getUniqueName();
-
- // Step-1 : create cache on each VM, this will start HTTP service in
- // embedded mode and deploy REST APIs web app on it.
- String url1 = (String) vm3.invoke(() -> RestAPITestBase.createCache( vm3 ));
- restURLs.add(url1);
-
- String url2 = (String) vm0.invoke(() -> RestAPITestBase.createCache( vm0 ));
- restURLs.add(url2);
+ public void testOnRegionExecutionWithPartitionRegion() throws Exception {
+ createCacheAndRegisterFunction();
- String url3 = (String) vm1.invoke(() -> RestAPITestBase.createCache( vm1 ));
- restURLs.add(url3);
-
- String url4 = (String) vm2.invoke(() -> RestAPITestBase.createCache( vm2 ));
- restURLs.add(url4);
-
- // Step-2: Register function in all VMs
- registerSampleFunction(vm3);
- registerSampleFunction(vm0);
- registerSampleFunction(vm1);
- registerSampleFunction(vm2);
-
- // Step-3: Create and configure PR on all VMs
- vm3.invoke(() -> createPeerWithPR());
vm0.invoke(() -> createPeerWithPR());
vm1.invoke(() -> createPeerWithPR());
vm2.invoke(() -> createPeerWithPR());
+ vm3.invoke(() -> createPeerWithPR());
- // Step-4: Do some puts such that data exist in each bucket
vm3.invoke(() -> populatePRRegion());
- // Step-5 : Execute function randomly (in iteration) on all available (per
- // VM) REST end-points and verify its result
- executeFunctionThroughRestCall(PR_REGION_NAME);
-
- // Assert that each node has executed the function once.
- verifyAndResetInvocationCount(vm0, 1);
- verifyAndResetInvocationCount(vm1, 1);
- verifyAndResetInvocationCount(vm2, 1);
- verifyAndResetInvocationCount(vm3, 1);
+ CloseableHttpResponse response = executeFunctionThroughRestCall("SampleFunction", PR_REGION_NAME, null, null, null, null);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertNotNull(response.getEntity());
- int c0 = getInvocationCount(vm0);
- int c1 = getInvocationCount(vm1);
- int c2 = getInvocationCount(vm2);
- int c3 = getInvocationCount(vm3);
+ vm0.invoke(() -> verifyAndResetInvocationCount(1));
+ vm1.invoke(() -> verifyAndResetInvocationCount(1));
+ vm2.invoke(() -> verifyAndResetInvocationCount(1));
+ vm3.invoke(() -> verifyAndResetInvocationCount(1));
restURLs.clear();
}
-}
+ public void testOnRegionWithFilterExecutionWithPartitionRegion() throws Exception {
+ createCacheAndRegisterFunction();
-class MyFunctionException implements Function {
+ vm0.invoke(() -> createPeerWithPR());
+ vm1.invoke(() -> createPeerWithPR());
+ vm2.invoke(() -> createPeerWithPR());
+ vm3.invoke(() -> createPeerWithPR());
- /**
- *
- */
- private static final long serialVersionUID = 1L;
+ vm3.invoke(() -> populatePRRegion());
- @Override
- public void execute(FunctionContext context) {
- throw new RuntimeException("failure");
- }
+ CloseableHttpResponse response = executeFunctionThroughRestCall("SampleFunction", PR_REGION_NAME, "key2", null, null, null);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertNotNull(response.getEntity());
- @Override
- public String getId() {
- return this.getClass().getName();
- }
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+ int c3 = vm3.invoke(() -> getInvocationCount());
- @Override
- public boolean hasResult() {
- return true;
- }
+ assertEquals(1, (c0 + c1 + c2 + c3));
- @Override
- public boolean isHA() {
- return false;
+ restURLs.clear();
}
- @Override
- public boolean optimizeForWrite() {
- return false;
- }
+// public void testOnRegionWithFilterExecutionWithPartitionRegionJsonArgs() throws Exception {
+// createCacheAndRegisterFunction();
+//
+// vm0.invoke(() -> createPeerWithPR());
+// vm1.invoke(() -> createPeerWithPR());
+// vm2.invoke(() -> createPeerWithPR());
+// vm3.invoke(() -> createPeerWithPR());
+//
+// vm3.invoke(() -> populatePRRegion());
+//
+// String jsonBody = "["
+// + "{\"@type\": \"double\",\"@value\": 210}"
+// + ",{\"@type\":\"com.gemstone.gemfire.web.rest.domain.Item\","
+// + "\"itemNo\":\"599\",\"description\":\"Part X Free on Bumper Offer\","
+// + "\"quantity\":\"2\","
+// + "\"unitprice\":\"5\","
+// + "\"totalprice\":\"10.00\"}"
+// + "]";
+//
+// CloseableHttpResponse response = executeFunctionThroughRestCall("SampleFunction", PR_REGION_NAME, null, jsonBody, null, null);
+// assertEquals(200, response.getStatusLine().getStatusCode());
+// assertNotNull(response.getEntity());
+//
+// // Assert that only 1 node has executed the function.
+// int c0 = vm0.invoke(() -> getInvocationCount());
+// int c1 = vm1.invoke(() -> getInvocationCount());
+// int c2 = vm2.invoke(() -> getInvocationCount());
+// int c3 = vm3.invoke(() -> getInvocationCount());
+//
+// assertEquals(1, (c0 + c1 + c2 + c3));
+//
+// restURLs.clear();
+// }
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPITestBase.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPITestBase.java b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPITestBase.java
index 3709475..0d1fee8 100644
--- a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPITestBase.java
+++ b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPITestBase.java
@@ -16,36 +16,48 @@
*/
package com.gemstone.gemfire.rest.internal.web.controllers;
-import java.util.Properties;
-
import com.gemstone.gemfire.cache.Cache;
-import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.CacheFactory;
-import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.AvailablePortHelper;
import com.gemstone.gemfire.internal.GemFireVersion;
+import com.gemstone.gemfire.internal.lang.StringUtils;
import com.gemstone.gemfire.management.internal.AgentUtil;
-import com.gemstone.gemfire.test.dunit.DistributedTestCase;
-import com.gemstone.gemfire.test.dunit.Host;
-import com.gemstone.gemfire.test.dunit.Invoke;
-import com.gemstone.gemfire.test.dunit.VM;
-import com.gemstone.gemfire.test.dunit.Wait;
+import com.gemstone.gemfire.rest.internal.web.RestFunctionTemplate;
+import com.gemstone.gemfire.test.dunit.*;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.json.JSONArray;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
public class RestAPITestBase extends DistributedTestCase {
- private static final long serialVersionUID = 1L;
- public static Cache cache = null;
+ protected Cache cache = null;
+ protected List<String> restURLs = new ArrayList();
VM vm0 = null;
VM vm1 = null;
VM vm2 = null;
VM vm3 = null;
-
+
public RestAPITestBase(String name) {
super(name);
}
-
-
+
@Override
public void setUp() throws Exception {
super.setUp();
@@ -54,7 +66,7 @@ public class RestAPITestBase extends DistributedTestCase {
if (agentUtil.findWarLocation("geode-web-api") == null) {
fail("unable to locate geode-web-api WAR file");
}
- Wait.pause(5000);
+ Wait.pause(1000);
final Host host = Host.getHost(0);
vm0 = host.getVM(0);
vm1 = host.getVM(1);
@@ -62,9 +74,9 @@ public class RestAPITestBase extends DistributedTestCase {
vm3 = host.getVM(3);
// gradle sets a property telling us where the build is located
final String buildDir = System.getProperty("geode.build.dir", System.getProperty("user.dir"));
- Invoke.invokeInEveryVM(()-> System.setProperty("geode.build.dir", buildDir));
- }
-
+ Invoke.invokeInEveryVM(() -> System.setProperty("geode.build.dir", buildDir));
+ }
+
/**
* close the clients and teh servers
*/
@@ -78,56 +90,122 @@ public class RestAPITestBase extends DistributedTestCase {
/**
* close the cache
- *
*/
- public static void closeCache() {
+ private void closeCache() {
if (cache != null && !cache.isClosed()) {
cache.close();
cache.getDistributedSystem().disconnect();
}
}
-
- protected static String createCache(VM currentVM) {
-
- RestAPITestBase test = new RestAPITestBase(getTestMethodName());
-
- final String hostName = currentVM.getHost().getHostName();
- final int serverPort = AvailablePortHelper.getRandomAvailableTCPPort();
-
- Properties props = new Properties();
-
- props.setProperty(DistributionConfig.START_DEV_REST_API_NAME, "true");
- props.setProperty(DistributionConfig.HTTP_SERVICE_BIND_ADDRESS_NAME, hostName);
- props.setProperty(DistributionConfig.HTTP_SERVICE_PORT_NAME,String.valueOf(serverPort));
-
- InternalDistributedSystem ds = test.getSystem(props);
- cache = CacheFactory.create(ds);
- return "http://" + hostName + ":" + serverPort + "/gemfire-api/v1";
-
- }
-
- public static String createCacheWithGroups (VM vm, final String groups, final String regionName ) {
+ public String createCacheWithGroups(VM vm, final String groups) {
RestAPITestBase test = new RestAPITestBase(getTestMethodName());
-
- final String hostName = vm.getHost().getHostName();
+
+ final String hostName = vm.getHost().getHostName();
final int serverPort = AvailablePortHelper.getRandomAvailableTCPPort();
-
+
Properties props = new Properties();
-
- if(groups != null) {
+
+ if (groups != null) {
props.put("groups", groups);
}
-
+
props.setProperty(DistributionConfig.START_DEV_REST_API_NAME, "true");
props.setProperty(DistributionConfig.HTTP_SERVICE_BIND_ADDRESS_NAME, hostName);
props.setProperty(DistributionConfig.HTTP_SERVICE_PORT_NAME, String.valueOf(serverPort));
-
+
InternalDistributedSystem ds = test.getSystem(props);
cache = CacheFactory.create(ds);
-
- String restEndPoint = "http://" + hostName + ":" + serverPort + "/gemfire-api/v1";
- return restEndPoint;
+
+ String restEndPoint = "http://" + hostName + ":" + serverPort + "/gemfire-api/v1";
+ return restEndPoint;
+ }
+
+ protected int getInvocationCount() {
+ RestFunctionTemplate function = (RestFunctionTemplate) FunctionService.getFunction(getFunctionID());
+ return function.invocationCount;
+ }
+
+ protected CloseableHttpResponse executeFunctionThroughRestCall(String function, String regionName, String filter, String jsonBody, String groups,
+ String members) {
+ LogWriterUtils.getLogWriter().info("Entering executeFunctionThroughRestCall");
+ try {
+ CloseableHttpClient httpclient = HttpClients.createDefault();
+ Random randomGenerator = new Random();
+ int restURLIndex = randomGenerator.nextInt(restURLs.size());
+
+ HttpPost post = createHTTPPost(function, regionName, filter, restURLIndex, groups, members, jsonBody);
+
+ LogWriterUtils.getLogWriter().info("Request: POST " + post.toString());
+ return httpclient.execute(post);
+ } catch (Exception e) {
+ throw new RuntimeException("unexpected exception", e);
+ }
}
-
+
+ private HttpPost createHTTPPost(String function, String regionName, String filter, int restUrlIndex, String groups, String members, String jsonBody) {
+ StringBuilder restURLBuilder = new StringBuilder();
+ restURLBuilder.append(restURLs.get(restUrlIndex) + "/functions/" + function+"?");
+ if (regionName != null && !regionName.isEmpty()) {
+ restURLBuilder.append("onRegion=" + regionName);
+ }
+ else if (groups != null && !groups.isEmpty()) {
+ restURLBuilder.append("onGroups=" + groups);
+ }
+ else if (members != null && !members.isEmpty()) {
+ restURLBuilder.append("onMembers=" + members);
+ }
+ if (filter != null && !filter.isEmpty()) {
+ restURLBuilder.append("&filter=" + filter);
+ }
+ String restString = restURLBuilder.toString();
+ HttpPost post = new HttpPost(restString);
+ post.addHeader("Content-Type", "application/json");
+ post.addHeader("Accept", "application/json");
+ if (jsonBody != null && !StringUtils.isEmpty(jsonBody)) {
+ StringEntity jsonStringEntity = new StringEntity(jsonBody, ContentType.DEFAULT_TEXT);
+ post.setEntity(jsonStringEntity);
+ }
+ return post;
+ }
+
+ protected String getFunctionID() {
+ throw new RuntimeException("This method should be overridden");
+ }
+
+ protected void assertHttpResponse(CloseableHttpResponse response, int httpCode, int expectedServerResponses) {
+ assertEquals(httpCode, response.getStatusLine().getStatusCode());
+
+ //verify response has body flag, expected is true.
+ assertNotNull(response.getEntity());
+ try {
+ String httpResponseString = processHttpResponse(response);
+ response.close();
+ LogWriterUtils.getLogWriter().info("Response : " + httpResponseString);
+ //verify function execution result
+ JSONArray resultArray = new JSONArray(httpResponseString);
+ assertEquals(resultArray.length(), expectedServerResponses);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String processHttpResponse(HttpResponse response) {
+ try {
+ HttpEntity entity = response.getEntity();
+ InputStream content = entity.getContent();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ content));
+ String line;
+ StringBuffer sb = new StringBuffer();
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+ return sb.toString();
+ } catch (IOException e) {
+ LogWriterUtils.getLogWriter().error("Error in processing Http Response", e);
+ }
+ return "";
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnGroupsFunctionExecutionDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnGroupsFunctionExecutionDUnitTest.java b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnGroupsFunctionExecutionDUnitTest.java
index 1ae3810..5acaccb 100644
--- a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnGroupsFunctionExecutionDUnitTest.java
+++ b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnGroupsFunctionExecutionDUnitTest.java
@@ -16,62 +16,119 @@
*/
package com.gemstone.gemfire.rest.internal.web.controllers;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Random;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.json.JSONArray;
-
-import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
-import com.gemstone.gemfire.test.dunit.Host;
-import com.gemstone.gemfire.test.dunit.IgnoredException;
+import com.gemstone.gemfire.rest.internal.web.RestFunctionTemplate;
import com.gemstone.gemfire.test.dunit.LogWriterUtils;
-import com.gemstone.gemfire.test.dunit.SerializableCallable;
-import com.gemstone.gemfire.test.dunit.VM;
+import org.apache.http.client.methods.CloseableHttpResponse;
+
+import java.util.ArrayList;
+import java.util.Collections;
public class RestAPIsOnGroupsFunctionExecutionDUnitTest extends RestAPITestBase {
public RestAPIsOnGroupsFunctionExecutionDUnitTest(String name) {
super(name);
}
-
+
public void setUp() throws Exception {
super.setUp();
- final Host host = Host.getHost(0);
}
-
- private void registerFunction(VM vm) {
- vm.invoke(new SerializableCallable() {
- private static final long serialVersionUID = 1L;
-
- @Override
- public Object call() throws Exception {
- FunctionService.registerFunction(new OnGroupsFunction());
- return null;
- }
- });
+
+ @Override
+ protected String getFunctionID() {
+ return OnGroupsFunction.Id;
+ }
+
+ private void resetInvocationCount() {
+ OnGroupsFunction f = (OnGroupsFunction) FunctionService.getFunction(OnGroupsFunction.Id);
+ f.invocationCount = 0;
+ }
+
+ public void testonGroupsExecutionOnAllMembers() {
+ setupCacheWithGroupsAndFunction();
+
+ for (int i = 0; i < 10; i++) {
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnGroupsFunction", null, null, null, "g0,g1", null);
+ assertHttpResponse(response, 200, 3);
+ }
+
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+
+ assertEquals(30, (c0 + c1 + c2));
+
+ restURLs.clear();
+ }
+
+ private void setupCacheWithGroupsAndFunction() {
+ restURLs.add(vm0.invoke(() -> createCacheWithGroups(vm0, "g0,gm")));
+ restURLs.add(vm1.invoke(() -> createCacheWithGroups(vm1, "g1")));
+ restURLs.add(vm2.invoke(() -> createCacheWithGroups(vm2, "g0,g1")));
+
+ vm0.invoke(() -> FunctionService.registerFunction(new OnGroupsFunction()));
+ vm1.invoke(() -> FunctionService.registerFunction(new OnGroupsFunction()));
+ vm2.invoke(() -> FunctionService.registerFunction(new OnGroupsFunction()));
}
-
- static class OnGroupsFunction implements Function {
- private static final long serialVersionUID = -1032915440862585532L;
+
+ public void testonGroupsExecutionOnAllMembersWithFilter() {
+ setupCacheWithGroupsAndFunction();
+
+ //Execute function randomly (in iteration) on all available (per VM) REST end-points and verify its result
+ for (int i = 0; i < 10; i++) {
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnGroupsFunction", null, "someKey", null, "g1", null);
+ assertHttpResponse(response, 500, 0);
+ }
+
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+
+ assertEquals(0, (c0 + c1 + c2));
+ restURLs.clear();
+ }
+
+ public void testBasicP2PFunctionSelectedGroup() {
+ setupCacheWithGroupsAndFunction();
+
+ //Step-3 : Execute function randomly (in iteration) on all available (per VM) REST end-points and verify its result
+ for (int i = 0; i < 5; i++) {
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnGroupsFunction", null, null, null, "no%20such%20group", null);
+ assertHttpResponse(response, 500, 0);
+ }
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+
+ assertEquals(0, (c0 + c1 + c2));
+
+ for (int i = 0; i < 5; i++) {
+
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnGroupsFunction", null, null, null, "gm", null);
+ assertHttpResponse(response, 200, 1);
+ }
+
+ c0 = vm0.invoke(() -> getInvocationCount());
+ c1 = vm1.invoke(() -> getInvocationCount());
+ c2 = vm2.invoke(() -> getInvocationCount());
+
+ assertEquals(5, (c0 + c1 + c2));
+
+ vm0.invoke(() -> resetInvocationCount());
+ vm1.invoke(() -> resetInvocationCount());
+ vm2.invoke(() -> resetInvocationCount());
+
+ restURLs.clear();
+ }
+
+ private class OnGroupsFunction extends RestFunctionTemplate {
public static final String Id = "OnGroupsFunction";
- public static int invocationCount;
@Override
public void execute(FunctionContext context) {
- LogWriterUtils.getLogWriter().fine("SWAP:1:executing OnGroupsFunction:"+invocationCount);
+ LogWriterUtils.getLogWriter().fine("SWAP:1:executing OnGroupsFunction:" + invocationCount);
InternalDistributedSystem ds = InternalDistributedSystem.getConnectedInstance();
invocationCount++;
ArrayList<String> l = (ArrayList<String>) context.getArguments();
@@ -101,206 +158,5 @@ public class RestAPIsOnGroupsFunctionExecutionDUnitTest extends RestAPITestBase
return false;
}
}
-
-
- public static void executeFunctionThroughRestCall(List<String> restURLs) {
- Random randomGenerator = new Random();
- int index = randomGenerator.nextInt(restURLs.size());
-
- try {
-
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/OnGroupsFunction?onGroups=g0,g1");
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
- LogWriterUtils.getLogWriter().info("Request POST : " + post.toString());
- response = httpclient.execute(post);
-
- HttpEntity entity = response.getEntity();
- InputStream content = entity.getContent();
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- content));
- String line;
- StringBuffer sb = new StringBuffer();
- while ((line = reader.readLine()) != null) {
- sb.append(line);
- }
- LogWriterUtils.getLogWriter().info("Response : " + sb.toString());
-
- //verify response status code. expected status code is 200 OK.
- assertEquals(response.getStatusLine().getStatusCode(), 200);
-
-
- //verify response hasbody flag, expected is true.
- assertNotNull(response.getEntity());
-
-
- response.close();
-
- //verify function execution result
- JSONArray resultArray = new JSONArray(sb.toString());
- assertEquals(resultArray.length(), 3);
-
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
- }
-
- }
-
- public static void executeFunctionOnMemberThroughRestCall(List<String> restURLs) {
- Random randomGenerator = new Random();
- int index = randomGenerator.nextInt(restURLs.size());
-
- //Testcase-1: Executing function on non-existing group.
- final IgnoredException ex = IgnoredException.addIgnoredException("com.gemstone.gemfire.cache.execute.FunctionException");
- try {
-
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/OnGroupsFunction?onGroups=no%20such%20group");
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
- response = httpclient.execute(post);
-
- if ( response.getStatusLine().getStatusCode() == 200 ) {
- fail("FunctionException expected : no member(s) are found belonging to the provided group(s)");
- }
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
-
- } finally {
- ex.remove();
- }
-
- //Testcase-2: Executing function on group with args.
-
- final String FUNCTION_ARGS1 = "{"
- + "\"@type\": \"string\","
- + "\"@value\": \"gm\""
- + "}";
-
- try {
-
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/OnGroupsFunction?onGroups=gm");
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
- response = httpclient.execute(post);
-
- //verify response status code
- assertEquals(response.getStatusLine().getStatusCode(), 200);
-
- //verify response hasbody flag
- assertNotNull(response.getEntity());
-
- HttpEntity entity = response.getEntity();
- InputStream content = entity.getContent();
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- content));
- String line;
- StringBuffer sb = new StringBuffer();
- while ((line = reader.readLine()) != null) {
- sb.append(line);
- }
- response.close();
-
- //verify function execution result
- JSONArray resultArray = new JSONArray(sb.toString());
- assertEquals(resultArray.length(), 1);
-
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
- }
- }
-
- private void verifyAndResetInvocationCount(VM vm, final int count) {
- vm.invoke(new SerializableCallable() {
- @Override
- public Object call() throws Exception {
- OnGroupsFunction f = (OnGroupsFunction) FunctionService.getFunction(OnGroupsFunction.Id);
- assertEquals(count, f.invocationCount);
- // assert succeeded, reset count
- f.invocationCount = 0;
- return null;
- }
- });
- }
-
- private void resetInvocationCount(VM vm) {
- vm.invoke(new SerializableCallable() {
- @Override
- public Object call() throws Exception {
- OnGroupsFunction f = (OnGroupsFunction) FunctionService.getFunction(OnGroupsFunction.Id);
- f.invocationCount = 0;
- return null;
- }
- });
- }
-
- public void testonGroupsExecutionOnAllMembers() {
-
- List<String> restURLs = new ArrayList<String>();
- //Step-1 : create cache on each VM, this will start HTTP service in embedded mode and deploy REST APIs web app on it.
- // Create and configure Region on all VMs. Add Rest end-point into the restURLs list.
-
- String url1 = (String)vm0.invoke(() -> RestAPITestBase.createCacheWithGroups(vm0, "g0,gm", "TEST_REGION"));
- restURLs.add(url1);
-
- String url2 = (String)vm1.invoke(() -> RestAPITestBase.createCacheWithGroups(vm1, "g1", "TEST_REGION" ));
- restURLs.add(url2);
-
- String url3 = (String)vm2.invoke(() -> RestAPITestBase.createCacheWithGroups(vm2, "g0,g1", "TEST_REGION"));
- restURLs.add(url3);
-
- //Step-2: Register function in all VMs
- registerFunction(vm0);
- registerFunction(vm1);
- registerFunction(vm2);
-
- //Step-3 : Execute function randomly (in iteration) on all available (per VM) REST end-points and verify its result
- for (int i=0; i< 10; i++)
- executeFunctionThroughRestCall(restURLs);
-
- //Verify that each node belonging to specified group has run the function
- verifyAndResetInvocationCount(vm0, 10);
- verifyAndResetInvocationCount(vm1, 10);
- verifyAndResetInvocationCount(vm2, 10);
-
- restURLs.clear();
- }
-
-
- public void testBasicP2PFunctionSelectedGroup() {
-
- List<String> restURLs = new ArrayList<String>();
-
- //Step-1 : create cache on each VM, this will start HTTP service in embedded mode and deploy REST APIs web app on it.
- // Create and configure Region on all VMs. Add Rest end-point into the restURLs list.
- String url1 = (String)vm0.invoke(() -> RestAPITestBase.createCacheWithGroups(vm0, "g0,gm", "null" ));
- restURLs.add(url1);
-
- String url2 = (String)vm1.invoke(() -> RestAPITestBase.createCacheWithGroups(vm1, "g1", "null" ));
- restURLs.add(url2);
-
- String url3 = (String)vm2.invoke(() -> RestAPITestBase.createCacheWithGroups(vm2, "g0,g1", "null" ));
- restURLs.add(url3);
-
- //Step-2: Register function in all VMs
- registerFunction(vm0);
- registerFunction(vm1);
- registerFunction(vm2);
-
- //Step-3 : Execute function randomly (in iteration) on all available (per VM) REST end-points and verify its result
- for (int i=0; i< 5; i++)
- executeFunctionOnMemberThroughRestCall(restURLs);
-
- resetInvocationCount(vm0);
- resetInvocationCount(vm1);
- resetInvocationCount(vm2);
-
- restURLs.clear();
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnMembersFunctionExecutionDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnMembersFunctionExecutionDUnitTest.java b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnMembersFunctionExecutionDUnitTest.java
index adb2b55..ac922ad 100644
--- a/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnMembersFunctionExecutionDUnitTest.java
+++ b/geode-assembly/src/test/java/com/gemstone/gemfire/rest/internal/web/controllers/RestAPIsOnMembersFunctionExecutionDUnitTest.java
@@ -16,82 +16,49 @@
*/
package com.gemstone.gemfire.rest.internal.web.controllers;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.json.JSONArray;
-
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.CacheFactory;
-import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.FunctionService;
-import com.gemstone.gemfire.cache30.CacheTestCase;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
-import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.AvailablePortHelper;
-import com.gemstone.gemfire.test.dunit.Assert;
-import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.rest.internal.web.RestFunctionTemplate;
import com.gemstone.gemfire.test.dunit.LogWriterUtils;
-import com.gemstone.gemfire.test.dunit.SerializableCallable;
import com.gemstone.gemfire.test.dunit.VM;
+import org.apache.http.client.methods.CloseableHttpResponse;
+
+import java.util.Properties;
/**
- *
* @author Nilkanth Patel
*/
-public class RestAPIsOnMembersFunctionExecutionDUnitTest extends CacheTestCase {
-
+public class RestAPIsOnMembersFunctionExecutionDUnitTest extends RestAPITestBase {
+
private static final long serialVersionUID = 1L;
-
- VM member1 = null;
- VM member2 = null;
- VM member3 = null;
- VM member4 = null;
-
- static InternalDistributedSystem ds = null;
public RestAPIsOnMembersFunctionExecutionDUnitTest(String name) {
super(name);
}
-
+
@Override
public void setUp() throws Exception {
super.setUp();
- Host host = Host.getHost(0);
- member1 = host.getVM(0);
- member2 = host.getVM(1);
- member3 = host.getVM(2);
- member4 = host.getVM(3);
}
-
- static class OnMembersFunction implements Function {
- private static final long serialVersionUID = -1032915440862585532L;
+
+ private class OnMembersFunction extends RestFunctionTemplate {
public static final String Id = "OnMembersFunction";
- public static int invocationCount;
@Override
public void execute(FunctionContext context) {
-
- LogWriterUtils.getLogWriter().fine("SWAP:1:executing OnMembersFunction:"+invocationCount);
- InternalDistributedSystem ds = InternalDistributedSystem.getConnectedInstance();
+
+ LogWriterUtils.getLogWriter().fine("SWAP:1:executing OnMembersFunction:" + invocationCount);
invocationCount++;
-
+
context.getResultSender().lastResult(Boolean.TRUE);
}
-
+
@Override
public String getId() {
return Id;
@@ -112,217 +79,98 @@ public class RestAPIsOnMembersFunctionExecutionDUnitTest extends CacheTestCase {
return false;
}
}
-
- private void verifyAndResetInvocationCount(VM vm, final int count) {
- vm.invoke(new SerializableCallable() {
- @Override
- public Object call() throws Exception {
- OnMembersFunction f = (OnMembersFunction) FunctionService.getFunction(OnMembersFunction.Id);
- assertEquals(count, f.invocationCount);
- // assert succeeded, reset count
- f.invocationCount = 0;
- return null;
- }
- });
- }
-
- private InternalDistributedSystem createSystem(Properties props){
- try {
- ds = getSystem(props);
- assertNotNull(ds);
- FunctionService.registerFunction(new OnMembersFunction());
-
- }
- catch (Exception e) {
- Assert.fail("Failed while creating the Distribued System", e);
- }
- return ds;
- }
-
- public static String createCacheAndRegisterFunction(VM vm, String memberName) {
- final String hostName = vm.getHost().getHostName();
+
+ private String createCacheAndRegisterFunction(VM vm, String memberName) {
+ final String hostName = vm.getHost().getHostName();
final int serverPort = AvailablePortHelper.getRandomAvailableTCPPort();
-
+
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, memberName);
props.setProperty(DistributionConfig.START_DEV_REST_API_NAME, "true");
props.setProperty(DistributionConfig.HTTP_SERVICE_BIND_ADDRESS_NAME, hostName);
props.setProperty(DistributionConfig.HTTP_SERVICE_PORT_NAME, String.valueOf(serverPort));
-
+
Cache c = null;
try {
- c = CacheFactory.getInstance( new RestAPIsOnMembersFunctionExecutionDUnitTest("temp").getSystem(props));
+ c = CacheFactory.getInstance(new RestAPIsOnMembersFunctionExecutionDUnitTest("temp").getSystem(props));
c.close();
} catch (CacheClosedException cce) {
}
-
+
c = CacheFactory.create(new RestAPIsOnMembersFunctionExecutionDUnitTest("temp").getSystem(props));
FunctionService.registerFunction(new OnMembersFunction());
-
- String restEndPoint = "http://" + hostName + ":" + serverPort + "/gemfire-api/v1";
+
+ String restEndPoint = "http://" + hostName + ":" + serverPort + "/gemfire-api/v1";
return restEndPoint;
-
+
}
-
- public static void executeFunctionOnAllMembersThroughRestCall(List<String> restURLs) {
- Random randomGenerator = new Random();
- int index = randomGenerator.nextInt(restURLs.size());
-
- //Testcase: onMembers Function execution with No groups specified
- try {
-
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/OnMembersFunction");
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
-
- LogWriterUtils.getLogWriter().info("Request POST : " + post.toString());
-
- response = httpclient.execute(post);
-
- HttpEntity entity = response.getEntity();
- InputStream content = entity.getContent();
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- content));
- String line;
- StringBuffer sb = new StringBuffer();
- while ((line = reader.readLine()) != null) {
- sb.append(line);
- }
- LogWriterUtils.getLogWriter().info("Response : " + sb.toString());
-
-
- //verify response status code
- assertEquals(200, response.getStatusLine().getStatusCode());
-
- //verify response hasbody flag
- assertNotNull(response.getEntity());
-
-
- response.close();
-
- JSONArray resultArray = new JSONArray(sb.toString());
- assertEquals(resultArray.length(), 4);
-
- //fail("Expected exception while executing function onMembers without any members ");
-
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
- }
+
+ @Override
+ protected String getFunctionID() {
+ return OnMembersFunction.Id;
}
-
- public static void executeFunctionOnGivenMembersThroughRestCall(List<String> restURLs) {
- Random randomGenerator = new Random();
- int index = randomGenerator.nextInt(restURLs.size());
-
- //Testcase: onMembers Function execution with valid groups
- try {
-
- CloseableHttpClient httpclient = HttpClients.createDefault();
- CloseableHttpResponse response = null;
- HttpPost post = new HttpPost(restURLs.get(index) + "/functions/OnMembersFunction?onMembers=m1,m2,m3");
- post.addHeader("Content-Type", "application/json");
- post.addHeader("Accept", "application/json");
- response = httpclient.execute(post);
-
- //verify response status code. expected status code is 200 OK.
- assertEquals(response.getStatusLine().getStatusCode(), 200);
-
- //verify response hasbody flag, expected is true.
- assertNotNull(response.getEntity());
-
-
- HttpEntity entity = response.getEntity();
- InputStream content = entity.getContent();
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- content));
- String line;
- StringBuffer sb = new StringBuffer();
- while ((line = reader.readLine()) != null) {
- sb.append(line);
- }
- response.close();
-
- //verify function execution result
- JSONArray resultArray = new JSONArray(sb.toString());
- assertEquals(resultArray.length(), 3);
-
- } catch (Exception e) {
- throw new RuntimeException("unexpected exception", e);
+
+ public void testFunctionExecutionOnAllMembers() {
+ restURLs.add(vm0.invoke(() -> createCacheAndRegisterFunction(vm0, "m1")));
+ restURLs.add(vm1.invoke(() -> createCacheAndRegisterFunction(vm1, "m2")));
+ restURLs.add(vm2.invoke(() -> createCacheAndRegisterFunction(vm2, "m3")));
+ restURLs.add(vm3.invoke(() -> createCacheAndRegisterFunction(vm3, "m4")));
+
+ for (int i = 0; i < 10; i++) {
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnMembersFunction",null,null,null,null,null);
+ assertHttpResponse(response, 200, 4);
}
+
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+ int c3 = vm3.invoke(() -> getInvocationCount());
+
+ assertEquals(40, (c0 + c1 + c2 + c3));
+
+ restURLs.clear();
}
-
- public void testFunctionExecutionOnAllMembers() {
-
- List<String> restURLs = new ArrayList<String>();
-
- //Step-1 : create cache on each VM, this will start HTTP service in embedded mode and deploy REST APIs web app on it.
- // Connect to DS and Register function. Add Rest end-point into the restURLs list.
-
- String url1 = (String)member1.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member1, "m1"));
- restURLs.add(url1);
-
- String url2 = (String)member2.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member2, "m2"));
- restURLs.add(url2);
-
- String url3 = (String)member3.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member3, "m3"));
- restURLs.add(url3);
-
- String url4 = (String)member4.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member4, "m4"));
- restURLs.add(url4);
-
- //default case, execute function on all members, register the function in controller VM
- //FunctionService.registerFunction(new OnMembersFunction());
-
- //Step-2 : Execute function randomly (in iteration) on all available (per VM) REST end-points and verify its result
- for (int i=0; i< 10; i++) {
- executeFunctionOnAllMembersThroughRestCall(restURLs);
+
+ public void testFunctionExecutionEOnSelectedMembers() {
+ restURLs.add((String) vm0.invoke(() -> createCacheAndRegisterFunction(vm0, "m1")));
+ restURLs.add((String) vm1.invoke(() -> createCacheAndRegisterFunction(vm1, "m2")));
+ restURLs.add((String) vm2.invoke(() -> createCacheAndRegisterFunction(vm2, "m3")));
+ restURLs.add((String) vm3.invoke(() -> createCacheAndRegisterFunction(vm3, "m4")));
+
+ for (int i = 0; i < 10; i++) {
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnMembersFunction",null,null,null,null,"m1,m2,m3");
+ assertHttpResponse(response, 200, 3);
}
-
- //Verify that each node (m1, m2, m3) has run the function
- verifyAndResetInvocationCount(member1, 10);
- verifyAndResetInvocationCount(member2, 10);
- verifyAndResetInvocationCount(member3, 10);
- verifyAndResetInvocationCount(member4, 10);
+
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+ int c3 = vm3.invoke(() -> getInvocationCount());
+
+ assertEquals(30, (c0 + c1 + c2 + c3));
restURLs.clear();
}
-
- public void testFunctionExecutionEOnSelectedMembers() {
-
- List<String> restURLs = new ArrayList<String>();
-
- //Step-1 : create cache on each VM, this will start HTTP service in embedded mode and deploy REST APIs web app on it.
- // Connect to DS and Register function. Add Rest end-point into the restURLs list.
-
- String url1 = (String)member1.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member1, "m1"));
- restURLs.add(url1);
-
- String url2 = (String)member2.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member2, "m2"));
- restURLs.add(url2);
-
- String url3 = (String)member3.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member3, "m3"));
- restURLs.add(url3);
-
- String url4 = (String)member4.invoke(() -> RestAPIsOnMembersFunctionExecutionDUnitTest.createCacheAndRegisterFunction(member4, "m4"));
- restURLs.add(url4);
-
- //default case, execute function on all members, register the function in controller VM
- //FunctionService.registerFunction(new OnMembersFunction());
-
- //Step-2 : Execute function randomly (in iteration) on all available (per VM) REST end-points and verify its result
- for (int i=0; i< 10; i++) {
- executeFunctionOnGivenMembersThroughRestCall(restURLs);
+
+ public void testFunctionExecutionOnMembersWithFilter() {
+ restURLs.add((String) vm0.invoke(() -> createCacheAndRegisterFunction(vm0, "m1")));
+ restURLs.add((String) vm1.invoke(() -> createCacheAndRegisterFunction(vm1, "m2")));
+ restURLs.add((String) vm2.invoke(() -> createCacheAndRegisterFunction(vm2, "m3")));
+ restURLs.add((String) vm3.invoke(() -> createCacheAndRegisterFunction(vm3, "m4")));
+
+ for (int i = 0; i < 10; i++) {
+ CloseableHttpResponse response = executeFunctionThroughRestCall("OnMembersFunction",null,"key2",null,null,"m1,m2,m3");
+ assertHttpResponse(response, 500, 0);
}
-
- //Verify that each node (m1, m2, m3) has run the function
- verifyAndResetInvocationCount(member1, 10);
- verifyAndResetInvocationCount(member2, 10);
- verifyAndResetInvocationCount(member3, 10);
-
+
+ int c0 = vm0.invoke(() -> getInvocationCount());
+ int c1 = vm1.invoke(() -> getInvocationCount());
+ int c2 = vm2.invoke(() -> getInvocationCount());
+ int c3 = vm3.invoke(() -> getInvocationCount());
+
+ assertEquals(0, (c0 + c1 + c2 + c3));
restURLs.clear();
}
-
+
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/FunctionAccessController.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/FunctionAccessController.java b/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/FunctionAccessController.java
index 2c37c7f..929b70a 100644
--- a/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/FunctionAccessController.java
+++ b/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/FunctionAccessController.java
@@ -17,44 +17,32 @@
package com.gemstone.gemfire.rest.internal.web.controllers;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.logging.log4j.Logger;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
-import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
import com.gemstone.gemfire.cache.LowMemoryException;
-import com.gemstone.gemfire.cache.execute.Execution;
-import com.gemstone.gemfire.cache.execute.Function;
-import com.gemstone.gemfire.cache.execute.FunctionException;
-import com.gemstone.gemfire.cache.execute.FunctionService;
-import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.cache.execute.*;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.rest.internal.web.exception.GemfireRestException;
import com.gemstone.gemfire.rest.internal.web.util.ArrayUtils;
import com.gemstone.gemfire.rest.internal.web.util.JSONUtils;
-import org.json.JSONException;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
+import org.apache.logging.log4j.Logger;
+import org.json.JSONException;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
/**
* The FunctionsController class serving REST Requests related to the function execution
- * <p/>
+ * <p>
+ *
* @author Nilkanth Patel, john blum
* @see org.springframework.stereotype.Controller
* @since 8.0
@@ -72,172 +60,181 @@ public class FunctionAccessController extends AbstractBaseController {
/**
* Gets the version of the REST API implemented by this @Controller.
- * <p/>
+ * <p>
+ *
* @return a String indicating the REST API version.
*/
@Override
protected String getRestApiVersion() {
return REST_API_VERSION;
}
-
+
/**
* list all registered functions in Gemfire data node
+ *
* @return result as a JSON document.
*/
- @RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
+ @RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
@ApiOperation(
- value = "list all functions",
- notes = "list all functions available in the GemFire cluster",
- response = void.class
+ value = "list all functions",
+ notes = "list all functions available in the GemFire cluster",
+ response = void.class
)
- @ApiResponses( {
- @ApiResponse( code = 200, message = "OK." ),
- @ApiResponse( code = 500, message = "GemFire throws an error or exception." )
- } )
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "OK."),
+ @ApiResponse(code = 500, message = "GemFire throws an error or exception.")
+ })
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<?> list() {
-
- if(logger.isDebugEnabled()){
+
+ if (logger.isDebugEnabled()) {
logger.debug("Listing all registered Functions in GemFire...");
}
-
+
final Map<String, Function> registeredFunctions = FunctionService.getRegisteredFunctions();
- String listFunctionsAsJson = JSONUtils.formulateJsonForListFunctionsCall(registeredFunctions.keySet());
- final HttpHeaders headers = new HttpHeaders();
+ String listFunctionsAsJson = JSONUtils.formulateJsonForListFunctionsCall(registeredFunctions.keySet());
+ final HttpHeaders headers = new HttpHeaders();
headers.setLocation(toUri("functions"));
return new ResponseEntity<String>(listFunctionsAsJson, headers, HttpStatus.OK);
- }
-
+ }
+
/**
* Execute a function on Gemfire data node using REST API call.
- * Arguments to the function are passed as JSON string in the request body.
+ * Arguments to the function are passed as JSON string in the request body.
+ *
* @param functionId represents function to be executed
- * @param region list of regions on which function to be executed.
- * @param members list of nodes on which function to be executed.
- * @param groups list of groups on which function to be executed.
+ * @param region list of regions on which function to be executed.
+ * @param members list of nodes on which function to be executed.
+ * @param groups list of groups on which function to be executed.
+ * @param filter list of keys which the function will use to determine on which node to execute the function.
* @param argsInBody function argument as a JSON document
* @return result as a JSON document
*/
@RequestMapping(method = RequestMethod.POST, value = "/{functionId}", produces = { MediaType.APPLICATION_JSON_VALUE })
@ApiOperation(
- value = "execute function",
- notes = "Execute function with arguments on regions, members, or group(s). By default function will be executed on all nodes if none of (onRegion, onMembers, onGroups) specified",
- response = void.class
+ value = "execute function",
+ notes = "Execute function with arguments on regions, members, or group(s). By default function will be executed on all nodes if none of (onRegion, onMembers, onGroups) specified",
+ response = void.class
)
- @ApiResponses( {
- @ApiResponse( code = 200, message = "OK." ),
- @ApiResponse( code = 500, message = "if GemFire throws an error or exception" ),
- @ApiResponse( code = 400, message = "if Function arguments specified as JSON document in the request body is invalid" )
- } )
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "OK."),
+ @ApiResponse(code = 500, message = "if GemFire throws an error or exception"),
+ @ApiResponse(code = 400, message = "if Function arguments specified as JSON document in the request body is invalid")
+ })
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<String> execute(@PathVariable("functionId") String functionId,
- @RequestParam(value = "onRegion", required = false ) String region,
- @RequestParam(value = "onMembers", required = false ) final String[] members,
- @RequestParam(value = "onGroups", required = false) final String[] groups,
- @RequestBody(required = false) final String argsInBody
- )
- {
+ @RequestParam(value = "onRegion", required = false) String region,
+ @RequestParam(value = "onMembers", required = false) final String[] members,
+ @RequestParam(value = "onGroups", required = false) final String[] groups,
+ @RequestParam(value = "filter", required = false) final String[] filter,
+ @RequestBody(required = false) final String argsInBody
+ ) {
Execution function = null;
functionId = decode(functionId);
-
+
if (StringUtils.hasText(region)) {
- if(logger.isDebugEnabled()){
+ if (logger.isDebugEnabled()) {
logger.debug("Executing Function ({}) with arguments ({}) on Region ({})...", functionId,
ArrayUtils.toString(argsInBody), region);
}
-
+
region = decode(region);
try {
function = FunctionService.onRegion(getRegion(region));
- } catch(FunctionException fe){
+ } catch (FunctionException fe) {
throw new GemfireRestException(String.format("The Region identified by name (%1$s) could not found!", region), fe);
}
- }
- else if (ArrayUtils.isNotEmpty(members)) {
- if(logger.isDebugEnabled()){
+ } else if (ArrayUtils.isNotEmpty(members)) {
+ if (logger.isDebugEnabled()) {
logger.debug("Executing Function ({}) with arguments ({}) on Member ({})...", functionId,
ArrayUtils.toString(argsInBody), ArrayUtils.toString(members));
}
- try {
+ try {
function = FunctionService.onMembers(getMembers(members));
- } catch(FunctionException fe){
- throw new GemfireRestException("Could not found the specified members in disributed system!", fe);
+ } catch (FunctionException fe) {
+ throw new GemfireRestException("Could not found the specified members in distributed system!", fe);
}
- }
- else if (ArrayUtils.isNotEmpty(groups)) {
- if(logger.isDebugEnabled()){
+ } else if (ArrayUtils.isNotEmpty(groups)) {
+ if (logger.isDebugEnabled()) {
logger.debug("Executing Function ({}) with arguments ({}) on Groups ({})...", functionId,
ArrayUtils.toString(argsInBody), ArrayUtils.toString(groups));
}
try {
function = FunctionService.onMembers(groups);
- } catch(FunctionException fe){
+ } catch (FunctionException fe) {
throw new GemfireRestException("no member(s) are found belonging to the provided group(s)!", fe);
}
- }
- else {
+ } else {
//Default case is to execute function on all existing data node in DS, document this.
- if(logger.isDebugEnabled()){
+ if (logger.isDebugEnabled()) {
logger.debug("Executing Function ({}) with arguments ({}) on all Members...", functionId,
ArrayUtils.toString(argsInBody));
}
-
+
try {
function = FunctionService.onMembers(getAllMembersInDS());
- } catch(FunctionException fe) {
- throw new GemfireRestException("Disributed system does not contain any valid data node to run the specified function!", fe);
+ } catch (FunctionException fe) {
+ throw new GemfireRestException("Distributed system does not contain any valid data node to run the specified function!", fe);
+ }
+ }
+
+ if (!ArrayUtils.isEmpty(filter)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Executing Function ({}) with filter ({})", functionId,
+ ArrayUtils.toString(filter));
}
+ Set filter1 = ArrayUtils.asSet(filter);
+ function = function.withFilter(filter1);
}
final ResultCollector<?, ?> results;
-
+
try {
- if(argsInBody != null)
- {
+ if (argsInBody != null) {
Object[] args = jsonToObjectArray(argsInBody);
-
+
//execute function with specified arguments
- if(args.length == 1){
+ if (args.length == 1) {
results = function.withArgs(args[0]).execute(functionId);
} else {
results = function.withArgs(args).execute(functionId);
}
- }else {
+ } else {
//execute function with no args
results = function.execute(functionId);
}
- } catch(ClassCastException cce){
+ } catch (ClassCastException cce) {
throw new GemfireRestException("Key is of an inappropriate type for this region!", cce);
- } catch(NullPointerException npe){
+ } catch (NullPointerException npe) {
throw new GemfireRestException("Specified key is null and this region does not permit null keys!", npe);
- } catch(LowMemoryException lme){
+ } catch (LowMemoryException lme) {
throw new GemfireRestException("Server has encountered low memory condition!", lme);
} catch (IllegalArgumentException ie) {
throw new GemfireRestException("Input parameter is null! ", ie);
- }catch (FunctionException fe){
+ } catch (FunctionException fe) {
throw new GemfireRestException("Server has encountered error while executing the function!", fe);
}
-
+
try {
Object functionResult = results.getResult();
-
- if(functionResult instanceof List<?>) {
+
+ if (functionResult instanceof List<?>) {
final HttpHeaders headers = new HttpHeaders();
headers.setLocation(toUri("functions", functionId));
-
+
try {
@SuppressWarnings("unchecked")
- String functionResultAsJson = JSONUtils.convertCollectionToJson((ArrayList<Object>)functionResult);
- return new ResponseEntity<String>(functionResultAsJson, headers, HttpStatus.OK);
+ String functionResultAsJson = JSONUtils.convertCollectionToJson((ArrayList<Object>) functionResult);
+ return new ResponseEntity<String>(functionResultAsJson, headers, HttpStatus.OK);
} catch (JSONException e) {
throw new GemfireRestException("Could not convert function results into Restful (JSON) format!", e);
}
- }else {
+ } else {
throw new GemfireRestException("Function has returned results that could not be converted into Restful (JSON) format!");
}
- }catch (FunctionException fe) {
+ } catch (FunctionException fe) {
fe.printStackTrace();
throw new GemfireRestException("Server has encountered an error while processing function execution!", fe);
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/util/ArrayUtils.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/util/ArrayUtils.java b/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/util/ArrayUtils.java
index 261f9ad..d2d4f2f 100644
--- a/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/util/ArrayUtils.java
+++ b/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/util/ArrayUtils.java
@@ -17,6 +17,9 @@
package com.gemstone.gemfire.rest.internal.web.util;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
/**
* The ArrayUtils class is an abstract utility class for working with Object arrays.
* <p/>
@@ -56,5 +59,12 @@ public abstract class ArrayUtils {
public static String toString(final String... array) {
return toString((Object[])array);
}
-
+
+ public static Set asSet(String[] filter) {
+ LinkedHashSet linkedHashSet = new LinkedHashSet(filter.length);
+ for (int i = 0; i < filter.length; i++) {
+ linkedHashSet.add(filter[i]);
+ }
+ return linkedHashSet;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f2175524/gradle/dependency-versions.properties
----------------------------------------------------------------------
diff --git a/gradle/dependency-versions.properties b/gradle/dependency-versions.properties
index 8a533f6..f0738d7 100644
--- a/gradle/dependency-versions.properties
+++ b/gradle/dependency-versions.properties
@@ -45,8 +45,8 @@ hamcrest-all.version = 1.3
hbase.version = 0.94.27
hibernate.version = 3.5.5-Final
hibernate-commons-annotations.version = 3.2.0.Final
-httpclient.version = 4.3.3
-httpcore.version = 4.3.3
+httpclient.version = 4.5.1
+httpcore.version = 4.4.4
httpunit.version = 1.7.2
hsqldb.version = 2.0.0
jackson.version = 2.2.0