From 19c615e17e465c9aa95698a5af0c330008571674 Mon Sep 17 00:00:00 2001
From: GCHQDev404 <45399082+GCHQDev404@users.noreply.github.com>
Date: Tue, 25 Oct 2022 22:38:17 +0100
Subject: [PATCH 1/2] Gh 2357 federatedstore hotfix (#2789)
* gh-2357 Exposing better exceptions.
---
.../handler/impl/FederatedOperationHandler.java | 4 ++--
.../handler/FederatedOperationHandlerTest.java | 12 +++++-------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedOperationHandler.java b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedOperationHandler.java
index 937ec6486cd..d843c430f6d 100644
--- a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedOperationHandler.java
+++ b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedOperationHandler.java
@@ -43,7 +43,7 @@
@Since("2.0.0")
public class FederatedOperationHandler implements OperationHandler> {
- public static final String ERROR_WHILE_RUNNING_OPERATION_ON_GRAPHS = "Error while running operation on graphs";
+ public static final String ERROR_WHILE_RUNNING_OPERATION_ON_GRAPHS_FORMAT = "Error while running operation on graphs, due to: %s";
@Override
public Object doOperation(final FederatedOperation operation, final Context context, final Store store) throws OperationException {
@@ -80,7 +80,7 @@ private Iterable getAllGraphResults(final FederatedOperation oper
return results;
} catch (final Exception e) {
- throw new OperationException(ERROR_WHILE_RUNNING_OPERATION_ON_GRAPHS, e);
+ throw new OperationException(String.format(ERROR_WHILE_RUNNING_OPERATION_ON_GRAPHS_FORMAT, e), e);
}
}
diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/FederatedOperationHandlerTest.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/FederatedOperationHandlerTest.java
index 057a6500c49..fd861b70001 100644
--- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/FederatedOperationHandlerTest.java
+++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/FederatedOperationHandlerTest.java
@@ -61,6 +61,7 @@
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -198,13 +199,10 @@ public void shouldThrowStoreException() throws Exception {
when(federatedStore.getGraphs(testUser, null, federatedOperation)).thenReturn(asList(graph1, graph2, graph3, graph4));
// When
- try {
- Object ignore = new FederatedOperationHandler>().doOperation(federatedOperation, context, federatedStore);
- fail("Exception Not thrown");
- } catch (OperationException e) {
- assertEquals(FederatedOperationHandler.ERROR_WHILE_RUNNING_OPERATION_ON_GRAPHS, e.getMessage());
- assertTrue(e.getCause().getMessage().contains(errorMessage));
- }
+ assertThatExceptionOfType(OperationException.class)
+ .isThrownBy(() -> new FederatedOperationHandler>().doOperation(federatedOperation, context, federatedStore))
+ .withMessageContaining(String.format(FederatedOperationHandler.ERROR_WHILE_RUNNING_OPERATION_ON_GRAPHS_FORMAT, ""))
+ .withStackTraceContaining(errorMessage);
}
@Test
From 20413bfcb513911924f7c4aed326f447ef35a8ef Mon Sep 17 00:00:00 2001
From: GCHQDev404 <45399082+GCHQDev404@users.noreply.github.com>
Date: Tue, 25 Oct 2022 22:42:03 +0100
Subject: [PATCH 2/2] gh-2630 example real federatedstore (#2631)
---
.gitignore | 3 +
.../basic/scripts/addMapEdgesClashingGraph.sh | 1 -
.../main/resources/federatedStore.properties | 1 +
.../main/resources/operationDeclarations.json | 4 ++
example/real-federated-store/README.md | 42 ++++++++++++++
.../have-a-go-at-operations/README.md | 35 ++++++++++++
.../curl_add1BasicEdge.sh | 1 +
.../curl_add1BasicEdge_alternative.sh | 16 ++++++
.../curl_addGraphForBasicEdges.sh | 1 +
.../curl_addGraphForBasicEdges_alternative.sh | 41 ++++++++++++++
.../curl_getAllElements.sh | 1 +
.../curl_getAllGraphIds.sh | 1 +
.../curl-operation-examples/curl_getSchema.sh | 1 +
.../curl_getSchema_alternative.sh | 4 ++
.../curl_removeBasicEdgeGraph.sh | 1 +
.../curl_removeBasicEdgeGraph_alternative.sh | 4 ++
.../operation_add1BasicEdge.json | 18 ++++++
.../operation_addGraphAccumuloBasicEdges.json | 26 +++++++++
.../operation_addGraphMapBasicEdges.json | 40 ++++++++++++++
.../operation_getAllElements.json | 3 +
.../operation_getAllGraphIds.json | 3 +
.../operation_getSchema.json | 3 +
.../operation_removeBasicEdgeGraph.json | 4 ++
.../startRealFederatedStore.sh | 55 +++++++++++++++++++
24 files changed, 308 insertions(+), 1 deletion(-)
create mode 100644 example/federated-demo/src/main/resources/operationDeclarations.json
create mode 100644 example/real-federated-store/README.md
create mode 100644 example/real-federated-store/have-a-go-at-operations/README.md
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge_alternative.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges_alternative.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllElements.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllGraphIds.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema_alternative.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph_alternative.sh
create mode 100755 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_add1BasicEdge.json
create mode 100755 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphAccumuloBasicEdges.json
create mode 100755 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphMapBasicEdges.json
create mode 100644 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllElements.json
create mode 100644 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllGraphIds.json
create mode 100644 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getSchema.json
create mode 100644 example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_removeBasicEdgeGraph.json
create mode 100755 example/real-federated-store/startRealFederatedStore.sh
diff --git a/.gitignore b/.gitignore
index 9f3155def0a..c0de98738b0 100755
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,6 @@ __pycache__
parquet_data/
**/graphLibrary/
**/.vscode
+example/real-federated-store/*.properties
+example/real-federated-store/*.json
+example/real-federated-store/*.jar
\ No newline at end of file
diff --git a/example/federated-demo/basic/scripts/addMapEdgesClashingGraph.sh b/example/federated-demo/basic/scripts/addMapEdgesClashingGraph.sh
index 29f44246615..3c9d00a0f2f 100755
--- a/example/federated-demo/basic/scripts/addMapEdgesClashingGraph.sh
+++ b/example/federated-demo/basic/scripts/addMapEdgesClashingGraph.sh
@@ -36,7 +36,6 @@ curl -X POST --header 'Content-Type: application/json' --header 'Accept: applica
}
]
}
- }
}
},
"isPublic": true
diff --git a/example/federated-demo/src/main/resources/federatedStore.properties b/example/federated-demo/src/main/resources/federatedStore.properties
index 05f4f3f19f7..1fa25f80cc0 100644
--- a/example/federated-demo/src/main/resources/federatedStore.properties
+++ b/example/federated-demo/src/main/resources/federatedStore.properties
@@ -15,3 +15,4 @@
#
gaffer.store.class=uk.gov.gchq.gaffer.federatedstore.FederatedStore
gaffer.cache.service.class=uk.gov.gchq.gaffer.cache.impl.JcsCacheService
+gaffer.store.operation.declarations=./operationDeclarations.json
diff --git a/example/federated-demo/src/main/resources/operationDeclarations.json b/example/federated-demo/src/main/resources/operationDeclarations.json
new file mode 100644
index 00000000000..1b3ded98ffc
--- /dev/null
+++ b/example/federated-demo/src/main/resources/operationDeclarations.json
@@ -0,0 +1,4 @@
+{
+ "operations": [
+ ]
+}
\ No newline at end of file
diff --git a/example/real-federated-store/README.md b/example/real-federated-store/README.md
new file mode 100644
index 00000000000..f4a99333ab0
--- /dev/null
+++ b/example/real-federated-store/README.md
@@ -0,0 +1,42 @@
+Copyright 2022 Crown Copyright
+
+Licensed 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.
+
+Real FederatedStore Example
+=============
+This example uses a simple shell script that can build the Gaffer project, gathers
+default config files (federatedStore.properties, graphConfig.json, OperationDeclarations.json, schema.json)
+and an executable Gaffer Spring REST API. The REST API is then started backed by a real FederatedStore from the current config files.
+Users can change these local config files, target/indexed-disk-cache and then reboot the REST API.
+The script will keep users changes to config files, it will only re-gather deleted/missing files.
+This should give a good foundation for users to learn how to configure, interact and launch a real FederatedStore.
+
+## Deployment
+This example does not start or configure a real accumulo cluster. Without you having access to an Accumulo cluster you will not be able to use a Gaffer Accumulo Store.
+
+Assuming you have Java 8, Maven and Git installed, you can build and run the latest version of Gaffer FederatedStore locally by doing the following:
+```bash
+# Clone the Gaffer repository, to reduce the amount you need to download this will only clone the master branch with a depth of 1 so there won't be any history.
+git clone --depth 1 https://github.com/gchq/Gaffer.git #--branch master
+cd Gaffer/example/real-federated-store/
+
+# Run this script from this directory.
+# This will download several maven dependencies such as tomcat.
+./startRealFederatedStore.sh
+```
+
+The rest api will be deployed to localhost:8080/rest.
+
+
+## Example Operations
+Examples can be found at `have-a-go-at-operations`.
\ No newline at end of file
diff --git a/example/real-federated-store/have-a-go-at-operations/README.md b/example/real-federated-store/have-a-go-at-operations/README.md
new file mode 100644
index 00000000000..d902668cf3f
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/README.md
@@ -0,0 +1,35 @@
+Copyright 2022-2022 Crown Copyright
+
+Licensed 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.
+
+Have A Go Operations
+=============
+
+Your FederatedStore will be empty the first time, so a graph followed by elements will need to be added. Example operations can be found here.
+
+## JSON
+Example json operations can be found at `json-operation-examples`.
+Copy & paste the files contents into the Swaggers execute panel.
+
+## Curl Command
+Example curl commands within shell scripts can be found at `curl-opertion-examples`.
+Execute these shell scripts or copy & paste the curl command into your terminal.
+Curl commands with the "alternative" in the name are duplicate examples that contain inline JSON
+instead of reference to a .json file. This allows users to have a go at changing and editing operations in the command line.
+
+```bash
+cd curl-operation-examples/
+./curl_getAllGraphIds.sh
+```
+
+The rest api will be deployed to localhost:8080/rest.
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge.sh
new file mode 100755
index 00000000000..e0d149034d2
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge.sh
@@ -0,0 +1 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d @../json-operation-examples/operation_add1BasicEdge.json 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge_alternative.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge_alternative.sh
new file mode 100755
index 00000000000..e6eaea06b55
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_add1BasicEdge_alternative.sh
@@ -0,0 +1,16 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
+ "class" : "uk.gov.gchq.gaffer.operation.impl.add.AddElements",
+ "input" : [ {
+ "group" : "BasicEdge",
+ "source" : "1",
+ "destination" : "2",
+ "directed" : true,
+ "properties" : {
+ "count" : 1
+ },
+ "class" : "uk.gov.gchq.gaffer.data.element.Edge"
+ } ],
+ "options": {
+ "gaffer.federatedstore.operation.graphIds": "mapEdges"
+ }
+ }' 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges.sh
new file mode 100755
index 00000000000..773cad2d80b
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges.sh
@@ -0,0 +1 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d @../json-operation-examples/operation_addGraphMapBasicEdges.json 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges_alternative.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges_alternative.sh
new file mode 100755
index 00000000000..96b5e0cac2f
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_addGraphForBasicEdges_alternative.sh
@@ -0,0 +1,41 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
+ "class": "AddGraph",
+ "graphId": "mapEdges",
+ "storeProperties": {
+ "gaffer.store.class":"uk.gov.gchq.gaffer.mapstore.MapStore"
+ },
+ "schema": {
+ "edges": {
+ "BasicEdge": {
+ "source": "vertex",
+ "destination": "vertex",
+ "directed": "true",
+ "properties": {
+ "count": "count"
+ }
+ }
+ },
+
+ "types": {
+ "vertex": {
+ "class": "java.lang.String"
+ },
+ "count": {
+ "class": "java.lang.Integer",
+ "aggregateFunction": {
+ "class": "uk.gov.gchq.koryphe.impl.binaryoperator.Sum"
+ }
+ },
+ "true": {
+ "description": "A simple boolean that must always be true.",
+ "class": "java.lang.Boolean",
+ "validateFunctions": [
+ {
+ "class": "uk.gov.gchq.koryphe.impl.predicate.IsTrue"
+ }
+ ]
+ }
+ }
+ },
+ "isPublic": true
+ }' 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllElements.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllElements.sh
new file mode 100755
index 00000000000..d67c3aab385
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllElements.sh
@@ -0,0 +1 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d @../json-operation-examples/operation_getAllElements.json 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllGraphIds.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllGraphIds.sh
new file mode 100755
index 00000000000..c350a5ae87e
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getAllGraphIds.sh
@@ -0,0 +1 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d @../json-operation-examples/operation_getAllGraphIds.json 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema.sh
new file mode 100755
index 00000000000..2734981bc62
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema.sh
@@ -0,0 +1 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d @../json-operation-examples/operation_getSchema.json 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema_alternative.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema_alternative.sh
new file mode 100755
index 00000000000..bf56070110d
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_getSchema_alternative.sh
@@ -0,0 +1,4 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '
+{
+"class":"getSchema"
+}' 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph.sh
new file mode 100755
index 00000000000..fcaeb7f4dad
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph.sh
@@ -0,0 +1 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d @../json-operation-examples/operation_removeBasicEdgeGraph.json 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph_alternative.sh b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph_alternative.sh
new file mode 100755
index 00000000000..f42169f688e
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/curl-operation-examples/curl_removeBasicEdgeGraph_alternative.sh
@@ -0,0 +1,4 @@
+curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
+"class": "removeGraph",
+"graphId": "mapEdges"
+}' 'http://localhost:8080/rest/graph/operations/execute'
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_add1BasicEdge.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_add1BasicEdge.json
new file mode 100755
index 00000000000..18202ce13dd
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_add1BasicEdge.json
@@ -0,0 +1,18 @@
+{
+ "class": "uk.gov.gchq.gaffer.operation.impl.add.AddElements",
+ "input": [
+ {
+ "group": "BasicEdge",
+ "source": "1",
+ "destination": "2",
+ "directed": true,
+ "properties": {
+ "count": 1
+ },
+ "class": "uk.gov.gchq.gaffer.data.element.Edge"
+ }
+ ],
+ "options": {
+ "gaffer.federatedstore.operation.graphIds": "mapEdges"
+ }
+}
\ No newline at end of file
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphAccumuloBasicEdges.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphAccumuloBasicEdges.json
new file mode 100755
index 00000000000..7620eeae4bf
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphAccumuloBasicEdges.json
@@ -0,0 +1,26 @@
+{
+ "class" : "uk.gov.gchq.gaffer.federatedstore.operation.AddGraph",
+ "graphId" : "ToAccumulo",
+ "isPublic" : true,
+ "schema" : {
+ "edges" : {
+ "simple" : {
+ "source" : "String",
+ "destination" : "String"
+ }
+ },
+ "types" : {
+ "String" : {
+ "class" : "java.lang.String"
+ }
+ }
+ },
+ "storeProperties" : {
+ "gaffer.store.class" : "uk.gov.gchq.gaffer.accumulostore.AccumuloStore",
+ "accumulo.user" : "root",
+ "accumulo.instance" : "accumulo",
+ "gaffer.store.properties.class" : "uk.gov.gchq.gaffer.accumulostore.AccumuloProperties",
+ "accumulo.zookeepers" : "localhost:2181",
+ "accumulo.password" : "secret"
+ }
+}
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphMapBasicEdges.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphMapBasicEdges.json
new file mode 100755
index 00000000000..c42c6257a4e
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_addGraphMapBasicEdges.json
@@ -0,0 +1,40 @@
+{
+ "class": "AddGraph",
+ "graphId": "mapEdges",
+ "storeProperties": {
+ "gaffer.store.class": "uk.gov.gchq.gaffer.mapstore.MapStore"
+ },
+ "schema": {
+ "edges": {
+ "BasicEdge": {
+ "source": "vertex",
+ "destination": "vertex",
+ "directed": "true",
+ "properties": {
+ "count": "count"
+ }
+ }
+ },
+ "types": {
+ "vertex": {
+ "class": "java.lang.String"
+ },
+ "count": {
+ "class": "java.lang.Integer",
+ "aggregateFunction": {
+ "class": "uk.gov.gchq.koryphe.impl.binaryoperator.Sum"
+ }
+ },
+ "true": {
+ "description": "A simple boolean that must always be true.",
+ "class": "java.lang.Boolean",
+ "validateFunctions": [
+ {
+ "class": "uk.gov.gchq.koryphe.impl.predicate.IsTrue"
+ }
+ ]
+ }
+ }
+ },
+ "isPublic": true
+}
\ No newline at end of file
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllElements.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllElements.json
new file mode 100644
index 00000000000..0a57292b785
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllElements.json
@@ -0,0 +1,3 @@
+{
+ "class": "GetAllElements"
+}
\ No newline at end of file
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllGraphIds.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllGraphIds.json
new file mode 100644
index 00000000000..bc5086d2384
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getAllGraphIds.json
@@ -0,0 +1,3 @@
+{
+ "class": "GetAllGraphIds"
+}
\ No newline at end of file
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getSchema.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getSchema.json
new file mode 100644
index 00000000000..26ca45e3ce4
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_getSchema.json
@@ -0,0 +1,3 @@
+{
+ "class": "GetSchema"
+}
\ No newline at end of file
diff --git a/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_removeBasicEdgeGraph.json b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_removeBasicEdgeGraph.json
new file mode 100644
index 00000000000..1e535095b04
--- /dev/null
+++ b/example/real-federated-store/have-a-go-at-operations/json-operation-examples/operation_removeBasicEdgeGraph.json
@@ -0,0 +1,4 @@
+{
+ "class": "removeGraph",
+ "graphId": "mapEdges"
+}
\ No newline at end of file
diff --git a/example/real-federated-store/startRealFederatedStore.sh b/example/real-federated-store/startRealFederatedStore.sh
new file mode 100755
index 00000000000..313942c0cef
--- /dev/null
+++ b/example/real-federated-store/startRealFederatedStore.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+# Run this script from this repository.
+# Usage: ./realFederatedStore.sh
+
+SPRING_V=$(cat ../pom.xml | grep "^ .*$" | awk -F'[><]' '{print $3}')
+SPRING_JAR=spring-rest-$SPRING_V-exec.jar
+SPRING_TARGET=../../rest-api/spring-rest/target/$SPRING_JAR
+PROP=federatedStore.properties
+CONF=graphConfig.json
+SCHEMA=schema.json
+OP_DEC=operationDeclarations.json
+PROP_RESOURCE=../federated-demo/src/main/resources/$PROP
+CONF_RESOURCE=../federated-demo/src/main/resources/$CONF
+SCHEMA_RESOURCE=../federated-demo/src/main/resources/$SCHEMA
+OP_DEC_RESOURCE=../federated-demo/src/main/resources/$OP_DEC
+
+if [[ ! -f $CONF ]]
+then
+ echo "Getting graph config $CONF_RESOURCE"
+ cp $CONF_RESOURCE ./$CONF
+fi
+
+if [[ ! -f $PROP ]]
+then
+ echo "Getting properties file: $PROP_RESOURCE"
+ cp $PROP_RESOURCE ./$PROP
+fi
+
+if [[ ! -f $OP_DEC ]]
+then
+ echo "Getting operationDeclarations file: $OP_DEC_RESOURCE"
+ cp $OP_DEC_RESOURCE ./$OP_DEC
+fi
+
+if [[ ! -f $SCHEMA ]]
+then
+ echo "Making empty schema"
+ echo "{}" > $SCHEMA
+fi
+
+if [[ ! -f $SPRING_JAR ]]
+then
+ echo "Getting Spring Jar $SPRING_TARGET"
+ if [[ ! -f $SPRING_TARGET ]]
+ then
+ echo "Spring Jar not found, so building project"
+ mvn clean install -Pquick -f ../../
+ fi
+ cp $SPRING_TARGET ./$SPRING_JAR
+ # echo "mvn clean"
+ # mvn clean -f ../../
+fi
+
+java -Dgaffer.storeProperties=$PROP -Dgaffer.graph.config=$CONF -Dgaffer.schemas=$SCHEMA -jar $SPRING_JAR