You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2017/09/21 13:50:41 UTC

[7/7] nifi-registry git commit: NIFIREG-18 Initial plumbling for H2 database - Setup Flyway with initial migration to define tables - Setup entity classes with repositories - Setup unit testing for repositories - Removed existing MetadataProvider concept

NIFIREG-18 Initial plumbling for H2 database
- Setup Flyway with initial migration to define tables
- Setup entity classes with repositories
- Setup unit testing for repositories
- Removed existing MetadataProvider concept
- Removed provider impl module and moved remaining pieces into framework
- Added MetadataService with DatabaseMetadataService implementation
- Refactored RegistryService to use MetadataService
- Introduced verbose flag on some end-points to control loading nested objects
- Added ability to pass down paging/sorting params
- Added endpoints for available fields
- Adding ItemResource and ability to retrieve all items, or items by bucket
- Changing from Set to List on retrieval methods
- Added web linking in entities returned from REST end-points

This closes #10.


Project: http://git-wip-us.apache.org/repos/asf/nifi-registry/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-registry/commit/d478c20e
Tree: http://git-wip-us.apache.org/repos/asf/nifi-registry/tree/d478c20e
Diff: http://git-wip-us.apache.org/repos/asf/nifi-registry/diff/d478c20e

Branch: refs/heads/master
Commit: d478c20ee26ae6d021573dd842bb9098ed8c752d
Parents: d93eab3
Author: Bryan Bende <bb...@apache.org>
Authored: Tue Sep 19 10:01:24 2017 -0400
Committer: Bryan Bende <bb...@apache.org>
Committed: Thu Sep 21 09:50:04 2017 -0400

----------------------------------------------------------------------
 nifi-registry-assembly/pom.xml                  |   3 +
 nifi-registry-data-model/pom.xml                |   4 +
 .../org/apache/nifi/registry/bucket/Bucket.java |   9 +-
 .../apache/nifi/registry/bucket/BucketItem.java |  21 +-
 .../nifi/registry/flow/VersionedFlow.java       |  11 -
 .../flow/VersionedFlowSnapshotMetadata.java     |   3 +-
 .../apache/nifi/registry/link/LinkAdapter.java  |  67 ++
 .../nifi/registry/link/LinkableEntity.java      |  45 +
 nifi-registry-framework/pom.xml                 |  50 +-
 .../nifi/registry/db/DataSourceFactory.java     |  85 ++
 .../registry/db/DatabaseMetadataService.java    | 394 +++++++++
 .../nifi/registry/db/entity/BucketEntity.java   | 123 +++
 .../registry/db/entity/BucketItemEntity.java    | 135 +++
 .../db/entity/BucketItemEntityType.java         |  42 +
 .../nifi/registry/db/entity/FlowEntity.java     |  57 ++
 .../registry/db/entity/FlowSnapshotEntity.java  |  93 +++
 .../db/entity/FlowSnapshotEntityKey.java        |  82 ++
 .../db/repository/BucketItemRepository.java     |  84 ++
 .../db/repository/BucketRepository.java         |  31 +
 .../registry/db/repository/FlowRepository.java  |  31 +
 .../db/repository/FlowSnapshotRepository.java   |  28 +
 .../flow/StandardFlowSnapshotContext.java       | 155 ----
 .../nifi/registry/provider/ProviderFactory.java |   6 -
 .../provider/StandardProviderFactory.java       |  38 +-
 .../flow/FileSystemFlowPersistenceProvider.java | 169 ++++
 .../flow/StandardFlowSnapshotContext.java       | 157 ++++
 .../serialization/jaxb/JAXBSerializer.java      |   2 +-
 .../nifi/registry/service/DataModelMapper.java  | 131 +--
 .../nifi/registry/service/MetadataService.java  | 186 +++++
 .../nifi/registry/service/RegistryService.java  | 293 ++++---
 .../nifi/registry/service/TestService.java      |  31 -
 .../service/params/QueryParameters.java         | 109 +++
 .../nifi/registry/service/params/SortOrder.java |  47 ++
 .../registry/service/params/SortParameter.java  |  79 ++
 .../main/resources/db/migration/V1__Initial.sql |  46 ++
 .../src/main/xsd/providers.xsd                  |   1 -
 .../registry/db/RepositoryTestApplication.java  |  45 +
 .../db/repository/RepositoryBaseTest.java       |  34 +
 .../db/repository/TestBucketItemRepository.java |  98 +++
 .../db/repository/TestBucketRepository.java     | 177 ++++
 .../db/repository/TestFlowRepository.java       | 125 +++
 .../repository/TestFlowSnapshotRepository.java  | 109 +++
 .../flow/TestStandardFlowSnapshotContext.java   |  53 --
 .../registry/provider/MockMetadataProvider.java | 119 ---
 .../provider/TestStandardProviderFactory.java   |  31 -
 .../TestFileSystemFlowPersistenceProvider.java  | 204 +++++
 .../flow/TestStandardFlowSnapshotContext.java   |  55 ++
 .../registry/service/TestDataModelMapper.java   | 174 ----
 .../registry/service/TestRegistryService.java   | 828 ++++++++++---------
 .../src/test/resources/application.properties   |  19 +
 .../db/migration/V999999.1__test-setup.sql      |  64 ++
 .../provider/providers-class-not-found.xml      |   6 -
 .../test/resources/provider/providers-good.xml  |   6 -
 .../properties/NiFiRegistryProperties.java      |  12 +
 .../nifi/registry/metadata/BucketMetadata.java  |  51 --
 .../nifi/registry/metadata/FlowMetadata.java    |  69 --
 .../registry/metadata/FlowSnapshotMetadata.java |  54 --
 .../registry/metadata/MetadataProvider.java     | 158 ----
 .../metadata/MetadataProviderException.java     |  35 -
 .../metadata/StandardBucketMetadata.java        | 131 ---
 .../registry/metadata/StandardFlowMetadata.java | 174 ----
 .../metadata/StandardFlowSnapshotMetadata.java  | 136 ---
 nifi-registry-provider-impl/pom.xml             |  94 ---
 .../flow/FileSystemFlowPersistenceProvider.java | 166 ----
 .../metadata/FileSystemMetadataProvider.java    | 469 -----------
 .../nifi/registry/metadata/MetadataHolder.java  | 176 ----
 .../src/main/xsd/metadata.xsd                   | 139 ----
 .../TestFileSystemFlowPersistenceProvider.java  | 202 -----
 .../TestFileSystemMetadataProvider.java         | 549 ------------
 .../metadata/metadata-empty-concise.xml         |  16 -
 .../test/resources/metadata/metadata-empty.xml  |  17 -
 .../resources/metadata/metadata-existing.xml    |  35 -
 .../src/main/resources/conf/logback.xml         |   5 +
 .../resources/conf/nifi-registry.properties     |  10 +-
 .../src/main/resources/conf/providers.xml       |   7 +-
 nifi-registry-web-api/pom.xml                   |  12 +-
 .../registry/NiFiRegistryApiApplication.java    |  54 ++
 .../registry/NiFiRegistryPropertiesFactory.java |  47 ++
 .../web/NiFiRegistryApiApplication.java         |  44 -
 .../web/NiFiRegistryPropertiesFactory.java      |  46 --
 .../web/NiFiRegistryResourceConfig.java         |   6 +-
 .../nifi/registry/web/api/BucketResource.java   |  55 +-
 .../nifi/registry/web/api/FlowResource.java     |  70 +-
 .../nifi/registry/web/api/ItemResource.java     | 125 +++
 .../nifi/registry/web/api/TestResource.java     |  55 --
 .../nifi/registry/web/link/LinkService.java     | 110 +++
 .../web/link/builder/BucketLinkBuilder.java     |  45 +
 .../registry/web/link/builder/LinkBuilder.java  |  30 +
 .../link/builder/VersionedFlowLinkBuilder.java  |  45 +
 .../VersionedFlowSnapshotLinkBuilder.java       |  46 ++
 .../registry/web/response/FieldsEntity.java     |  37 +
 .../nifi/registry/web/response/TestEntity.java  |  31 -
 .../apache/nifi/registry/web/TestRestAPI.java   |  78 +-
 .../nifi/registry/web/link/TestLinkService.java | 119 +++
 .../src/main/webapp/WEB-INF/web.xml             |   1 +
 pom.xml                                         |  30 +-
 96 files changed, 4631 insertions(+), 4155 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-assembly/pom.xml b/nifi-registry-assembly/pom.xml
