Gizmo uses Champ the microservice
[aai/gizmo.git] / src / main / java / org / onap / crud / dao / champ / ChampDao.java
index f217897..fa2bab5 100644 (file)
  */
 package org.onap.crud.dao.champ;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.onap.aai.champcore.ChampGraph;
-import org.onap.aai.champcore.ChampTransaction;
-import org.onap.aai.champcore.exceptions.ChampMarshallingException;
-import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
-import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
-import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
-import org.onap.aai.champcore.exceptions.ChampTransactionException;
-import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
-import org.onap.aai.champcore.model.ChampObject;
-import org.onap.aai.champcore.model.ChampRelationship;
-import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep;
+import net.dongliu.gson.GsonJava8TypeAdapterFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.message.BasicNameValuePair;
+import org.eclipse.jetty.util.security.Password;
+import org.onap.aai.logging.LoggingContext;
 import org.onap.aai.cl.api.Logger;
 import org.onap.aai.cl.eelf.LoggerFactory;
 import org.onap.crud.dao.GraphDao;
 import org.onap.crud.entity.Edge;
 import org.onap.crud.entity.Vertex;
 import org.onap.crud.exception.CrudException;
-import org.onap.crud.logging.CrudServiceMsgs;
-
-/**
- * This is the integration layer between the CRUD API service and the low level
- * Champ library for graph database interaction.
- */
-public class ChampDao implements GraphDao {
-
-  public static final String CONFIG_STORAGE_BACKEND = "storage.backend";
-  public static final String CONFIG_STORAGE_BACKEND_DB = "storage.backend.db";
-  public static final String STORAGE_HBASE_DB = "hbase";
-  public static final String STORAGE_CASSANDRA_DB = "cassandra";
-  public static final String CONFIG_STORAGE_HOSTNAMES = "storage.hostnames";
-  public static final String CONFIG_STORAGE_PORT = "storage.port";
-  public static final String CONFIG_HBASE_ZNODE_PARENT = "storage.hbase.ext.zookeeper.znode.parent";
-  public static final String CONFIG_GRAPH_NAME = "graph.name";
-  public static final String GRAPH_UNQ_INSTANCE_ID_SUFFIX = "graph.unique-instance-id-suffix";
+import org.onap.crud.util.CrudServiceConstants;
+import org.openecomp.restclient.client.OperationResult;
+import org.openecomp.restclient.client.RestClient;
+import org.openecomp.restclient.enums.RestAuthenticationMode;
+import org.slf4j.MDC;
 
-  public static final String CONFIG_EVENT_STREAM_PUBLISHER = "event.stream.publisher";
-  public static final String CONFIG_EVENT_STREAM_NUM_PUBLISHERS = "event.stream.num-publishers";
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
-  private static Map<String, ChampTransaction> transactions = new ConcurrentHashMap<String, ChampTransaction>();
-  public static final String DEFAULT_GRAPH_NAME = "default_graph";
+public class ChampDao implements GraphDao {
+  private RestClient client;
+  private String baseObjectUrl;
+  private String baseRelationshipUrl;
+  private String baseTransactionUrl;
+
+  private static final String HEADER_FROM_APP = "X-FromAppId";
+  private static final String HEADER_TRANS_ID = "X-TransactionId";
+  private static final String FROM_APP_NAME = "Gizmo";
+  private static final String OBJECT_SUB_URL = "objects";
+  private static final String RELATIONSHIP_SUB_URL = "relationships";
+  private static final String TRANSACTION_SUB_URL = "transaction";
 
-  private enum GraphType {
-    IN_MEMORY, TITAN, DSE
-  }
+  private Logger logger = LoggerFactory.getInstance().getLogger(ChampDao.class.getName());
 
-  /**
-   * Instance of the API used for interacting with the Champ library.
-   */
-  private ChampGraph champApi = null;
+  // We use a custom vertex serializer for champ because it expects "key"
+  // instead of "id"
+  private static final Gson champGson = new GsonBuilder()
+      .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory())
+      .registerTypeAdapter(Vertex.class, new ChampVertexSerializer())
+      .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create();
 
-  private Logger logger = LoggerFactory.getInstance().getLogger(ChampDao.class.getName());
+  public ChampDao(String champUrl, String certPassword) {
+    try {
+      client = new RestClient().authenticationMode(RestAuthenticationMode.SSL_CERT).validateServerHostname(false)
+          .validateServerCertChain(false).clientCertFile(CrudServiceConstants.CRD_CHAMP_AUTH_FILE)
+          .clientCertPassword(Password.deobfuscate(certPassword));
 
-  /**
-   * Creates a new instance of the ChampDao.
-   *
-   * @param champGraph
-   *          - Concrete implementation of the graph dao layer
-   */
-  public ChampDao(ChampGraph champGraph) {
-    this.champApi = champGraph;
+      baseObjectUrl = champUrl + OBJECT_SUB_URL;
+      baseRelationshipUrl = champUrl + RELATIONSHIP_SUB_URL;
+      baseTransactionUrl = champUrl + TRANSACTION_SUB_URL;
+    } catch (Exception e) {
+      System.out.println("Error setting up Champ configuration");
+      e.printStackTrace();
+      System.exit(1);
+    }
   }
 
   @Override
   public Vertex getVertex(String id) throws CrudException {
+    String url = baseObjectUrl + "/" + id;
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-    try {
-
-      if (logger.isDebugEnabled()) {
-        logger.debug("getVertex with id: " + id);
-      }
-
-      long idAsLong = Long.parseLong(id);
-
-      Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
-
-      String nodeType = org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName();
-      if (retrievedVertex.isPresent() && retrievedVertex.get().getProperties().get(nodeType) != null) {
-        return vertexFromChampObject(retrievedVertex.get(),
-            retrievedVertex.get().getProperties().get(nodeType).toString());
-      } else {
-
-        // We didn't find a vertex with the supplied id, so just throw an
-        // exception.
-        throw new CrudException("No vertex with id " + id + " found in graph",
-            javax.ws.rs.core.Response.Status.NOT_FOUND);
-      }
-
-    } catch (ChampUnmarshallingException | ChampTransactionException e) {
-
-      // Something went wrong - throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == 200) {
+      return Vertex.fromJson(getResult.getResult());
+    } else {
+      // We didn't find a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("No vertex with id " + id + " found in graph",
+          javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
   }
 
   @Override
   public Vertex getVertex(String id, String type) throws CrudException {
+    String url = baseObjectUrl + "/" + id;
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-    try {
-
-      if (logger.isDebugEnabled()) {
-        logger.debug("getVertex with id: " + id);
-      }
-
-      long idAsLong = Long.parseLong(id);
-
-      // Request the vertex from the graph db.
-      Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
-
-      // Did we find it?
-      if (retrievedVertex.isPresent()
-          && retrievedVertex.get().getProperties()
-              .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) != null
-          && retrievedVertex.get().getProperties()
-              .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()
-              .equalsIgnoreCase(type)) {
+    if (getResult.getResultCode() == 200) {
+      Vertex vert = Vertex.fromJson(getResult.getResult());
 
-        // Yup, convert it to a Vector object and return it.
-        return vertexFromChampObject(retrievedVertex.get(), type);
-
-      } else {
-
-        // We didn't find a vertex with the supplied id, so just throw an
+      if (!vert.getType().equalsIgnoreCase(type)) {
+        // We didn't find a vertex with the supplied type, so just throw an
         // exception.
-        throw new CrudException("No vertex with id " + id + " found in graph",
+        throw new CrudException("No vertex with id " + id + "and type " + type + " found in graph",
             javax.ws.rs.core.Response.Status.NOT_FOUND);
       }
-
-    } catch (ChampUnmarshallingException | ChampTransactionException e) {
-
-      // Something went wrong - throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+      return vert;
+    } else {
+      // We didn't find a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("No vertex with id " + id + " found in graph",
+          javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
   }
 
   @Override
   public List<Edge> getVertexEdges(String id) throws CrudException {
+    String url = baseObjectUrl + "/relationships/" + id;
 
-    if (logger.isDebugEnabled()) {
-      logger.debug("get Edges incident to vertex with id: " + id + " from graph");
-    }
-
-    try {
-      long idAsLong = Long.parseLong(id); // GDF - what to do about id???
-
-      // Request the vertex from the graph db.
-      Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
-
-      // Did we find it?
-      if (retrievedVertex.isPresent()) {
-
-        // Query the Champ library for the edges which are incident to the
-        // specified
-        // vertex.
-        Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get());
-
-        // Build an edge list from the result stream.
-        List<Edge> edges = new ArrayList<Edge>();
-        relationships.forEach(r -> edges.add(edgeFromChampRelationship(r)));
-
-        return edges;
-
-      } else {
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-        // We couldn't find the specified vertex, so throw an exception.
-        throw new CrudException("No vertex with id " + id + " found in graph",
-            javax.ws.rs.core.Response.Status.NOT_FOUND);
-      }
-
-    } catch (ChampUnmarshallingException e) {
-
-      // Something went wrong, so throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-
-    } catch (ChampObjectNotExistsException e) {
-
-      // We couldn't find the specified vertex, so throw an exception.
+    if (getResult.getResultCode() == 200) {
+      return champGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>() {
+      }.getType());
+    } else {
+      // We didn't find a vertex with the supplied id, so just throw an
+      // exception.
       throw new CrudException("No vertex with id " + id + " found in graph",
           javax.ws.rs.core.Response.Status.NOT_FOUND);
-    } catch (ChampTransactionException e) {
-      throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-    }
-  }
-
-  @Override
-  public Vertex addVertex(String type, Map<String, Object> properties) throws CrudException {
-
-    if (logger.isDebugEnabled()) {
-      logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties));
-    }
-
-    // Add the aai_node_type so that AAI can read the data created by gizmo
-    properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
-
-    // Create an object to represent our vertex in the format expected by the
-    // Champ library.
-    ChampObject objectToCreate = buildChampObject(type, properties);
-
-    try {
-
-      // Ask the Champ library to store our vertex, placing the returned object
-      // into a
-      // list so that we can easily put that into our result object.
-      return vertexFromChampObject(champApi.storeObject(objectToCreate), type);
-
-    } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException
-        | ChampTransactionException e) {
-
-      // Something went wrong - throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-    }
-  }
-
-  @Override
-  public Vertex updateVertex(String id, String type, Map<String, Object> properties) throws CrudException {
-
-    if (logger.isDebugEnabled()) {
-      logger.debug("Update vertex with id: " + id + " with properties: " + propertiesMapToString(properties));
-    }
-    // Add the aai_node_type so that AAI can read the data created by gizmo
-    properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
-
-    try {
-      // Now, build the updated version of the Champ Object...
-      ChampObject updateObject = buildChampObject(id, type, properties);
-      // ...and send it to the Champ library.
-      return vertexFromChampObject(champApi.replaceObject(updateObject), type);
-
-    } catch (ChampObjectNotExistsException e) {
-      throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
-    } catch (NumberFormatException | ChampMarshallingException | ChampSchemaViolationException e) {
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-    } catch (ChampTransactionException e) {
-      throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
     }
-
   }
 
   @Override
   public List<Vertex> getVertices(String type, Map<String, Object> filter) throws CrudException {
-
-    if (logger.isDebugEnabled()) {
-      logger.debug("Retrieve vertices with type label: " + type + " which map query parameters: "
-          + propertiesMapToString(filter));
-    }
-
     filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
 
-    Stream<ChampObject> retrievedVertices;
-    try {
-      retrievedVertices = champApi.queryObjects(filter);
-
-    } catch (ChampTransactionException e) {
-      throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-    }
-
-    List<Vertex> vertices = retrievedVertices.map(v -> vertexFromChampObject(v, type)).collect(Collectors.toList());
-
-    if (logger.isDebugEnabled()) {
-      logger.debug("Resulting vertex list: " + retrievedVertices);
-    }
+    String url = baseObjectUrl + "/filter" + "?"
+        + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
 
-    // ...and return it to the caller.
-    return vertices;
-  }
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-  private Object getRelKey(String id) {
-    Object key = id;
-    // convert into Long if applicable . TODO : revisit in story NUC-304
-    try {
-      key = Long.parseLong(id);
-    } catch (NumberFormatException e) {
-      // The id isn't a Long, leave it as a string
+    if (getResult.getResultCode() == 200) {
+      return champGson.fromJson(getResult.getResult(), new TypeToken<List<Vertex>>() {
+      }.getType());
+    } else {
+      // We didn't find a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("No vertices found in graph for given filters",
+          javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
-
-    return key;
   }
 
   @Override
   public Edge getEdge(String id, String type) throws CrudException {
+    String url = baseRelationshipUrl + "/" + id;
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-    if (logger.isDebugEnabled()) {
-      logger.debug("Get edge with id: " + id);
-    }
-
-    try {
-
-      // Request the edge from the graph db.
-      Optional<ChampRelationship> relationship = champApi.retrieveRelationship(getRelKey(id));
-
-      // Did we find it?
-      if (relationship.isPresent() && relationship.get().getType().equals(type)) {
-
-        // Yup - return the result.
-        return edgeFromChampRelationship(relationship.get());
-
-      } else {
+    if (getResult.getResultCode() == 200) {
+      Edge edge = Edge.fromJson(getResult.getResult());
 
-        // We didn't find an edge with the supplied id, so throw an exception.
-        throw new CrudException("No edge with id " + id + " found in graph",
+      if (!edge.getType().equalsIgnoreCase(type)) {
+        // We didn't find an edge with the supplied type, so just throw an
+        // exception.
+        throw new CrudException("No edge with id " + id + "and type " + type + " found in graph",
             javax.ws.rs.core.Response.Status.NOT_FOUND);
       }
-
-    } catch (ChampUnmarshallingException | ChampTransactionException e) {
-
-      // Something went wrong, so throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+      return edge;
+    } else {
+      // We didn't find a edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
   }
 
   @Override
-  public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties) throws CrudException {
-
-    // For now, assume source and target are straight ids...
-    try {
-
-      Optional<ChampObject> sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()));
-      if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) {
-        throw new CrudException(
-            "Error creating edge - source vertex with id " + source + " does not exist in graph data base",
-            javax.ws.rs.core.Response.Status.BAD_REQUEST);
-      }
-
-      Optional<ChampObject> targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()));
-      if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) {
-        throw new CrudException(
-            "Error creating edge - target vertex with id " + target + " does not exist in graph data base",
-            javax.ws.rs.core.Response.Status.BAD_REQUEST);
-      }
-
-      // Now, create the ChampRelationship object for our edge and store it in
-      // the graph database.
-      return edgeFromChampRelationship(champApi.storeRelationship(
-          new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build()));
+  public List<Edge> getEdges(String type, Map<String, Object> filter) throws CrudException {
+    String url = baseRelationshipUrl + "/filter" + "?"
+        + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
 
-    } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException
-        | ChampRelationshipNotExistsException | ChampUnmarshallingException | NumberFormatException
-        | ChampTransactionException e) {
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      throw new CrudException("Error creating edge: " + e.getMessage(),
-          javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == 200) {
+      return champGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>() {
+      }.getType());
+    } else {
+      // We didn't find a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("No edges found in graph for given filters", javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
   }
 
   @Override
-  public List<Edge> getEdges(String type, Map<String, Object> filter) throws CrudException {
-
-    filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type);
-
-    Stream<ChampRelationship> retrievedRelationships;
-    try {
-      retrievedRelationships = champApi.queryRelationships(filter);
-
-    } catch (ChampTransactionException e) {
-      throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-    }
-
-    // Process the result stream from the Champ library into an Edge list,
-    // keeping only
-    // edges of the specified type.
-    List<Edge> edges = retrievedRelationships.map(r -> edgeFromChampRelationship(r)).collect(Collectors.toList());
+  public Vertex addVertex(String type, Map<String, Object> properties) throws CrudException {
+    String url = baseObjectUrl;
 
-    return edges;
-  }
+    // Add the aai_node_type so that AAI can read the data created by gizmo
+    // TODO: This probably shouldn't be here
+    properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
 
-  @Override
-  public Edge updateEdge(Edge edge) throws CrudException {
+    Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+    properties.forEach(insertVertexBuilder::property);
+    Vertex insertVertex = insertVertexBuilder.build();
 
-    if (logger.isDebugEnabled()) {
-      logger.debug(
-          "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties()));
-    }
+    OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
 
-    try {
-      // Now, build the updated version of the Champ Relationship...
-      ChampRelationship updateRelationship = new ChampRelationship.Builder(
-          buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(),
-              edge.getSource().getProperties()),
-          buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(),
-              edge.getTarget().getProperties()),
-          edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build();
-      // ...and send it to the Champ library.
-      return edgeFromChampRelationship(champApi.replaceRelationship(updateRelationship));
-
-    } catch (ChampRelationshipNotExistsException ex) {
-      throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
-    } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException
-        | ChampSchemaViolationException | ChampTransactionException ex) {
-
-      throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
+      return Vertex.fromJson(getResult.getResult());
+    } else {
+      // We didn't create a vertex with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to create vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
   }
 
   @Override
-  public void deleteVertex(String id, String type) throws CrudException {
-
-    try {
-
-      // First, retrieve the vertex that we intend to delete.
-      Optional<ChampObject> retrievedVertex = champApi.retrieveObject(Long.parseLong(id));
-
-      // Did we find it?
-      if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) {
-        throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.",
-            javax.ws.rs.core.Response.Status.NOT_FOUND);
-      }
-
-      // Now, verify that there are no edges incident to the vertex (they must
-      // be deleted
-      // first if so).
-      Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get());
+  public Vertex updateVertex(String id, String type, Map<String, Object> properties) throws CrudException {
+    String url = baseObjectUrl + "/" + id;
 
-      if (relationships.count() > 0) {
-        throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.",
-            javax.ws.rs.core.Response.Status.BAD_REQUEST);
-      }
+    // Add the aai_node_type so that AAI can read the data created by gizmo
+    // TODO: This probably shouldn't be here
+    properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
 
-      // Finally, we can attempt to delete our vertex.
-      champApi.deleteObject(Long.parseLong(id));
+    Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+    insertVertexBuilder.id(id);
+    properties.forEach(insertVertexBuilder::property);
+    Vertex insertVertex = insertVertexBuilder.build();
 
-    } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException
-        | ChampTransactionException e) {
+    String payload = insertVertex.toJson(champGson);
+    OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
 
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+      return Vertex.fromJson(getResult.getResult());
+    } else {
+      // We didn't create a vertex with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to update vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
   }
 
   @Override