index b2403de..7ed4ff0 100644
--- a/nifi-registry-assembly/pom.xml
+++ b/nifi-registry-assembly/pom.xml
@@ -140,5 +140,8 @@
         <!-- nifi-registry.properties: provider properties -->
         <nifi.registry.providers.configuration.file>./conf/providers.xml</nifi.registry.providers.configuration.file>
 
+        <!-- nifi-registry.properties: database properties -->
+        <nifi.registry.db.directory>./database</nifi.registry.db.directory>
+        <nifi.registry.db.url.append>;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE</nifi.registry.db.url.append>
     </properties>
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/pom.xml b/nifi-registry-data-model/pom.xml
index 438fe01..3b6d4b1 100644
--- a/nifi-registry-data-model/pom.xml
+++ b/nifi-registry-data-model/pom.xml
@@ -30,5 +30,9 @@
             <groupId>javax.validation</groupId>
             <artifactId>validation-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
index 9928cd8..314598e 100644
--- a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
+++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
@@ -18,6 +18,7 @@ package org.apache.nifi.registry.bucket;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import org.apache.nifi.registry.link.LinkableEntity;
 import org.apache.nifi.registry.flow.VersionedFlow;
 
 import javax.validation.Valid;
@@ -29,7 +30,7 @@ import java.util.Set;
 
 @XmlRootElement
 @ApiModel(value = "bucket")