-  public void deleteEdge(String id, String type) throws CrudException {
-
-    try {
-
-      // First, retrieve the edge that we want to delete.
-      Optional<ChampRelationship> relationshipToDelete = champApi.retrieveRelationship(getRelKey(id));
-
-      // Did we find it?
-      if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) {
-        throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist",
-            javax.ws.rs.core.Response.Status.NOT_FOUND);
-      }
-
-      // Now we can delete the edge.
-      champApi.deleteRelationship(relationshipToDelete.get());
-
-    } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException
-        | ChampTransactionException e) {
+  public void deleteVertex(String id, String type) throws CrudException {
+    String url = baseObjectUrl + "/" + id;
+    OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() != Response.Status.OK.getStatusCode()) {
+      // We didn't delete a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("Failed to delete vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
   }
 
-  /**
-   * This helper method generates a string representation of a properties map
-   * for logging purposes.
-   *
-   * @param properties
-   *          - The properties map to be converted.
-   * @return - The log statement friendly conversion of the properties map.
-   */
-  private String propertiesMapToString(Map<String, Object> properties) {
-
-    StringBuilder sb = new StringBuilder();
-    sb.append("{");
-
-    for (String key : properties.keySet()) {
-      sb.append("(").append(key).append(" -> ").append(properties.get(key)).append(") ");
-    }
+  @Override
+  public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties) throws CrudException {
+    String url = baseRelationshipUrl;
 
-    sb.append("}");
+    // Try requests to ensure source and target exist in Champ
+    Vertex dbSource = getVertex(source.getId().get(), source.getType());
+    Vertex dbTarget = getVertex(target.getId().get(), target.getType());
 
-    return sb.toString();
-  }
+    Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget);
+    properties.forEach(insertEdgeBuilder::property);
+    Edge insertEdge = insertEdgeBuilder.build();
 
-  /**
-   * This helper method constructs a {@link ChampObject} suitable for passing to
-   * the Champ library.
-   *
-   * @param type
-   *          - The type to assign to our ChampObject
-   * @param properties
-   *          - The set of properties to assign to our ChampObject
-   * @return - A populated ChampObject
-   */
-  private ChampObject buildChampObject(String type, Map<String, Object> properties) {
-
-    ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withoutKey();
-
-    for (String key : properties.keySet()) {
-      objectInProgress.withProperty(key, properties.get(key));
-    }
-    return objectInProgress.build();
-  }
+    String edgeJson = insertEdge.toJson(champGson);
+    OperationResult getResult = client.post(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
 
-  /**
-   * This helper method constructs a {@link ChampObject} suitable for passing to
-   * the Champ library.
-   *
-   * @param id
-   *          - Unique identifier for this object.
-   * @param type
-   *          - The type to assign to our ChampObject
-   * @param properties
-   *          - The set of properties to assign to our ChampObject
-   * @return - A populated ChampObject
-   */
-  private ChampObject buildChampObject(String id, String type, Map<String, Object> properties) {
-
-    ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withKey(Long.parseLong(id));
-
-    for (String key : properties.keySet()) {
-      objectInProgress.withProperty(key, properties.get(key));
+    if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
+      return Edge.fromJson(getResult.getResult());
+    } else {
+      // We didn't create an edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to create edge", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
-    return objectInProgress.build();
   }
 
-  private Vertex vertexFromChampObject(ChampObject champObject, String type) {
-
-    // Get the identifier for this vertex from the Champ object.
-    Object id = champObject.getKey().orElse("");
-
-    // Start building our {@link Vertex} object.
-    Vertex.Builder vertexBuilder = new Vertex.Builder(type);
-    vertexBuilder.id(id.toString());
-
-    // Convert the properties associated with the Champ object into the form
-    // expected for
-    // a Vertex object.
-    for (String key : champObject.getProperties().keySet()) {
-      vertexBuilder.property(key, champObject.getProperties().get(key));
+  @Override
+  public Edge updateEdge(Edge edge) throws CrudException {
+    if (!edge.getId().isPresent()) {
+      throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST);
     }
+    String url = baseRelationshipUrl + "/" + edge.getId().get();
 
-    // ...and return it.
-    return vertexBuilder.build();
-  }
+    String edgeJson = edge.toJson(champGson);
+    OperationResult getResult = client.put(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
 
-  /**
-   * This helper method converts a {@link ChampRelationship} from the Champ
-   * library into an equivalent {@link Edge} object that is understood by the
-   * CRUD Service.
-   *
-   * @param relationship
-   *          - The ChampRelationship object to be converted.
-   * @return - An Edge object corresponding to the supplied ChampRelationship
-   */
-  private Edge edgeFromChampRelationship(ChampRelationship relationship) {
-
-    // Populate the edge's id, if available.
-    Object relationshipId = relationship.getKey().orElse("");
-
-    Edge.Builder edgeBuilder = new Edge.Builder(relationship.getType()).id(relationshipId.toString());
-    edgeBuilder.source(vertexFromChampObject(relationship.getSource(),
-        relationship.getSource().getProperties()
-            .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
-                ? relationship.getSource().getType()
-                : relationship.getSource().getProperties()
-                    .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()));
-    edgeBuilder.target(vertexFromChampObject(relationship.getTarget(),
-        relationship.getTarget().getProperties()
-            .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
-                ? relationship.getTarget().getType()
-                : relationship.getTarget().getProperties()
-                    .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()));
-
-    for (String key : relationship.getProperties().keySet()) {
-      edgeBuilder.property(key, relationship.getProperties().get(key).toString());
+    if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+      return Edge.fromJson(getResult.getResult());
+    } else {
+      // We didn't create an edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to update edge", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
-
-    return edgeBuilder.build();
   }
 
-  /**
-   * Performs any necessary shut down operations when the DAO is no longer
-   * needed.
-   */
-  public void close() {
-
-    if (champApi != null) {
-
-      logger.info(CrudServiceMsgs.STOPPING_CHAMP_DAO);
+  @Override
+  public void deleteEdge(String id, String type) throws CrudException {
+    String url = baseRelationshipUrl + "/" + id;
+    OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      champApi.shutdown();
+    if (getResult.getResultCode() != 200) {
+      // We didn't find an edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
   }
 
   @Override
   public String openTransaction() {
+    String url = baseTransactionUrl;
 
-    ChampTransaction transaction = champApi.openTransaction();
+    OperationResult getResult = client.post(url, "", createHeader(), MediaType.TEXT_PLAIN_TYPE, MediaType.TEXT_PLAIN_TYPE);
 
-    transactions.put(transaction.id(), transaction);
-    logger.info(CrudServiceMsgs.TRANSACTION, "Stored transaction " + transaction.id() + " in hashmap");
-    logger.info(CrudServiceMsgs.TRANSACTION, "Hash map contents:");
-    for (String key : transactions.keySet()) {
-      logger.info(CrudServiceMsgs.TRANSACTION, key);
+    if (getResult.getResultCode() == 200) {
+      return getResult.getResult();
+    } else {
+      return null;
     }
-    return transaction.id();
   }
 
   @Override
   public void commitTransaction(String id) throws CrudException {
+    String url = baseTransactionUrl + "/" + id;
 
-    try {
-      champApi.commitTransaction(getTransaction(id));
-    } catch (ChampTransactionException e) {
-      throw new CrudException("Error while commiting transaction " + id,
-          javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    OperationResult getResult = client.put(url, "{\"method\": \"commit\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.TEXT_PLAIN_TYPE);
+
+    if (getResult.getResultCode() != 200) {
+      throw new CrudException("Unable to commit transaction",
+          Response.Status.fromStatusCode(getResult.getResultCode()));
     }
-    transactions.remove(id);
   }
 
   @Override
   public void rollbackTransaction(String id) throws CrudException {
+    String url = baseTransactionUrl + "/" + id;
 
-    try {
-      champApi.rollbackTransaction(getTransaction(id));
-    } catch (ChampTransactionException e) {
-      throw new CrudException("Error while transaction rollback " + id,
-          javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    OperationResult getResult = client.put(url, "{\"method\": \"rollback\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.TEXT_PLAIN_TYPE);
+
+    if (getResult.getResultCode() != 200) {
+      throw new CrudException("Unable to rollback transaction",
+          Response.Status.fromStatusCode(getResult.getResultCode()));
     }
-    transactions.remove(id);
   }
 
-  private ChampTransaction getTransaction(String id) throws CrudException {
+  @Override
+  public boolean transactionExists(String id) throws CrudException {
+    String url = baseTransactionUrl + "/" + id;
+    Map<String, List<String>> headers = new HashMap<>();
+    headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+    headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
 
-    logger.info(CrudServiceMsgs.TRANSACTION, "Looking up transaction " + id);
-    if (transactions.containsKey(id)) {
-      logger.info(CrudServiceMsgs.TRANSACTION, "Found it!");
-      return (transactions.get(id));
-    } else {
-      logger.info(CrudServiceMsgs.TRANSACTION, "Didn't find transaction id " + id + ".  Hash map contains: ");
-      for (String key : transactions.keySet()) {
-        logger.info(CrudServiceMsgs.TRANSACTION, key);
-      }
-      throw new CrudException("No open transaction with id: " + id, javax.ws.rs.core.Response.Status.NOT_FOUND);
-    }
+    OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+    return getResult.getResultCode() == 200;
   }
 
   @Override
   public Vertex addVertex(String type, Map<String, Object> properties, String txId) throws CrudException {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties));
-    }
+    String url = baseObjectUrl + "?transactionId=" + txId;
 
     // Add the aai_node_type so that AAI can read the data created by gizmo
+    // TODO: This probably shouldn't be here
     properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
 
-    // Create an object to represent our vertex in the format expected by the
-    // Champ library.
-    ChampObject objectToCreate = buildChampObject(type, properties);
+    Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+    properties.forEach(insertVertexBuilder::property);
+    Vertex insertVertex = insertVertexBuilder.build();
 
-    try {
-
-      // Ask the Champ library to store our vertex, placing the returned object
-      // into a
-      // list so that we can easily put that into our result object.
-      return vertexFromChampObject(champApi.storeObject(objectToCreate, Optional.of(getTransaction(txId))), type);
+    OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
 
-    } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException
-        | ChampTransactionException e) {
-
-      // Something went wrong - throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
+      return Vertex.fromJson(getResult.getResult());
+    } else {
+      // We didn't create a vertex with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to create vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
   }
 
   @Override
   public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String txId)
       throws CrudException {
-    // For now, assume source and target are straight ids...
-    try {
-
-      Optional<ChampObject> sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()),
-          Optional.of(getTransaction(txId)));
-      if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) {
-        throw new CrudException(
-            "Error creating edge - source vertex with id " + source + " does not exist in graph data base",
-            javax.ws.rs.core.Response.Status.BAD_REQUEST);
-      }
+    String url = baseRelationshipUrl + "?transactionId=" + txId;
 
-      Optional<ChampObject> targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()),
-          Optional.of(getTransaction(txId)));
-      if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) {
-        throw new CrudException(
-            "Error creating edge - target vertex with id " + target + " does not exist in graph data base",
-            javax.ws.rs.core.Response.Status.BAD_REQUEST);
-      }
+    // Try requests to ensure source and target exist in Champ
+    Vertex dbSource = getVertex(source.getId().get(), source.getType(), txId);
+    Vertex dbTarget = getVertex(target.getId().get(), target.getType(), txId);
 
-      // Now, create the ChampRelationship object for our edge and store it in
-      // the graph database.
-      return edgeFromChampRelationship(champApi.storeRelationship(
-          new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build(),
-          Optional.of(getTransaction(txId))));
+    Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget);
+    properties.forEach(insertEdgeBuilder::property);
+    Edge insertEdge = insertEdgeBuilder.build();
 
-    } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException
-        | ChampTransactionException | ChampRelationshipNotExistsException | ChampUnmarshallingException e) {
+    OperationResult getResult = client.post(url, insertEdge.toJson(champGson), createHeader(),
+        MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
 
-      throw new CrudException("Error creating edge: " + e.getMessage(),
-          javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
+      return Edge.fromJson(getResult.getResult());
+    } else {
+      // We didn't create an edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to create edge", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
-
   }
 
   @Override
   public Vertex updateVertex(String id, String type, Map<String, Object> properties, String txId) throws CrudException {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Update vertex with id: " + id + " with properties: " + propertiesMapToString(properties));
-    }
+    String url = baseObjectUrl + "/" + id + "?transactionId=" + txId;
+
     // Add the aai_node_type so that AAI can read the data created by gizmo
+    // TODO: This probably shouldn't be here
     properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
 
-    try {
-      // Now, build the updated version of the Champ Object...
-      ChampObject updateObject = buildChampObject(id, type, properties);
-      // ...and send it to the Champ library.
-      return vertexFromChampObject(champApi.replaceObject(updateObject, Optional.of(getTransaction(txId))), type);
-
-    } catch (ChampObjectNotExistsException e) {
-      throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
-    } catch (NumberFormatException | ChampMarshallingException | ChampTransactionException
-        | ChampSchemaViolationException e) {
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
-    }
-  }
+    Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+    insertVertexBuilder.id(id);
+    properties.forEach(insertVertexBuilder::property);
+    Vertex insertVertex = insertVertexBuilder.build();
 
-  @Override
-  public boolean transactionExists(String id) throws CrudException {
-    return transactions.containsKey(id);
+    String payload = insertVertex.toJson(champGson);
+    OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
+
+    if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+      return Vertex.fromJson(getResult.getResult());
+    } else {
+      // We didn't create a vertex with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to update vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
+    }
   }
 
   @Override
   public void deleteVertex(String id, String type, String txId) throws CrudException {
-    try {
-
-      // First, retrieve the vertex that we intend to delete.
-      Optional<ChampObject> retrievedVertex = champApi.retrieveObject(Long.parseLong(id),
-          Optional.of(getTransaction(txId)));
-
-      // Did we find it?
-      if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) {
-        throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.",
-            javax.ws.rs.core.Response.Status.NOT_FOUND);
-      }
-
-      // Now, verify that there are no edges incident to the vertex (they must
-      // be deleted
-      // first if so).
-      Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get(),
-          Optional.of(getTransaction(txId)));
-
-      if (relationships.count() > 0) {
-        throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.",
-            javax.ws.rs.core.Response.Status.BAD_REQUEST);
-      }
+    String url = baseObjectUrl + "/" + id + "?transactionId=" + txId;
+    OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      // Finally, we can attempt to delete our vertex.
-      champApi.deleteObject(Long.parseLong(id), Optional.of(getTransaction(txId)));
-
-    } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException
-        | ChampTransactionException e) {
-
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() != Response.Status.OK.getStatusCode()) {
+      // We didn't delete a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("Failed to delete vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
     }
-
   }
 
   @Override
   public Edge updateEdge(Edge edge, String txId) throws CrudException {
-    if (logger.isDebugEnabled()) {
-      logger.debug(
-          "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties()));
+    if (!edge.getId().isPresent()) {
+      throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST);
     }
+    String url = baseRelationshipUrl + "/" + edge.getId().get() + "?transactionId=" + txId;
+    OperationResult getResult = client.put(url, edge.toJson(champGson), createHeader(), MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
 
-    try {
-      // Now, build the updated version of the Champ Relationship...
-      ChampRelationship updateRelationship = new ChampRelationship.Builder(
-          buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(),
-              edge.getSource().getProperties()),
-          buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(),
-              edge.getTarget().getProperties()),
-          edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build();
-      // ...and send it to the Champ library.
-      return edgeFromChampRelationship(
-          champApi.replaceRelationship(updateRelationship, Optional.of(getTransaction(txId))));
-
-    } catch (ChampRelationshipNotExistsException ex) {
-      throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
-    } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException
-        | ChampSchemaViolationException | ChampTransactionException ex) {
-
-      throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+      return Edge.fromJson(getResult.getResult());
+    } else {
+      // We didn't create an edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("Failed to update edge: " + getResult.getFailureCause(),
+          Response.Status.fromStatusCode(getResult.getResultCode()));
     }
   }
 
   @Override
   public void deleteEdge(String id, String type, String txId) throws CrudException {
-    try {
-
-      // First, retrieve the edge that we want to delete.
-      Optional<ChampRelationship> relationshipToDelete = champApi.retrieveRelationship(getRelKey(id),
-          Optional.of(getTransaction(txId)));
-
-      // Did we find it?
-      if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) {
-        throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist",
-            javax.ws.rs.core.Response.Status.NOT_FOUND);
-      }
-
-      // Now we can delete the edge.
-      champApi.deleteRelationship(relationshipToDelete.get(), Optional.of(getTransaction(txId)));
-
-    } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException
-        | ChampTransactionException e) {
+    String url = baseRelationshipUrl + "/" + id + "?transactionId=" + txId;
+    OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+    if (getResult.getResultCode() != 200) {
+      // We didn't find an edge with the supplied type, so just throw an
+      // exception.
+      throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
-
   }
 
   @Override
   public Edge getEdge(String id, String type, String txId) throws CrudException {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Get edge with id: " + id);
-    }
-
-    try {
+    String url = baseRelationshipUrl + "/" + id + "?transactionId=" + txId;
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      // Request the edge from the graph db.
-      Optional<ChampRelationship> relationship = champApi.retrieveRelationship(getRelKey(id),
-          Optional.of(getTransaction(txId)));
+    if (getResult.getResultCode() == 200) {
+      Edge edge = Edge.fromJson(getResult.getResult());
 
-      // Did we find it?
-      if (relationship.isPresent() && relationship.get().getType().equals(type)) {
+      if (!edge.getType().equalsIgnoreCase(type)) {
+        // We didn't find an edge with the supplied type, so just throw an
+        // exception.
+        throw new CrudException("No edge with id " + id + "and type " + type + " found in graph",
+            javax.ws.rs.core.Response.Status.NOT_FOUND);
+      }
+      return edge;
+    } else {
+      // We didn't find an edge with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
+    }
+  }
 
-        // Yup - return the result.
-        return edgeFromChampRelationship(relationship.get());
+  public Vertex getVertex(String id, String type, String txId) throws CrudException {
+    String url = baseObjectUrl + "/" + id + "?transactionId=" + txId;
+    OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
 
-      } else {
+    if (getResult.getResultCode() == 200) {
+      Vertex vert = Vertex.fromJson(getResult.getResult());
 
-        // We didn't find an edge with the supplied id, so throw an exception.
-        throw new CrudException("No edge with id " + id + " found in graph",
+      if (!vert.getType().equalsIgnoreCase(type)) {
+        // We didn't find a vertex with the supplied type, so just throw an
+        // exception.
+        throw new CrudException("No vertex with id " + id + "and type " + type + " found in graph",
             javax.ws.rs.core.Response.Status.NOT_FOUND);
       }
-
-    } catch (ChampUnmarshallingException | ChampTransactionException e) {
-
-      // Something went wrong, so throw an exception.
-      throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+      return vert;
+    } else {
+      // We didn't find a vertex with the supplied id, so just throw an
+      // exception.
+      throw new CrudException("No vertex with id " + id + " found in graph",
+          javax.ws.rs.core.Response.Status.NOT_FOUND);
     }
   }
 
+  // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient
+  private List<NameValuePair> convertToNameValuePair(Map<String, Object> pairs) {
+    List<NameValuePair> nvpList = new ArrayList<>(pairs.size());
+
+    pairs.forEach((key, value) -> nvpList.add(new BasicNameValuePair(key, value.toString())));
+
+    return nvpList;
+  }
+  
+  private Map<String, List<String>> createHeader() {
+    Map<String, List<String>> headers = new HashMap<>();
+    headers.put(HEADER_FROM_APP, Arrays.asList(FROM_APP_NAME));
+    headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+    return headers;
+  }
 }