-public class Bucket {
+public class Bucket extends LinkableEntity {
 
     @NotBlank
     private String identifier;
@@ -46,7 +47,7 @@ public class Bucket {
     private Set<VersionedFlow> versionedFlows;
 
 
-    @ApiModelProperty("The id of the bucket. This is set by the server at creation time.")
+    @ApiModelProperty("An ID to uniquely identify this object.")
     public String getIdentifier() {
         return identifier;
     }
@@ -93,7 +94,7 @@ public class Bucket {
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(this.identifier);
+        return Objects.hashCode(this.getIdentifier());
     }
 
     @Override
@@ -106,7 +107,7 @@ public class Bucket {
         }
 
         final Bucket other = (Bucket) obj;
-        return Objects.equals(this.identifier, other.identifier);
+        return Objects.equals(this.getIdentifier(), other.getIdentifier());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/BucketItem.java
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/BucketItem.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/BucketItem.java
index d57f07b..cb55664 100644
--- a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/BucketItem.java
+++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/BucketItem.java
@@ -18,6 +18,7 @@ package org.apache.nifi.registry.bucket;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import org.apache.nifi.registry.link.LinkableEntity;
 
 import javax.validation.constraints.Min;
 import javax.validation.constraints.NotBlank;
@@ -25,7 +26,7 @@ import javax.validation.constraints.NotNull;
 import java.util.Objects;
 
 @ApiModel("bucketItem")
-public abstract class BucketItem {
+public abstract class BucketItem extends LinkableEntity {
 
     @NotBlank
     private String identifier;
@@ -33,6 +34,8 @@ public abstract class BucketItem {
     @NotBlank
     private String name;
 
+    private String description;
+
     @NotBlank
     private String bucketIdentifier;
 
@@ -45,11 +48,11 @@ public abstract class BucketItem {
     @NotNull
     private final BucketItemType type;
 
+
     public BucketItem(final BucketItemType type) {
         this.type = type;
     }
 
-
     @ApiModelProperty("An ID to uniquely identify this object.")
     public String getIdentifier() {
         return identifier;
@@ -68,6 +71,16 @@ public abstract class BucketItem {
         this.name = name;
     }
 
+    @ApiModelProperty("A description of the item.")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+
     @ApiModelProperty("The identifier of the bucket this items belongs to.")
     public String getBucketIdentifier() {
         return bucketIdentifier;
@@ -102,7 +115,7 @@ public abstract class BucketItem {
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(this.identifier);
+        return Objects.hashCode(this.getIdentifier());
     }
 
     @Override
@@ -115,6 +128,6 @@ public abstract class BucketItem {
         }
 
         final BucketItem other = (BucketItem) obj;
-        return Objects.equals(this.identifier, other.identifier);
+        return Objects.equals(this.getIdentifier(), other.getIdentifier());
     }
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
index 8bbb040..b70f6be 100644
--- a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
+++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlow.java
@@ -38,8 +38,6 @@ import java.util.SortedSet;
 @ApiModel(value = "versionedFlow")
 public class VersionedFlow extends BucketItem {
 
-    private String description;
-
     @Valid
     private SortedSet<VersionedFlowSnapshotMetadata> snapshotMetadata;
 
@@ -47,15 +45,6 @@ public class VersionedFlow extends BucketItem {
         super(BucketItemType.FLOW);
     }
 
-    @ApiModelProperty("A description of the flow.")
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
     @ApiModelProperty(value = "The metadata for each snapshot of this flow.", readOnly = true)
     public SortedSet<VersionedFlowSnapshotMetadata> getSnapshotMetadata() {
         return snapshotMetadata;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
index e60dcfd..36a4cf9 100644
--- a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
+++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshotMetadata.java
@@ -18,6 +18,7 @@ package org.apache.nifi.registry.flow;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import org.apache.nifi.registry.link.LinkableEntity;
 
 import javax.validation.constraints.Min;
 import javax.validation.constraints.NotBlank;
@@ -28,7 +29,7 @@ import java.util.Objects;
  * to sort based on the snapshot version in ascending order.
  */
 @ApiModel(value = "versionedFlowSnapshot")
-public class VersionedFlowSnapshotMetadata implements Comparable<VersionedFlowSnapshotMetadata> {
+public class VersionedFlowSnapshotMetadata extends LinkableEntity implements Comparable<VersionedFlowSnapshotMetadata> {
 
     @NotBlank
     private String bucketIdentifier;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java
new file mode 100644
index 0000000..c3dae90
--- /dev/null
+++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkAdapter.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.link;
+
+import javax.ws.rs.core.Link;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.namespace.QName;
+import java.util.Map;
+
+/**
+ * This class is a modified version of Jersey's Link.JaxbAdapter that adds protection against nulls.
+ */
+public class LinkAdapter extends XmlAdapter<Link.JaxbLink, Link> {
+
+    /**
+     * Convert a {@link Link.JaxbLink} into a {@link Link}.
+     *
+     * @param v instance of type {@link Link.JaxbLink}.
+     * @return mapped instance of type {@link Link.JaxbLink}
+     */
+    @Override
+    public Link unmarshal(Link.JaxbLink v) {
+        if (v == null) {
+            return null;
+        }
+
+        Link.Builder lb = Link.fromUri(v.getUri());
+        for (Map.Entry<QName, Object> e : v.getParams().entrySet()) {
+            lb.param(e.getKey().getLocalPart(), e.getValue().toString());
+        }
+        return lb.build();
+    }
+
+    /**
+     * Convert a {@link Link} into a {@link Link.JaxbLink}.
+     *
+     * @param v instance of type {@link Link}.
+     * @return mapped instance of type {@link Link.JaxbLink}.
+     */
+    @Override
+    public Link.JaxbLink marshal(Link v) {
+        if (v == null) {
+           return null;
+        }
+
+        Link.JaxbLink jl = new Link.JaxbLink(v.getUri());
+        for (Map.Entry<String, String> e : v.getParams().entrySet()) {
+            final String name = e.getKey();
+            jl.getParams().put(new QName("", name), e.getValue());
+        }
+        return jl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java
----------------------------------------------------------------------
diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java
new file mode 100644
index 0000000..896e9d3
--- /dev/null
+++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/link/LinkableEntity.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.link;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.ws.rs.core.Link;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+/**
+ * Base classes for domain objects that want to provide a hypermedia link.
+ */
+@ApiModel("linkableEntity")
+public abstract class LinkableEntity {
+
+    private Link link;
+
+    @XmlElement
+    @XmlJavaTypeAdapter(LinkAdapter.class)
+    @ApiModelProperty(value = "An WebLink to this entity.", readOnly = true)
+    public Link getLink() {
+        return link;
+    }
+
+    public void setLink(Link link) {
+        this.link = link;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/pom.xml b/nifi-registry-framework/pom.xml
index 7ad7468..8b708d2 100644
--- a/nifi-registry-framework/pom.xml
+++ b/nifi-registry-framework/pom.xml
@@ -72,20 +72,17 @@
         </dependency>
         <dependency>
             <groupId>org.apache.nifi.registry</groupId>
-            <artifactId>nifi-registry-properties</artifactId>
+            <artifactId>nifi-registry-utils</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-beans</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-core</artifactId>
+            <groupId>org.apache.nifi.registry</groupId>
+            <artifactId>nifi-registry-properties</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
         </dependency>
         <dependency>
             <groupId>org.hibernate</groupId>
@@ -95,8 +92,43 @@
             <groupId>org.glassfish</groupId>
             <artifactId>javax.el</artifactId>
         </dependency>
+        <!-- Database related dependencies, spring-boot-starter-data-jpa also brings in the standard Spring
+             dependencies for the backend to define beans -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <version>${spring.boot.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-jdbc</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-core</artifactId>
+            <version>${flyway.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <version>1.4.196</version>
+        </dependency>
         <!-- Test Dependencies -->
         <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <version>${spring.boot.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb.flyway-test-extensions</groupId>
+            <artifactId>flyway-spring-test</artifactId>
+            <version>${flyway.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>4.12</version>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DataSourceFactory.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DataSourceFactory.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DataSourceFactory.java
new file mode 100644
index 0000000..5ec2043
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DataSourceFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.properties.NiFiRegistryProperties;
+import org.h2.jdbcx.JdbcConnectionPool;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import javax.sql.DataSource;
+import java.io.File;
+
+/**
+ * Overriding Spring Boot's normal automatic creation of a DataSource in order to use the properties
+ * from NiFiRegistryProperties rather than the standard application.properties/yaml.
+ */
+@Configuration
+public class DataSourceFactory {
+
+    private static final String DB_USERNAME_PASSWORD = "nifireg";
+    private static final int MAX_CONNECTIONS = 5;
+
+    // database file name
+    private static final String DATABASE_FILE_NAME = "nifi-registry";
+
+    private final NiFiRegistryProperties properties;
+
+    private JdbcConnectionPool connectionPool;
+
+    @Autowired
+    public DataSourceFactory(final NiFiRegistryProperties properties) {
+        this.properties = properties;
+    }
+
+    @Bean
+    @Primary
+    public DataSource getDataSource() {
+        if (connectionPool == null) {
+            // locate the repository directory
+            final String repositoryDirectoryPath = properties.getDatabaseDirectory();
+
+            // ensure the repository directory is specified
+            if (repositoryDirectoryPath == null) {
+                throw new NullPointerException("Database directory must be specified.");
+            }
+
+            // create a handle to the repository directory
+            final File repositoryDirectory = new File(repositoryDirectoryPath);
+
+            // get a handle to the database file
+            final File databaseFile = new File(repositoryDirectory, DATABASE_FILE_NAME);
+
+            // format the database url
+            String databaseUrl = "jdbc:h2:" + databaseFile + ";AUTOCOMMIT=OFF;DB_CLOSE_ON_EXIT=FALSE;LOCK_MODE=3";
+            String databaseUrlAppend = properties.getDatabaseUrlAppend();
+            if (StringUtils.isNotBlank(databaseUrlAppend)) {
+                databaseUrl += databaseUrlAppend;
+            }
+
+            // create the pool
+            connectionPool = JdbcConnectionPool.create(databaseUrl, DB_USERNAME_PASSWORD, DB_USERNAME_PASSWORD);
+            connectionPool.setMaxConnections(MAX_CONNECTIONS);
+        }
+
+        return connectionPool;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
new file mode 100644
index 0000000..35c6b55
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.nifi.registry.db.entity.BucketEntity;
+import org.apache.nifi.registry.db.entity.BucketItemEntity;
+import org.apache.nifi.registry.db.entity.FlowEntity;
+import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
+import org.apache.nifi.registry.db.entity.FlowSnapshotEntityKey;
+import org.apache.nifi.registry.db.repository.BucketItemRepository;
+import org.apache.nifi.registry.db.repository.BucketRepository;
+import org.apache.nifi.registry.db.repository.FlowRepository;
+import org.apache.nifi.registry.db.repository.FlowSnapshotRepository;
+import org.apache.nifi.registry.service.MetadataService;
+import org.apache.nifi.registry.service.params.QueryParameters;
+import org.apache.nifi.registry.service.params.SortOrder;
+import org.apache.nifi.registry.service.params.SortParameter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.EntityManager;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.Metamodel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * A MetadataProvider backed by the embedded relational database. All database access should occur through this class,
+ * other services should not directly use the repositories.
+ */
+@Service
+public class DatabaseMetadataService implements MetadataService {
+
+    private final BucketRepository bucketRepository;
+    private final FlowRepository flowRepository;
+    private final FlowSnapshotRepository flowSnapshotRepository;
+    private final BucketItemRepository itemRepository;
+    private final EntityManager entityManager;
+
+    private final Set<String> bucketFields;
+    private final Set<String> bucketItemFields;
+    private final Set<String> flowFields;
+
+    @Autowired
+    public DatabaseMetadataService(final BucketRepository bucketRepository,
+                                   final FlowRepository flowRepository,
+                                   final FlowSnapshotRepository flowSnapshotRepository,
+                                   final BucketItemRepository itemRepository,
+                                   final EntityManager entityManager) {
+        this.bucketRepository = bucketRepository;
+        this.flowRepository = flowRepository;
+        this.flowSnapshotRepository = flowSnapshotRepository;
+        this.itemRepository = itemRepository;
+        this.entityManager = entityManager;
+
+        Validate.notNull(this.bucketRepository);
+        Validate.notNull(this.flowRepository);
+        Validate.notNull(this.flowSnapshotRepository);
+        Validate.notNull(this.itemRepository);
+        Validate.notNull(this.entityManager);
+
+        this.bucketFields = Collections.unmodifiableSet(getEntityFields(BucketEntity.class));
+        this.bucketItemFields = Collections.unmodifiableSet(getEntityFields(BucketItemEntity.class));
+        this.flowFields = Collections.unmodifiableSet(getEntityFields(FlowEntity.class));
+    }
+
+    private Set<String> getEntityFields(Class<?> clazz) {
+        final Metamodel metamodel = entityManager.getMetamodel();
+        final ManagedType<?> bucketEntityManagedType = metamodel.managedType(clazz);
+        return bucketEntityManagedType.getSingularAttributes().stream().map(s -> s.getName()).collect(Collectors.toSet());
+    }
+
+    // ------------------------------------------------------------------------------------
+
+    @Override
+    public BucketEntity createBucket(final BucketEntity bucket) {
+        bucket.setCreated(new Date());
+        return bucketRepository.save(bucket);
+    }
+
+    @Override
+    public BucketEntity getBucketById(final String bucketIdentifier) {
+        return bucketRepository.findOne(bucketIdentifier);
+    }
+
+    @Override
+    public List<BucketEntity> getBucketsByName(final String name) {
+        List<BucketEntity> buckets = new ArrayList<>();
+
+        final Iterable<BucketEntity> retrievedBuckets = bucketRepository.findByNameIgnoreCase(name);
+        if (retrievedBuckets != null) {
+            for (BucketEntity bucket : retrievedBuckets) {
+                buckets.add(bucket);
+            }
+        }
+
+        return buckets;
+    }
+
+    @Override
+    public BucketEntity updateBucket(final BucketEntity bucket) {
+        return bucketRepository.save(bucket);
+    }
+
+    @Override
+    public void deleteBucket(final BucketEntity bucketEntity) {
+        bucketRepository.delete(bucketEntity);
+    }
+
+    @Override
+    public List<BucketEntity> getBuckets(final QueryParameters params) {
+        if (params.getNumRows() != null && params.getPageNum() != null) {
+            return getPagedBuckets(params);
+        } else if (params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+            return getSortedBuckets(params);
+        } else {
+            return getAllBuckets();
+        }
+    }
+
+    private List<BucketEntity> getAllBuckets() {
+        final List<BucketEntity> buckets = new ArrayList<>();
+        for (BucketEntity bucket : bucketRepository.findAll()) {
+            buckets.add(bucket);
+        }
+        return buckets;
+    }
+
+    private List<BucketEntity> getPagedBuckets(final QueryParameters params) {
+        final Pageable pageable = getPageRequest(params);
+        final List<BucketEntity> buckets = new ArrayList<>();
+        for (BucketEntity bucket : bucketRepository.findAll(pageable)) {
+            buckets.add(bucket);
+        }
+        return buckets;
+    }
+
+    private List<BucketEntity> getSortedBuckets(final QueryParameters params) {
+        final Sort sort = getSort(params);
+        final List<BucketEntity> buckets = new ArrayList<>();
+        for (BucketEntity bucket : bucketRepository.findAll(sort)) {
+            buckets.add(bucket);
+        }
+        return buckets;
+    }
+
+    // ------------------------------------------------------------------------------------
+
+    @Override
+    public List<BucketItemEntity> getBucketItems(final QueryParameters params) {
+        if (params.getNumRows() != null && params.getPageNum() != null) {
+            return getPagedBucketItems(params);
+        } else if (params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+            return getSortedBucketItems(params);
+        } else {
+            return getAllBucketItems();
+        }
+    }
+
+    private List<BucketItemEntity> getAllBucketItems() {
+        final List<BucketItemEntity> bucketItems = new ArrayList<>();
+        for (BucketItemEntity item : itemRepository.findAll()) {
+            bucketItems.add(item);
+        }
+        return bucketItems;
+    }
+
+    private List<BucketItemEntity> getPagedBucketItems(final QueryParameters params) {
+        final Pageable pageable = getPageRequest(params);
+        final List<BucketItemEntity> items = new ArrayList<>();
+        for (BucketItemEntity item : itemRepository.findAll(pageable)) {
+            items.add(item);
+        }
+        return items;
+    }
+
+    private List<BucketItemEntity> getSortedBucketItems(final QueryParameters params) {
+        final Sort sort = getSort(params);
+        final List<BucketItemEntity> items = new ArrayList<>();
+        for (BucketItemEntity item : itemRepository.findAll(sort)) {
+            items.add(item);
+        }
+        return items;
+    }
+
+    // ------------------------------------------------------------------------------------
+
+    @Override
+    public List<BucketItemEntity> getBucketItems(final QueryParameters params, final BucketEntity bucket) {
+        if (params.getNumRows() != null && params.getPageNum() != null) {
+            return getPagedBucketItems(params, bucket);
+        } else if (params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+            return getSortedBucketItems(params, bucket);
+        } else {
+            return getBucketItems(bucket);
+        }
+    }
+
+    private List<BucketItemEntity> getBucketItems(final BucketEntity bucket) {
+        final List<BucketItemEntity> bucketItems = new ArrayList<>();
+        for (BucketItemEntity item : itemRepository.findByBucket(bucket)) {
+            bucketItems.add(item);
+        }
+        return bucketItems;
+    }
+
+    private List<BucketItemEntity> getPagedBucketItems(final QueryParameters params, final BucketEntity bucket) {
+        final Pageable pageable = getPageRequest(params);
+        final List<BucketItemEntity> items = new ArrayList<>();
+        for (BucketItemEntity item : itemRepository.findByBucket(bucket, pageable)) {
+            items.add(item);
+        }
+        return items;
+    }
+
+    private List<BucketItemEntity> getSortedBucketItems(final QueryParameters params, final BucketEntity bucket) {
+        final Sort sort = getSort(params);
+        final List<BucketItemEntity> items = new ArrayList<>();
+        for (BucketItemEntity item : itemRepository.findByBucket(bucket, sort)) {
+            items.add(item);
+        }
+        return items;
+    }
+
+    // ------------------------------------------------------------------------------------
+
+    @Override
+    public FlowEntity createFlow(final FlowEntity flow) {
+        flow.setCreated(new Date());
+        flow.setModified(new Date());
+        return flowRepository.save(flow);
+    }
+
+    @Override
+    public FlowEntity getFlowById(final String flowIdentifier) {
+        return flowRepository.findOne(flowIdentifier);
+    }
+
+    @Override
+    public List<FlowEntity> getFlowsByName(final String name) {
+        List<FlowEntity> flows = new ArrayList<>();
+
+        final Iterable<FlowEntity> retrievedFlows = flowRepository.findByNameIgnoreCase(name);
+        if (retrievedFlows != null) {
+            for (FlowEntity flow : retrievedFlows) {
+                flows.add(flow);
+            }
+        }
+
+        return flows;
+    }
+
+    @Override
+    public FlowEntity updateFlow(final FlowEntity flow) {
+        flow.setModified(new Date());
+        return flowRepository.save(flow);
+    }
+
+    @Override
+    public void deleteFlow(final FlowEntity flow) {
+        flowRepository.delete(flow);
+    }
+
+    @Override
+    public List<FlowEntity> getFlows(final QueryParameters params) {
+        if (params.getNumRows() != null && params.getPageNum() != null) {
+            return getPagedFlows(params);
+        } else if (params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+            return getSortedFlows(params);
+        } else {
+            return getAllFlows();
+        }
+    }
+
+    private List<FlowEntity> getAllFlows() {
+        final List<FlowEntity> flows = new ArrayList<>();
+        for (FlowEntity flowEntity : flowRepository.findAll()) {
+            flows.add(flowEntity);
+        }
+        return flows;
+    }
+
+    private List<FlowEntity> getPagedFlows(final QueryParameters params) {
+        final Pageable pageable = getPageRequest(params);
+        final List<FlowEntity> flows = new ArrayList<>();
+        for (FlowEntity flowEntity : flowRepository.findAll(pageable)) {
+            flows.add(flowEntity);
+        }
+        return flows;
+    }
+
+    private List<FlowEntity> getSortedFlows(final QueryParameters params) {
+        final Sort sort = getSort(params);
+        final List<FlowEntity> flows = new ArrayList<>();
+        for (FlowEntity flowEntity : flowRepository.findAll(sort)) {
+            flows.add(flowEntity);
+        }
+        return flows;
+    }
+
+    // ------------------------------------------------------------------------------------
+
+    @Override
+    public FlowSnapshotEntity createFlowSnapshot(final FlowSnapshotEntity flowSnapshot) {
+        flowSnapshot.setCreated(new Date());
+        return flowSnapshotRepository.save(flowSnapshot);
+    }
+
+    @Override
+    public FlowSnapshotEntity getFlowSnapshot(final String flowIdentifier, final Integer version) {
+        final FlowSnapshotEntityKey key = new FlowSnapshotEntityKey(flowIdentifier, version);
+        return flowSnapshotRepository.findOne(key);
+    }
+
+    @Override
+    public void deleteFlowSnapshot(final FlowSnapshotEntity flowSnapshot) {
+        flowSnapshotRepository.delete(flowSnapshot);
+    }
+
+    @Override
+    public Set<String> getBucketFields() {
+        return bucketFields;
+    }
+
+    @Override
+    public Set<String> getBucketItemFields() {
+        return bucketItemFields;
+    }
+
+    @Override
+    public Set<String> getFlowFields() {
+        return flowFields;
+    }
+
+    /**
+     * Converts the registry query parameters to Spring Data's PageRequest.
+     *
+     * @param parameters the registry query parameters
+     * @return the equivalent Pageable
+     */
+    private Pageable getPageRequest(final QueryParameters parameters) {
+        final Sort sort = getSort(parameters);
+        if (sort == null) {
+            return new PageRequest(parameters.getPageNum(), parameters.getNumRows());
+        } else {
+            return new PageRequest(parameters.getPageNum(), parameters.getNumRows(), sort);
+        }
+    }
+
+    /**
+     * Converts the registry sort parameters to Spring Data's Sort.
+     *
+     * @param parameters the registry query parameters
+     * @return the equivalent Sort
+     */
+    private Sort getSort(final QueryParameters parameters) {
+        final List<Sort.Order> orders = new ArrayList<>();
+
+        for (SortParameter sortParameter : parameters.getSortParameters()) {
+            final Sort.Direction direction = sortParameter.getOrder() == SortOrder.ASC ? Sort.Direction.ASC : Sort.Direction.DESC;
+            final Sort.Order order = new Sort.Order(direction, sortParameter.getFieldName());
+            orders.add(order);
+        }
+
+        if (orders.isEmpty()) {
+            return null;
+        } else {
+            return new Sort(orders);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java
new file mode 100644
index 0000000..539dc65
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.entity;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
+
+@Entity
+@Table(name = "BUCKET")
+public class BucketEntity {
+
+    @Id
+    private String id;
+
+    private String name;
+
+    private String description;
+
+    private Date created;
+
+    @OneToMany(
+            mappedBy = "bucket",
+            cascade = CascadeType.ALL,
+            orphanRemoval = true
+    )
+    private Set<BucketItemEntity> items;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Date getCreated() {
+        return created;
+    }
+
+    public void setCreated(Date created) {
+        this.created = created;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Set<BucketItemEntity> getItems() {
+        return items;
+    }
+
+    public void setItems(Set<BucketItemEntity> items) {
+        this.items = items;
+    }
+
+    /**
+     * Convenience method to obtain all FlowEntity objects from the items set.
+     *
+     * @return a set of FlowEntities
+     */
+    public Set<FlowEntity> getFlows() {
+        final Set<FlowEntity> flows = new LinkedHashSet<>();
+        for (final BucketItemEntity itemEntity : getItems()) {
+            if (BucketItemEntityType.FLOW == itemEntity.getType()) {
+                flows.add((FlowEntity) itemEntity);
+            }
+        }
+        return flows;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(this.id);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        final BucketEntity other = (BucketEntity) obj;
+        return Objects.equals(this.id, other.id);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntity.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntity.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntity.java
new file mode 100644
index 0000000..7bdf4cf
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntity.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.entity;
+
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorColumn;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import java.util.Date;
+import java.util.Objects;
+
+@Entity
+@Table(name = "BUCKET_ITEM")
+@Inheritance(strategy = InheritanceType.JOINED)
+@DiscriminatorColumn(name = "ITEM_TYPE")
+public class BucketItemEntity {
+
+    @Id
+    private String id;
+
+    private String name;
+
+    private String description;
+
+    private Date created;
+
+    private Date modified;
+
+    // NOTE: sub-classes should ensure that the type is set appropriately by overriding the getter/setter
+
+    @Column(name = "ITEM_TYPE", nullable = false, insertable = false, updatable = false)
+    @Enumerated(EnumType.STRING)
+    private BucketItemEntityType type;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "BUCKET_ID")
+    private BucketEntity bucket;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Date getCreated() {
+        return created;
+    }
+
+    public void setCreated(Date created) {
+        this.created = created;
+    }
+
+    public Date getModified() {
+        return modified;
+    }
+
+    public void setModified(Date modified) {
+        this.modified = modified;
+    }
+
+    public BucketItemEntityType getType() {
+        return type;
+    }
+
+    public void setType(BucketItemEntityType type) {
+        this.type = type;
+    }
+
+    public BucketEntity getBucket() {
+        return bucket;
+    }
+
+    public void setBucket(BucketEntity bucket) {
+        this.bucket = bucket;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(this.id);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        final BucketItemEntity other = (BucketItemEntity) obj;
+        return Objects.equals(this.id, other.id);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntityType.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntityType.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntityType.java
new file mode 100644
index 0000000..e78b2b1
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketItemEntityType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.entity;
+
+/**
+ * Possible types of BucketItemEntity.
+ */
+public enum BucketItemEntityType {
+
+    FLOW(Values.FLOW);
+
+    private final String value;
+
+    BucketItemEntityType(final String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+
+    // need these constants to reference from @DiscriminatorValue
+    public static class Values {
+        public static final String FLOW = "FLOW";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowEntity.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowEntity.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowEntity.java
new file mode 100644
index 0000000..84d2ab4
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowEntity.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.entity;
+
+import javax.persistence.CascadeType;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Set;
+
+@Entity
+@Table(name = "FLOW")
+@DiscriminatorValue(value = BucketItemEntityType.Values.FLOW)
+public class FlowEntity extends BucketItemEntity {
+
+    @OneToMany(
+            mappedBy = "flow",
+            cascade = CascadeType.ALL,
+            orphanRemoval = true
+    )
+    private Set<FlowSnapshotEntity> snapshots;
+
+    public FlowEntity() {
+        setType(BucketItemEntityType.FLOW);
+    }
+
+    public Set<FlowSnapshotEntity> getSnapshots() {
+        return snapshots;
+    }
+
+    public void setSnapshots(Set<FlowSnapshotEntity> snapshots) {
+        this.snapshots = snapshots;
+    }
+
+    @Override
+    public void setType(BucketItemEntityType type) {
+        if (BucketItemEntityType.FLOW != type) {
+            throw new IllegalStateException("Must set type to FLOW");
+        }
+        super.setType(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntity.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntity.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntity.java
new file mode 100644
index 0000000..de30845
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntity.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.entity;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import java.util.Date;
+import java.util.Objects;
+
+@Entity
+@Table(name = "FLOW_SNAPSHOT")
+public class FlowSnapshotEntity {
+
+    @EmbeddedId
+    private FlowSnapshotEntityKey id;
+
+    private Date created;
+
+    private String comments;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "FLOW_ID", insertable = false, updatable = false)
+    private FlowEntity flow;
+
+    public FlowSnapshotEntityKey getId() {
+        return id;
+    }
+
+    public void setId(FlowSnapshotEntityKey id) {
+        this.id = id;
+    }
+
+    public Date getCreated() {
+        return created;
+    }
+
+    public void setCreated(Date created) {
+        this.created = created;
+    }
+
+    public String getComments() {
+        return comments;
+    }
+
+    public void setComments(String comments) {
+        this.comments = comments;
+    }
+
+    public FlowEntity getFlow() {
+        return flow;
+    }
+
+    public void setFlow(FlowEntity flow) {
+        this.flow = flow;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(this.id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+
+        if (!(obj instanceof FlowSnapshotEntity)) {
+            return false;
+        }
+
+        final FlowSnapshotEntity other = (FlowSnapshotEntity) obj;
+        return Objects.equals(this.id, other.id);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntityKey.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntityKey.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntityKey.java
new file mode 100644
index 0000000..679932c
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotEntityKey.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * Composite Key for FlowSnapshotEntity made up of the flow id and the snapshot version.
+ */
+@Embeddable
+public class FlowSnapshotEntityKey implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Column(name = "FLOW_ID")
+    private String flowId;
+
+    @Column(name = "VERSION")
+    private Integer version;
+
+    public FlowSnapshotEntityKey() {
+
+    }
+
+    public FlowSnapshotEntityKey(String flowId, Integer version) {
+        this.flowId = flowId;
+        this.version = version;
+    }
+
+    public String getFlowId() {
+        return flowId;
+    }
+
+    public void setFlowId(String flowId) {
+        this.flowId = flowId;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(flowId, version);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+
+        if (!(obj instanceof FlowSnapshotEntityKey)) {
+            return false;
+        }
+
+        final FlowSnapshotEntityKey other = (FlowSnapshotEntityKey) obj;
+        return Objects.equals(this.flowId, other.flowId) && Objects.equals(this.version, other.version);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketItemRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketItemRepository.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketItemRepository.java
new file mode 100644
index 0000000..85d98ad
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketItemRepository.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.repository;
+
+import org.apache.nifi.registry.db.entity.BucketEntity;
+import org.apache.nifi.registry.db.entity.BucketItemEntity;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.repository.Repository;
+
+import java.util.List;
+
+/**
+ * Repository for BucketItems that exposes only the methods from PagingAndSortingRepository.
+ *
+ * There should be no CRUD methods performed directly on BucketItems, only general retrieval.
+ */
+public interface BucketItemRepository extends Repository<BucketItemEntity,String> {
+
+    /**
+     * Returns all instances of the type.
+     *
+     * @return all entities
+     */
+    Iterable<BucketItemEntity> findAll();
+
+    /**
+     * Returns all entities sorted by the given options.
+     *
+     * @param sort the sort params
+     * @return all entities sorted by the given options
+     */
+    Iterable<BucketItemEntity> findAll(Sort sort);
+
+    /**
+     * Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
+     *
+     * @param pageable the pageable params
+     * @return a page of entities
+     */
+    Page<BucketItemEntity> findAll(Pageable pageable);
+
+    /**
+     * Find all items by bucket.
+     *
+     * @param bucket the bucket to find items for
+     * @return the list of items for the bucket
+     */
+    List<BucketItemEntity> findByBucket(BucketEntity bucket);
+
+    /**
+     * Find all items by bucket with sorting.
+     *
+     * @param bucket the bucket to find items for
+     * @param sort the sort params
+     * @return the list of items for the bucket
+     */
+    List<BucketItemEntity> findByBucket(BucketEntity bucket, Sort sort);
+
+    /**
+     * Find all items by bucket with paging/sorting.
+     *
+     * @param bucket the bucket to find items for
+     * @param pageable the pageable params
+     * @return the list of items for the bucket based on the pageable params
+     */
+    List<BucketItemEntity> findByBucket(BucketEntity bucket, Pageable pageable);
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketRepository.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketRepository.java
new file mode 100644
index 0000000..e917c2d
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/BucketRepository.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.repository;
+
+import org.apache.nifi.registry.db.entity.BucketEntity;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * Spring Data Repository for BucketEntity.
+ */
+public interface BucketRepository extends PagingAndSortingRepository<BucketEntity,String> {
+
+    List<BucketEntity> findByNameIgnoreCase(String name);
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowRepository.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowRepository.java
new file mode 100644
index 0000000..ac20f81
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowRepository.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.repository;
+
+import org.apache.nifi.registry.db.entity.FlowEntity;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * Spring Data Repository for FlowEntity.
+ */
+public interface FlowRepository extends PagingAndSortingRepository<FlowEntity,String> {
+
+    List<FlowEntity> findByNameIgnoreCase(String name);
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowSnapshotRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowSnapshotRepository.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowSnapshotRepository.java
new file mode 100644
index 0000000..1b3917d
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/repository/FlowSnapshotRepository.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db.repository;
+
+import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
+import org.apache.nifi.registry.db.entity.FlowSnapshotEntityKey;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+/**
+ * Repository for FlowSnapshotEntity.
+ */
+public interface FlowSnapshotRepository extends PagingAndSortingRepository<FlowSnapshotEntity, FlowSnapshotEntityKey> {
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/flow/StandardFlowSnapshotContext.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/flow/StandardFlowSnapshotContext.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/flow/StandardFlowSnapshotContext.java
deleted file mode 100644
index 3527355..0000000
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/flow/StandardFlowSnapshotContext.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.registry.flow;
-
-import org.apache.commons.lang3.Validate;
-import org.apache.nifi.registry.bucket.Bucket;
-
-/**
- * Standard implementation of FlowSnapshotContext.
- */
-public class StandardFlowSnapshotContext implements FlowSnapshotContext {
-
-    private final String bucketId;
-    private final String bucketName;
-    private final String flowId;
-    private final String flowName;
-    private final int version;
-    private final String comments;
-    private final long snapshotTimestamp;
-
-    private StandardFlowSnapshotContext(final Builder builder) {
-        this.bucketId = builder.bucketId;
-        this.bucketName = builder.bucketName;
-        this.flowId = builder.flowId;
-        this.flowName = builder.flowName;
-        this.version = builder.version;
-        this.comments = builder.comments;
-        this.snapshotTimestamp = builder.snapshotTimestamp;
-
-        Validate.notBlank(bucketId);
-        Validate.notBlank(bucketName);
-        Validate.notBlank(flowId);
-        Validate.notBlank(flowName);
-        Validate.isTrue(version > 0);
-        Validate.isTrue(snapshotTimestamp > 0);
-    }
-
-    @Override
-    public String getBucketId() {
-        return bucketId;
-    }
-
-    @Override
-    public String getBucketName() {
-        return bucketName;
-    }
-
-    @Override
-    public String getFlowId() {
-        return flowId;
-    }
-
-    @Override
-    public String getFlowName() {
-        return flowName;
-    }
-
-    @Override
-    public int getVersion() {
-        return version;
-    }
-
-    @Override
-    public String getComments() {
-        return comments;
-    }
-
-    @Override
-    public long getSnapshotTimestamp() {
-        return snapshotTimestamp;
-    }
-
-    /**
-     * Builder for creating instances of StandardFlowSnapshotContext.
-     */
-    public static class Builder {
-
-        private String bucketId;
-        private String bucketName;
-        private String flowId;
-        private String flowName;
-        private int version;
-        private String comments;
-        private long snapshotTimestamp;
-
-        public Builder() {
-
-        }
-
-        public Builder(final Bucket bucket, final VersionedFlowSnapshotMetadata snapshotMetadata) {
-            bucketId(bucket.getIdentifier());
-            bucketName(bucket.getName());
-            flowId(snapshotMetadata.getFlowIdentifier());
-            flowName(snapshotMetadata.getFlowName());
-            version(snapshotMetadata.getVersion());
-            comments(snapshotMetadata.getComments());
-            snapshotTimestamp(snapshotMetadata.getTimestamp());
-        }
-
-        public Builder bucketId(final String bucketId) {
-            this.bucketId = bucketId;
-            return this;
-        }
-
-        public Builder bucketName(final String bucketName) {
-            this.bucketName = bucketName;
-            return this;
-        }
-
-        public Builder flowId(final String flowId) {
-            this.flowId = flowId;
-            return this;
-        }
-
-        public Builder flowName(final String flowName) {
-            this.flowName = flowName;
-            return this;
-        }
-
-        public Builder version(final int version) {
-            this.version = version;
-            return this;
-        }
-
-        public Builder comments(final String comments) {
-            this.comments = comments;
-            return this;
-        }
-
-        public Builder snapshotTimestamp(final long snapshotTimestamp) {
-            this.snapshotTimestamp = snapshotTimestamp;
-            return this;
-        }
-
-        public StandardFlowSnapshotContext build() {
-            return new StandardFlowSnapshotContext(this);
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/ProviderFactory.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/ProviderFactory.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/ProviderFactory.java
index 0e6229c..d5b40a2 100644
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/ProviderFactory.java
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/ProviderFactory.java
@@ -17,7 +17,6 @@
 package org.apache.nifi.registry.provider;
 
 import org.apache.nifi.registry.flow.FlowPersistenceProvider;
-import org.apache.nifi.registry.metadata.MetadataProvider;
 
 /**
  * A factory for obtaining the configured providers.
@@ -32,11 +31,6 @@ public interface ProviderFactory {
     void initialize() throws ProviderFactoryException;
 
     /**
-     * @return the configured MetadataProvider
-     */
-    MetadataProvider getMetadataProvider();
-
-    /**
      * @return the configured FlowPersistenceProvider
      */
     FlowPersistenceProvider getFlowPersistenceProvider();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/d478c20e/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
index 918ab79..01d8a8a 100644
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
@@ -17,7 +17,6 @@
 package org.apache.nifi.registry.provider;
 
 import org.apache.nifi.registry.flow.FlowPersistenceProvider;
-import org.apache.nifi.registry.metadata.MetadataProvider;
 import org.apache.nifi.registry.properties.NiFiRegistryProperties;
 import org.apache.nifi.registry.provider.generated.Property;
 import org.apache.nifi.registry.provider.generated.Providers;
@@ -71,9 +70,9 @@ public class StandardProviderFactory implements ProviderFactory {
     private final AtomicReference<Providers> providersHolder = new AtomicReference<>(null);
 
     private FlowPersistenceProvider flowPersistenceProvider;
-    private MetadataProvider metadataProvider;
 
-    public StandardProviderFactory(@Autowired final NiFiRegistryProperties properties) {
+    @Autowired
+    public StandardProviderFactory(final NiFiRegistryProperties properties) {
         this.properties = properties;
 
         if (this.properties == null) {
@@ -110,39 +109,6 @@ public class StandardProviderFactory implements ProviderFactory {
 
     @Bean
     @Override
-    public synchronized MetadataProvider getMetadataProvider() {
-        if (metadataProvider == null) {
-            if (providersHolder.get() == null) {
-                throw new ProviderFactoryException("ProviderFactory must be initialized before obtaining a Provider");
-            }
-
-            final Providers providers = providersHolder.get();
-            final org.apache.nifi.registry.provider.generated.Provider jaxbMetadataProvider = providers.getMetadataProvider();
-            final String metadataProviderClassName = jaxbMetadataProvider.getClazz();
-
-            try {
-                final Class<?> rawMetadataProviderClass = Class.forName(metadataProviderClassName, true, StandardProviderFactory.class.getClassLoader());
-                final Class<? extends MetadataProvider> metadataProviderClass = rawMetadataProviderClass.asSubclass(MetadataProvider.class);
-
-                // otherwise create a new instance
-                final Constructor constructor = metadataProviderClass.getConstructor();
-                metadataProvider = (MetadataProvider) constructor.newInstance();
-
-                LOGGER.info("Instantiated MetadataProvider with class name {}", new Object[] {metadataProviderClassName});
-            } catch (Exception e) {
-                throw new ProviderFactoryException("Error creating MetadataProvider with class name: " + metadataProviderClassName, e);
-            }
-
-            final ProviderConfigurationContext configurationContext = createConfigurationContext(jaxbMetadataProvider.getProperty());
-            metadataProvider.onConfigured(configurationContext);
-            LOGGER.info("Configured MetadataProvider with class name {}", new Object[] {metadataProviderClassName});
-        }
-
-        return metadataProvider;
-    }
-
-    @Bean
-    @Override
     public synchronized FlowPersistenceProvider getFlowPersistenceProvider() {
         if (flowPersistenceProvider == null) {
             if (providersHolder.get() == null) {