nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bbe...@apache.org
Subject [2/2] nifi-registry git commit: NIFIREG-22 Adding versionCount to VersionedFlow with back-end support for populating it
Date Wed, 11 Oct 2017 18:54:00 GMT
NIFIREG-22 Adding versionCount to VersionedFlow with back-end support for populating it

This closes #11.

Signed-off-by: Bryan Bende <bbende@apache.org>


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

Branch: refs/heads/master
Commit: 2f7523538be0fa840bc1d4a7202acf527e7039a9
Parents: cd1114f
Author: Bryan Bende <bbende@apache.org>
Authored: Thu Sep 21 13:02:26 2017 -0400
Committer: Bryan Bende <bbende@apache.org>
Committed: Wed Oct 11 14:52:15 2017 -0400

----------------------------------------------------------------------
 .../nifi/registry/flow/VersionedFlow.java       |  13 +
 .../registry/db/DatabaseMetadataService.java    | 250 ++++++++-----------
 .../nifi/registry/db/entity/FlowEntity.java     |  12 +
 .../registry/db/entity/FlowSnapshotCount.java   |  41 +++
 .../db/repository/BucketItemRepository.java     |  24 --
 .../db/repository/BucketRepository.java         |   6 +
 .../registry/db/repository/FlowRepository.java  |  27 +-
 .../db/repository/FlowSnapshotRepository.java   |   7 +
 .../registry/service/AuthorizationService.java  |  11 +-
 .../nifi/registry/service/DataModelMapper.java  |   1 +
 .../nifi/registry/service/MetadataService.java  |  54 ++--
 .../nifi/registry/service/RegistryService.java  |  59 ++---
 .../nifi/registry/db/DatabaseBaseTest.java      |  34 +++
 .../registry/db/DatabaseTestApplication.java    |  45 ++++
 .../registry/db/RepositoryTestApplication.java  |  45 ----
 .../db/TestDatabaseMetadataService.java         | 104 ++++++++
 .../db/repository/RepositoryBaseTest.java       |  34 ---
 .../db/repository/TestBucketItemRepository.java |  28 +--
 .../db/repository/TestBucketRepository.java     |   3 +-
 .../db/repository/TestFlowRepository.java       |   3 +-
 .../repository/TestFlowSnapshotRepository.java  |  16 +-
 .../registry/service/TestRegistryService.java   |  51 +---
 .../web/NiFiRegistryResourceConfig.java         |   2 -
 .../nifi/registry/web/api/BucketResource.java   |  17 +-
 .../nifi/registry/web/api/FlowResource.java     | 128 ----------
 .../apache/nifi/registry/web/TestRestAPI.java   | 143 +++++------
 26 files changed, 535 insertions(+), 623 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/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 b70f6be..88a02d1 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
@@ -22,6 +22,7 @@ import org.apache.nifi.registry.bucket.BucketItem;
 import org.apache.nifi.registry.bucket.BucketItemType;
 
 import javax.validation.Valid;
+import javax.validation.constraints.Min;
 import javax.xml.bind.annotation.XmlRootElement;
 import java.util.SortedSet;
 
@@ -38,6 +39,9 @@ import java.util.SortedSet;
 @ApiModel(value = "versionedFlow")
 public class VersionedFlow extends BucketItem {
 
+    @Min(0)
+    private long versionCount;
+
     @Valid
     private SortedSet<VersionedFlowSnapshotMetadata> snapshotMetadata;
 
@@ -45,6 +49,15 @@ public class VersionedFlow extends BucketItem {
         super(BucketItemType.FLOW);
     }
 
+    @ApiModelProperty(value = "The number of versions of this flow.", readOnly = true)
+    public long getVersionCount() {
+        return versionCount;
+    }
+
+    public void setVersionCount(long versionCount) {
+        this.versionCount = versionCount;
+    }
+
     @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/2f752353/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
index 0fc10a4..07d530a 100644
--- 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
@@ -19,6 +19,7 @@ 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.BucketItemEntityType;
 import org.apache.nifi.registry.db.entity.FlowEntity;
 import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
 import org.apache.nifi.registry.db.entity.FlowSnapshotEntityKey;
@@ -42,8 +43,10 @@ import javax.persistence.metamodel.Metamodel;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -131,37 +134,46 @@ public class DatabaseMetadataService implements MetadataService {
     }
 
     @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);
+    public List<BucketEntity> getAllBuckets() {
+        final List<BucketEntity> buckets = new ArrayList<>();
+        for (BucketEntity bucket : bucketRepository.findAll()) {
+            buckets.add(bucket);
+        }
+        return buckets;
+    }
+
+    @Override
+    public List<BucketEntity> getBuckets(final QueryParameters params, final Set<String> bucketIds) {
+        if (params != null && params.getNumRows() != null && params.getPageNum() != null) {
+            return getPagedBuckets(params, bucketIds);
+        } else if (params != null && params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+            return getSortedBuckets(params, bucketIds);
         } else {
-            return getAllBuckets();
+            return getAllBuckets(bucketIds);
         }
     }
 
-    private List<BucketEntity> getAllBuckets() {
+    private List<BucketEntity> getAllBuckets(final Set<String> bucketIds) {
         final List<BucketEntity> buckets = new ArrayList<>();
-        for (BucketEntity bucket : bucketRepository.findAll()) {
+        for (BucketEntity bucket : bucketRepository.findByIdIn(bucketIds)) {
             buckets.add(bucket);
         }
         return buckets;
     }
 
-    private List<BucketEntity> getPagedBuckets(final QueryParameters params) {
+    private List<BucketEntity> getPagedBuckets(final QueryParameters params, final Set<String> bucketIds) {
         final Pageable pageable = getPageRequest(params);
         final List<BucketEntity> buckets = new ArrayList<>();
-        for (BucketEntity bucket : bucketRepository.findAll(pageable)) {
+        for (BucketEntity bucket : bucketRepository.findByIdIn(bucketIds, pageable)) {
             buckets.add(bucket);
         }
         return buckets;
     }
 
-    private List<BucketEntity> getSortedBuckets(final QueryParameters params) {
+    private List<BucketEntity> getSortedBuckets(final QueryParameters params, final Set<String> bucketIds) {
         final Sort sort = getSort(params);
         final List<BucketEntity> buckets = new ArrayList<>();
-        for (BucketEntity bucket : bucketRepository.findAll(sort)) {
+        for (BucketEntity bucket : bucketRepository.findByIdIn(bucketIds, sort)) {
             buckets.add(bucket);
         }
         return buckets;
@@ -174,117 +186,89 @@ public class DatabaseMetadataService implements MetadataService {
     // ------------------------------------------------------------------------------------
 
     @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);
+    public List<BucketItemEntity> getBucketItems(final QueryParameters params, final BucketEntity bucket) {
+        if (params != null && params.getNumRows() != null && params.getPageNum() != null) {
+            return getPagedBucketItems(params, bucket);
+        } else if (params != null && params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+            return getSortedBucketItems(params, bucket);
         } else {
-            return getAllBucketItems();
+            return getBucketItems(bucket);
         }
     }
 
-    private List<BucketItemEntity> getAllBucketItems() {
-        final List<BucketItemEntity> bucketItems = new ArrayList<>();
-        for (BucketItemEntity item : itemRepository.findAll()) {
-            bucketItems.add(item);
-        }
-        return bucketItems;
+    private List<BucketItemEntity> getBucketItems(final BucketEntity bucket) {
+        final Iterable<BucketItemEntity> items = itemRepository.findByBucket(bucket);
+        return getItemsWithCounts(items);
     }
 
-    private List<BucketItemEntity> getPagedBucketItems(final QueryParameters params) {
+    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.findAll(pageable)) {
-            items.add(item);
-        }
-        return items;
+        final Iterable<BucketItemEntity> items = itemRepository.findByBucket(bucket, pageable);
+        return getItemsWithCounts(items);
     }
 
-    private List<BucketItemEntity> getSortedBucketItems(final QueryParameters params) {
+    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.findAll(sort)) {
-            items.add(item);
-        }
-        return items;
+        final Iterable<BucketItemEntity> items = itemRepository.findByBucket(bucket, sort);
+        return getItemsWithCounts(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);
-        }
-    }
-
-    @Override
     public List<BucketItemEntity> getBucketItems(final QueryParameters params, final Set<String> bucketIds) {
         Set<BucketEntity> filterBuckets = getBuckets(bucketIds);
-        if (params.getNumRows() != null && params.getPageNum() != null) {
+        if (params != null && params.getNumRows() != null && params.getPageNum() != null) {
             return getPagedBucketItems(params, filterBuckets);
-        } else if (params.getSortParameters() != null && params.getSortParameters().size() > 0) {
+        } else if (params != null && params.getSortParameters() != null && params.getSortParameters().size() > 0) {
             return getSortedBucketItems(params, filterBuckets);
         } else {
             return getBucketItems(filterBuckets);
         }
     }
 
-    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> getBucketItems(final Set<BucketEntity> buckets) {
+        final List<BucketItemEntity> items = itemRepository.findByBucketIn(buckets);
+        return getItemsWithCounts(items);
     }
 
-    private List<BucketItemEntity> getPagedBucketItems(final QueryParameters params, final BucketEntity bucket) {
+    private List<BucketItemEntity> getPagedBucketItems(final QueryParameters params, final Set<BucketEntity> buckets) {
         final Pageable pageable = getPageRequest(params);
-        final List<BucketItemEntity> items = new ArrayList<>();
-        for (BucketItemEntity item : itemRepository.findByBucket(bucket, pageable)) {
-            items.add(item);
-        }
-        return items;
+        final List<BucketItemEntity> items = itemRepository.findByBucketIn(buckets, pageable);
+        return getItemsWithCounts(items);
     }
 
-    private List<BucketItemEntity> getSortedBucketItems(final QueryParameters params, final BucketEntity bucket) {
+    private List<BucketItemEntity> getSortedBucketItems(final QueryParameters params, final Set<BucketEntity> buckets) {
         final Sort sort = getSort(params);
-        final List<BucketItemEntity> items = new ArrayList<>();
-        for (BucketItemEntity item : itemRepository.findByBucket(bucket, sort)) {
-            items.add(item);
-        }
-        return items;
+        final List<BucketItemEntity> items = itemRepository.findByBucketIn(buckets, sort);
+        return getItemsWithCounts(items);
     }
 
-    private List<BucketItemEntity> getBucketItems(final Set<BucketEntity> buckets) {
-        final List<BucketItemEntity> bucketItems = new ArrayList<>();
-        for (BucketItemEntity item : itemRepository.findByBucketIn(buckets)) {
-            bucketItems.add(item);
-        }
-        return bucketItems;
-    }
+    // ------------------------------------------------------------------------------------
 
-    private List<BucketItemEntity> getPagedBucketItems(final QueryParameters params, final Set<BucketEntity> buckets) {
-        final Pageable pageable = getPageRequest(params);
-        final List<BucketItemEntity> items = new ArrayList<>();
-        for (BucketItemEntity item : itemRepository.findByBucketIn(buckets, pageable)) {
-            items.add(item);
+    private List<BucketItemEntity> getItemsWithCounts(final Iterable<BucketItemEntity> items) {
+        final Map<String,Long> snapshotCounts = getFlowSnapshotCounts();
+
+        final List<BucketItemEntity> itemWithCounts = new ArrayList<>();
+        for (final BucketItemEntity item : items) {
+            if (item.getType() == BucketItemEntityType.FLOW) {
+                final Long snapshotCount = snapshotCounts.get(item.getId());
+                if (snapshotCount != null) {
+                    final FlowEntity flowEntity = (FlowEntity) item;
+                    flowEntity.setSnapshotCount(snapshotCount);
+                }
+            }
+
+            itemWithCounts.add(item);
         }
-        return items;
+
+        return itemWithCounts;
     }
 
-    private List<BucketItemEntity> getSortedBucketItems(final QueryParameters params, final Set<BucketEntity> buckets) {
-        final Sort sort = getSort(params);
-        final List<BucketItemEntity> items = new ArrayList<>();
-        for (BucketItemEntity item : itemRepository.findByBucketIn(buckets, sort)) {
-            items.add(item);
-        }
-        return items;
+    private Map<String,Long> getFlowSnapshotCounts() {
+        final Map<String,Long> flowSnapshotCounts = new HashMap<>();
+        flowSnapshotRepository.countByFlow().stream().forEach(c -> flowSnapshotCounts.put(c.getFlowIdentifier(), c.getSnapshotCount()));
+        return flowSnapshotCounts;
     }
 
     // ------------------------------------------------------------------------------------
@@ -300,7 +284,7 @@ public class DatabaseMetadataService implements MetadataService {
     public FlowEntity getFlowById(final String bucketIdentifier, final String flowIdentifier) {
         FlowEntity flow = flowRepository.findOne(flowIdentifier);
 
-        if (flow.getBucket() == null || !bucketIdentifier.equals(flow.getBucket().getId())) {
+        if (flow == null || flow.getBucket() == null || !bucketIdentifier.equals(flow.getBucket().getId())) {
             return null;
         }
 
@@ -308,6 +292,24 @@ public class DatabaseMetadataService implements MetadataService {
     }
 
     @Override
+    public FlowEntity getFlowByIdWithSnapshotCounts(final String bucketIdentifier, final String flowIdentifier) {
+        FlowEntity flow = flowRepository.findOne(flowIdentifier);
+
+        if (flow == null || flow.getBucket() == null || !bucketIdentifier.equals(flow.getBucket().getId())) {
+            return null;
+        }
+
+        final Map<String,Long> snapshotCounts = getFlowSnapshotCounts();
+
+        final Long snapshotCount = snapshotCounts.get(flow.getId());
+        if (snapshotCount != null) {
+            flow.setSnapshotCount(snapshotCount);
+        }
+
+        return flow;
+    }
+
+    @Override
     public List<FlowEntity> getFlowsByName(final String name) {
         List<FlowEntity> flows = new ArrayList<>();
 
@@ -322,6 +324,21 @@ public class DatabaseMetadataService implements MetadataService {
     }
 
     @Override
+    public List<FlowEntity> getFlowsByBucket(final BucketEntity bucketEntity) {
+        final Map<String,Long> snapshotCounts = getFlowSnapshotCounts();
+
+        final List<FlowEntity> flows = flowRepository.findByBucket(bucketEntity);
+        for (final FlowEntity flowEntity : flows) {
+            final Long snapshotCount = snapshotCounts.get(flowEntity.getId());
+            if (snapshotCount != null) {
+                flowEntity.setSnapshotCount(snapshotCount);
+            }
+        }
+
+        return flows;
+    }
+
+    @Override
     public FlowEntity updateFlow(final FlowEntity flow) {
         flow.setModified(new Date());
         return flowRepository.save(flow);
@@ -332,63 +349,6 @@ public class DatabaseMetadataService implements MetadataService {
         flowRepository.delete(flow);
     }
 
-    @Override
-    public List<FlowEntity> getFlows(final QueryParameters params) {
-        return getFlows(params, null);
-    }
-
-    @Override
-    public List<FlowEntity> getFlows(final QueryParameters params, Set<String> bucketIds) {
-        Set<BucketEntity> filterBuckets = getBuckets(bucketIds);
-        if (params.getNumRows() != null && params.getPageNum() != null) {
-            return getPagedFlows(params, filterBuckets);
-        } else if (params.getSortParameters() != null && params.getSortParameters().size() > 0) {
-            return getSortedFlows(params, filterBuckets);
-        } else {
-            return getAllFlows(filterBuckets);
-        }
-    }
-
-    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;
-    }
-
-    private List<FlowEntity> getAllFlows(Set<BucketEntity> buckets) {
-        return flowRepository.findByBucketIn(buckets);
-    }
-
-    private List<FlowEntity> getPagedFlows(final QueryParameters params, Set<BucketEntity> buckets) {
-        final Pageable pageable = getPageRequest(params);
-        return flowRepository.findByBucketIn(buckets, pageable);
-    }
-
-    private List<FlowEntity> getSortedFlows(final QueryParameters params, Set<BucketEntity> buckets) {
-        final Sort sort = getSort(params);
-        return flowRepository.findByBucketIn(buckets, sort);
-    }
-
     // ------------------------------------------------------------------------------------
 
     @Override

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/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
index 84d2ab4..a3b5cdd 100644
--- 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
@@ -21,6 +21,7 @@ import javax.persistence.DiscriminatorValue;
 import javax.persistence.Entity;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
+import javax.persistence.Transient;
 import java.util.Set;
 
 @Entity
@@ -35,6 +36,9 @@ public class FlowEntity extends BucketItemEntity {
     )
     private Set<FlowSnapshotEntity> snapshots;
 
+    @Transient
+    private long snapshotCount;
+
     public FlowEntity() {
         setType(BucketItemEntityType.FLOW);
     }
@@ -47,6 +51,14 @@ public class FlowEntity extends BucketItemEntity {
         this.snapshots = snapshots;
     }
 
+    public long getSnapshotCount() {
+        return snapshotCount;
+    }
+
+    public void setSnapshotCount(long snapshotCount) {
+        this.snapshotCount = snapshotCount;
+    }
+
     @Override
     public void setType(BucketItemEntityType type) {
         if (BucketItemEntityType.FLOW != type) {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotCount.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotCount.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotCount.java
new file mode 100644
index 0000000..b561abb
--- /dev/null
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/FlowSnapshotCount.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+/**
+ * Used to perform a custom query that returns the # of snapshots for each flow.
+ */
+public class FlowSnapshotCount {
+
+    private final String flowIdentifier;
+
+    private final long snapshotCount;
+
+    public FlowSnapshotCount(final String flowIdentifier, final long snapshotCount) {
+        this.flowIdentifier = flowIdentifier;
+        this.snapshotCount = snapshotCount;
+    }
+
+    public String getFlowIdentifier() {
+        return flowIdentifier;
+    }
+
+    public long getSnapshotCount() {
+        return snapshotCount;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/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
index 2f188e1..5d46606 100644
--- 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
@@ -18,7 +18,6 @@ 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;
@@ -34,29 +33,6 @@ import java.util.Set;
 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

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/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
index f7fb7fb..5f7e31c 100644
--- 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
@@ -17,6 +17,8 @@
 package org.apache.nifi.registry.db.repository;
 
 import org.apache.nifi.registry.db.entity.BucketEntity;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
 import java.util.List;
@@ -31,4 +33,8 @@ public interface BucketRepository extends PagingAndSortingRepository<BucketEntit
 
     List<BucketEntity> findByIdIn(Set<String> id);
 
+    List<BucketEntity> findByIdIn(Set<String> id, Sort sort);
+
+    List<BucketEntity> findByIdIn(Set<String> id, Pageable pageable);
+
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/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
index bfda5d0..6740d35 100644
--- 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
@@ -18,12 +18,9 @@ package org.apache.nifi.registry.db.repository;
 
 import org.apache.nifi.registry.db.entity.BucketEntity;
 import org.apache.nifi.registry.db.entity.FlowEntity;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
 import java.util.List;
-import java.util.Set;
 
 /**
  * Spring Data Repository for FlowEntity.
@@ -33,29 +30,11 @@ public interface FlowRepository extends PagingAndSortingRepository<FlowEntity,St
     List<FlowEntity> findByNameIgnoreCase(String name);
 
     /**
-     * Find all flows by buckets.
+     * Find flows for the given bucket.
      *
-     * @param buckets the buckets to find items for
-     * @return the list of items for the buckets
-     */
-    List<FlowEntity> findByBucketIn(Set<BucketEntity> buckets);
-
-    /**
-     * Find all flows by buckets with sorting.
-     *
-     * @param buckets the buckets to find flows for
-     * @param sort the sort params
+     * @param bucket the bucket to find flows for
      * @return the list of flows for the buckets
      */
-    List<FlowEntity> findByBucketIn(Set<BucketEntity> buckets, Sort sort);
-
-    /**
-     * Find all flows by buckets with paging/sorting.
-     *
-     * @param buckets the buckets to find flows for
-     * @param pageable the pageable params
-     * @return the list of flows for the buckets based on the pageable params
-     */
-    List<FlowEntity> findByBucketIn(Set<BucketEntity> buckets, Pageable pageable);
+    List<FlowEntity> findByBucket(BucketEntity bucket);
 
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/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
index 1b3917d..817048f 100644
--- 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
@@ -16,13 +16,20 @@
  */
 package org.apache.nifi.registry.db.repository;
 
+import org.apache.nifi.registry.db.entity.FlowSnapshotCount;
 import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
 import org.apache.nifi.registry.db.entity.FlowSnapshotEntityKey;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
+import java.util.List;
+
 /**
  * Repository for FlowSnapshotEntity.
  */
 public interface FlowSnapshotRepository extends PagingAndSortingRepository<FlowSnapshotEntity, FlowSnapshotEntityKey> {
 
+    @Query("select new org.apache.nifi.registry.db.entity.FlowSnapshotCount(fs.id.flowId, count(*)) from FlowSnapshotEntity as fs group by fs.id.flowId")
+    List<FlowSnapshotCount> countByFlow();
+
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
index c62d170..cc63af0 100644
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
@@ -19,14 +19,10 @@ package org.apache.nifi.registry.service;
 import org.apache.nifi.registry.authorization.AccessPolicyProvider;
 import org.apache.nifi.registry.authorization.AccessPolicyProviderInitializationContext;
 import org.apache.nifi.registry.authorization.AuthorizableLookup;
-import org.apache.nifi.registry.authorization.exception.AccessDeniedException;
-import org.apache.nifi.registry.authorization.exception.AuthorizationAccessException;
 import org.apache.nifi.registry.authorization.AuthorizeAccess;
 import org.apache.nifi.registry.authorization.Authorizer;
 import org.apache.nifi.registry.authorization.AuthorizerCapabilityDetection;
 import org.apache.nifi.registry.authorization.AuthorizerConfigurationContext;
-import org.apache.nifi.registry.authorization.exception.AuthorizerCreationException;
-import org.apache.nifi.registry.authorization.exception.AuthorizerDestructionException;
 import org.apache.nifi.registry.authorization.ConfigurableAccessPolicyProvider;
 import org.apache.nifi.registry.authorization.ConfigurableUserGroupProvider;
 import org.apache.nifi.registry.authorization.Group;
@@ -35,6 +31,10 @@ import org.apache.nifi.registry.authorization.RequestAction;
 import org.apache.nifi.registry.authorization.UserAndGroups;
 import org.apache.nifi.registry.authorization.UserGroupProvider;
 import org.apache.nifi.registry.authorization.UserGroupProviderInitializationContext;
+import org.apache.nifi.registry.authorization.exception.AccessDeniedException;
+import org.apache.nifi.registry.authorization.exception.AuthorizationAccessException;
+import org.apache.nifi.registry.authorization.exception.AuthorizerCreationException;
+import org.apache.nifi.registry.authorization.exception.AuthorizerDestructionException;
 import org.apache.nifi.registry.authorization.resource.ResourceFactory;
 import org.apache.nifi.registry.authorization.resource.ResourceType;
 import org.apache.nifi.registry.authorization.user.NiFiUserUtils;
@@ -45,7 +45,6 @@ import org.apache.nifi.registry.model.authorization.Resource;
 import org.apache.nifi.registry.model.authorization.Tenant;
 import org.apache.nifi.registry.model.authorization.User;
 import org.apache.nifi.registry.model.authorization.UserGroup;
-import org.apache.nifi.registry.service.params.QueryParameters;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -428,7 +427,7 @@ public class AuthorizationService {
 
         // add all buckets
         resources.add(ResourceFactory.getBucketsResource());
-        for (final Bucket bucket : registryService.getBuckets(QueryParameters.EMPTY_PARAMETERS)) {
+        for (final Bucket bucket : registryService.getBuckets()) {
             resources.add(ResourceFactory.getChildResource(ResourceType.Bucket, bucket.getIdentifier(), bucket.getName()));
         }
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
index b4448a5..383f819 100644
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
@@ -92,6 +92,7 @@ public class DataModelMapper {
         versionedFlow.setDescription(flowEntity.getDescription());
         versionedFlow.setCreatedTimestamp(flowEntity.getCreated().getTime());
         versionedFlow.setModifiedTimestamp(flowEntity.getModified().getTime());
+        versionedFlow.setVersionCount(flowEntity.getSnapshotCount());
 
         if (mapChildren && flowEntity.getSnapshots() != null) {
             final SortedSet<VersionedFlowSnapshotMetadata> snapshots = new TreeSet<>();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
index 2a85c84..d754b63 100644
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
@@ -71,20 +71,22 @@ public interface MetadataService {
     void deleteBucket(BucketEntity bucket);
 
     /**
-     * Retrieves all buckets known to this metadata provider.
+     * Retrieves all buckets with the given ids.
      *
      * @param params the paging and sorting params, or null
+     * @param bucketIds the ids of the buckets to retrieve
      * @return the set of all buckets
      */
-    List<BucketEntity> getBuckets(QueryParameters params);
+    List<BucketEntity> getBuckets(QueryParameters params, Set<String> bucketIds);
 
     /**
-     * Retrieves items across all buckets.
+     * Retrieves all buckets.
      *
-     * @param queryParameters the parameters for retrieving the items, or null
-     * @return the set of all items
+     * @return the set of all buckets
      */
-    List<BucketItemEntity> getBucketItems(QueryParameters queryParameters);
+    List<BucketEntity> getAllBuckets();
+
+    // --------------------------------------------------------------------------------------------
 
     /**
      * Retrieves items for the given bucket.
@@ -104,6 +106,8 @@ public interface MetadataService {
      */
     List<BucketItemEntity> getBucketItems(QueryParameters queryParameters, Set<String> bucketIds);
 
+    // --------------------------------------------------------------------------------------------
+
     /**
      * Creates a versioned flow in the given bucket.
      *
@@ -114,7 +118,7 @@ public interface MetadataService {
     FlowEntity createFlow(FlowEntity flow);
 
     /**
-     * Retrieves the versioned flow with the given id.
+     * Retrieves the versioned flow with the given id and DOES NOT populate the versionCount.
      *
      * @param bucketIdentifier the identifier of the bucket storing the flow
      * @param flowIdentifier the identifier of the flow to retrieve
@@ -123,6 +127,15 @@ public interface MetadataService {
     FlowEntity getFlowById(String bucketIdentifier, String flowIdentifier);
 
     /**
+     * Retrieves the versioned flow with the given id and DOES populate the versionCount.
+     *
+     * @param bucketIdentifier the identifier of the bucket storing the flow
+     * @param flowIdentifier the identifier of the flow to retrieve
+     * @return the versioned flow with the given id, or null if no flow with the given id exists
+     */
+    FlowEntity getFlowByIdWithSnapshotCounts(final String bucketIdentifier, final String flowIdentifier);
+
+    /**
      * Retrieves the versioned flows with the given name. The name comparison must be case-insensitive.
      *
      * @param name the name of the flow to retrieve
@@ -131,6 +144,14 @@ public interface MetadataService {
     List<FlowEntity> getFlowsByName(String name);
 
     /**
+     * Retrieves the versioned flows for the given bucket.
+     *
+     * @param bucketEntity the bucket entity
+     * @return the flows in the given bucket
+     */
+    List<FlowEntity> getFlowsByBucket(BucketEntity bucketEntity);
+
+    /**
      * Updates the given versioned flow, only the name and description should be allowed to be updated.
      *
      * @param flow the updated versioned flow to save
@@ -145,22 +166,7 @@ public interface MetadataService {
      */
     void deleteFlow(FlowEntity flow);
 
-    /**
-     * Retrieves all versioned flows known to this metadata provider.
-     *
-     * @param queryParameters the paging and sorting params, or null
-     * @return the set of all versioned flows
-     */
-    List<FlowEntity> getFlows(QueryParameters queryParameters);
-
-    /**
-     * Retrieves items for the given buckets.
-     *
-     * @param bucketIds the ids of buckets to retrieve items for
-     * @param queryParameters the parameters for retrieving the items, or null
-     * @return the set of items for the bucket
-     */
-    List<FlowEntity> getFlows(QueryParameters queryParameters, Set<String> bucketIds);
+    // --------------------------------------------------------------------------------------------
 
     /**
      * Creates a versioned flow snapshot.
@@ -188,6 +194,8 @@ public interface MetadataService {
      */
     void deleteFlowSnapshot(FlowSnapshotEntity flowSnapshot);
 
+    // --------------------------------------------------------------------------------------------
+
     /**
      * @return the set of field names for Buckets
      */

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
index f0fc927..f0e00d4 100644
--- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
+++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
@@ -126,7 +126,7 @@ public class RegistryService {
         }
     }
 
-    public Bucket getBucket(final String bucketIdentifier, final boolean verbose) {
+    public Bucket getBucket(final String bucketIdentifier) {
         if (bucketIdentifier == null) {
             throw new IllegalArgumentException("Bucket Identifier cannot be null");
         }
@@ -138,16 +138,26 @@ public class RegistryService {
                 throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketIdentifier);
             }
 
-            return DataModelMapper.map(bucket, verbose);
+            return DataModelMapper.map(bucket, false);
         } finally {
             readLock.unlock();
         }
     }
 
-    public List<Bucket> getBuckets(final QueryParameters queryParameters) {
+    public List<Bucket> getBuckets() {
         readLock.lock();
         try {
-            final List<BucketEntity> buckets = metadataService.getBuckets(queryParameters);
+            final List<BucketEntity> buckets = metadataService.getAllBuckets();
+            return buckets.stream().map(b -> DataModelMapper.map(b, false)).collect(Collectors.toList());
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    public List<Bucket> getBuckets(final QueryParameters queryParameters, final Set<String> bucketIds) {
+        readLock.lock();
+        try {
+            final List<BucketEntity> buckets = metadataService.getBuckets(queryParameters, bucketIds);
             return buckets.stream().map(b -> DataModelMapper.map(b, false)).collect(Collectors.toList());
         } finally {
             readLock.unlock();
@@ -230,17 +240,6 @@ public class RegistryService {
 
     // ---------------------- BucketItem methods ---------------------------------------------
 
-    public List<BucketItem> getBucketItems(final QueryParameters queryParameters) {
-        readLock.lock();
-        try {
-            final List<BucketItem> bucketItems = new ArrayList<>();
-            metadataService.getBucketItems(queryParameters).stream().forEach(b -> addBucketItem(bucketItems, b));
-            return bucketItems;
-        } finally {
-            readLock.unlock();
-        }
-    }
-
     public List<BucketItem> getBucketItems(final QueryParameters queryParameters, final String bucketIdentifier) {
         if (bucketIdentifier == null) {
             throw new IllegalArgumentException("Bucket Identifier cannot be null");
@@ -342,13 +341,17 @@ public class RegistryService {
     }
 
     public VersionedFlow getFlow(final String bucketIdentifier, final String flowIdentifier, final boolean verbose) {
+        if (StringUtils.isBlank(bucketIdentifier)) {
+            throw new IllegalArgumentException("Bucket Identifier Identifier cannot be null or blank");
+        }
+
         if (StringUtils.isBlank(flowIdentifier)) {
             throw new IllegalArgumentException("Flow Identifier cannot be null or blank");
         }
 
         readLock.lock();
         try {
-            final FlowEntity flowEntity = metadataService.getFlowById(bucketIdentifier, flowIdentifier);
+            final FlowEntity flowEntity = metadataService.getFlowByIdWithSnapshotCounts(bucketIdentifier, flowIdentifier);
             if (flowEntity == null) {
                 throw new ResourceNotFoundException("VersionedFlow does not exist for identifier: " + flowIdentifier);
             }
@@ -359,17 +362,6 @@ public class RegistryService {
         }
     }
 
-    public List<VersionedFlow> getFlows(final QueryParameters queryParameters) {
-        readLock.lock();
-        try {
-            // return non-verbose set of all flows
-            final List<FlowEntity> flows = metadataService.getFlows(queryParameters);
-            return flows.stream().map(f -> DataModelMapper.map(f, false)).collect(Collectors.toList());
-        } finally {
-            readLock.unlock();
-        }
-    }
-
     public List<VersionedFlow> getFlows(final String bucketId) {
         if (StringUtils.isBlank(bucketId)) {
             throw new IllegalArgumentException("Bucket Identifier cannot be null");
@@ -383,18 +375,7 @@ public class RegistryService {
             }
 
             // return non-verbose set of flows for the given bucket
-            final Set<FlowEntity> flows = existingBucket.getFlows();
-            return flows.stream().map(f -> DataModelMapper.map(f, false)).collect(Collectors.toList());
-        } finally {
-            readLock.unlock();
-        }
-    }
-
-    public List<VersionedFlow> getFlows(final QueryParameters queryParameters, final Set<String> bucketIds) {
-        readLock.lock();
-        try {
-            // return non-verbose set of all flows
-            final List<FlowEntity> flows = metadataService.getFlows(queryParameters, bucketIds);
+            final List<FlowEntity> flows = metadataService.getFlowsByBucket(existingBucket);
             return flows.stream().map(f -> DataModelMapper.map(f, false)).collect(Collectors.toList());
         } finally {
             readLock.unlock();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseBaseTest.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseBaseTest.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseBaseTest.java
new file mode 100644
index 0000000..6376918
--- /dev/null
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseBaseTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.nifi.registry.db.DatabaseTestApplication;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = DatabaseTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
+@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
+public abstract class DatabaseBaseTest {
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseTestApplication.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseTestApplication.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseTestApplication.java
new file mode 100644
index 0000000..ce72410
--- /dev/null
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/DatabaseTestApplication.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.db;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
+
+/**
+ * Sets up the application context for database repository tests.
+ *
+ * The @SpringBootTest annotation on the repository tests will find this class by working up the package hierarchy.
+ * This class must be in the "db" package in order to find the entities in "db.entity" and repositories in "db.repository".
+ *
+ * The DataSourceFactory is excluded so that Spring Boot will load an in-memory H2 database.
+ */
+@SpringBootApplication
+@ComponentScan(
+        excludeFilters = {
+                @ComponentScan.Filter(
+                        type = FilterType.ASSIGNABLE_TYPE,
+                        value = DataSourceFactory.class)
+        })
+public class DatabaseTestApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(DatabaseTestApplication.class, args);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/RepositoryTestApplication.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/RepositoryTestApplication.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/RepositoryTestApplication.java
deleted file mode 100644
index de8cd79..0000000
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/RepositoryTestApplication.java
+++ /dev/null
@@ -1,45 +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.db;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.FilterType;
-
-/**
- * Sets up the application context for database repository tests.
- *
- * The @SpringBootTest annotation on the repository tests will find this class by working up the package hierarchy.
- * This class must be in the "db" package in order to find the entities in "db.entity" and repositories in "db.repository".
- *
- * The DataSourceFactory is excluded so that Spring Boot will load an in-memory H2 database.
- */
-@SpringBootApplication
-@ComponentScan(
-        excludeFilters = {
-                @ComponentScan.Filter(
-                        type = FilterType.ASSIGNABLE_TYPE,
-                        value = DataSourceFactory.class)
-        })
-public class RepositoryTestApplication {
-
-    public static void main(String[] args) {
-        SpringApplication.run(RepositoryTestApplication.class, args);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java
new file mode 100644
index 0000000..86e07bf
--- /dev/null
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java
@@ -0,0 +1,104 @@
+/*
+ * 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.nifi.registry.db.entity.BucketEntity;
+import org.apache.nifi.registry.db.entity.BucketItemEntity;
+import org.apache.nifi.registry.db.entity.BucketItemEntityType;
+import org.apache.nifi.registry.db.entity.FlowEntity;
+import org.apache.nifi.registry.service.params.QueryParameters;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TestDatabaseMetadataService extends DatabaseBaseTest {
+
+    @Autowired
+    private DatabaseMetadataService metadataService;
+
+    @Test
+    public void testGetAllBuckets() {
+        final List<BucketEntity> buckets = metadataService.getAllBuckets();
+        assertNotNull(buckets);
+        assertEquals(6, buckets.size());
+    }
+
+    @Test
+    public void testGetBuckets() {
+        final List<BucketEntity> buckets = metadataService.getBuckets(QueryParameters.EMPTY_PARAMETERS, new HashSet<>(Arrays.asList("1", "2")));
+        assertNotNull(buckets);
+        assertEquals(2, buckets.size());
+    }
+
+    @Test
+    public void testGetItemsWithCounts() {
+        final List<BucketItemEntity> items = metadataService.getBucketItems(null, new HashSet<>(Arrays.asList("1", "2")));
+        assertNotNull(items);
+
+        // 3 items across all buckets
+        assertEquals(3, items.size());
+
+        final BucketItemEntity item1 = items.stream().filter(i -> i.getId().equals("1")).findFirst().orElse(null);
+        assertNotNull(item1);
+        assertEquals(BucketItemEntityType.FLOW, item1.getType());
+
+        final FlowEntity flowEntity = (FlowEntity) item1;
+        assertEquals(3, flowEntity.getSnapshotCount());
+    }
+
+    @Test
+    public void testGetItemsWithCountsFilteredByBuckets() {
+        final List<BucketItemEntity> items = metadataService.getBucketItems(null, Collections.singleton("1"));
+        assertNotNull(items);
+
+        // only 2 items in bucket 1
+        assertEquals(2, items.size());
+
+        final BucketItemEntity item1 = items.stream().filter(i -> i.getId().equals("1")).findFirst().orElse(null);
+        assertNotNull(item1);
+        assertEquals(BucketItemEntityType.FLOW, item1.getType());
+
+        final FlowEntity flowEntity = (FlowEntity) item1;
+        assertEquals(3, flowEntity.getSnapshotCount());
+    }
+
+    @Test
+    public void testGetFlowsByBucketWithCounts() {
+        final BucketEntity bucketEntity = metadataService.getBucketById("1");
+        final List<FlowEntity> flows = metadataService.getFlowsByBucket(bucketEntity);
+        assertEquals(2, flows.size());
+
+        final FlowEntity flowEntity = flows.stream().filter(f -> f.getId().equals("1")).findFirst().orElse(null);
+        assertNotNull(flowEntity);
+        assertEquals(3, flowEntity.getSnapshotCount());
+    }
+
+    @Test
+    public void testGetFlowByIdWithVersionCount() {
+        final FlowEntity flowEntity = metadataService.getFlowByIdWithSnapshotCounts("1", "1");
+        assertNotNull(flowEntity);
+        assertEquals(3, flowEntity.getSnapshotCount());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/RepositoryBaseTest.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/RepositoryBaseTest.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/RepositoryBaseTest.java
deleted file mode 100644
index 7ccd01f..0000000
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/RepositoryBaseTest.java
+++ /dev/null
@@ -1,34 +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.db.repository;
-
-import org.apache.nifi.registry.db.RepositoryTestApplication;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.TestExecutionListeners;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
-import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
-import org.springframework.transaction.annotation.Transactional;
-
-@Transactional
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes = RepositoryTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
-@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
-public abstract class RepositoryBaseTest {
-
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketItemRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketItemRepository.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketItemRepository.java
index 657d599..c7fd7af 100644
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketItemRepository.java
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketItemRepository.java
@@ -16,11 +16,11 @@
  */
 package org.apache.nifi.registry.db.repository;
 
+import org.apache.nifi.registry.db.DatabaseBaseTest;
 import org.apache.nifi.registry.db.entity.BucketEntity;
 import org.apache.nifi.registry.db.entity.BucketItemEntity;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Sort;
 
@@ -29,7 +29,7 @@ import java.util.List;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-public class TestBucketItemRepository extends RepositoryBaseTest {
+public class TestBucketItemRepository extends DatabaseBaseTest {
 
     @Autowired
     private BucketRepository bucketRepository;
@@ -38,30 +38,6 @@ public class TestBucketItemRepository extends RepositoryBaseTest {
     private BucketItemRepository bucketItemRepository;
 
     @Test
-    public void testFindAllPageable() {
-        final Page<BucketItemEntity> page = bucketItemRepository.findAll(new PageRequest(0, 10));
-        assertNotNull(page);
-        assertEquals(1, page.getTotalPages());
-        assertEquals(3, page.getTotalElements());
-
-        final List<BucketItemEntity> entities = page.getContent();
-        assertNotNull(entities);
-        assertEquals(3, entities.size());
-    }
-
-    @Test
-    public void testFindAll() {
-        final Iterable<BucketItemEntity> entities = bucketItemRepository.findAll();
-        assertNotNull(entities);
-
-        int count = 0;
-        for (BucketItemEntity entity : entities) {
-            count++;
-        }
-        assertEquals(3, count);
-    }
-
-    @Test
     public void testFindByBucket() {
         final BucketEntity bucket = bucketRepository.findOne("1");
         assertNotNull(bucket);

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketRepository.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketRepository.java
index 6a0a3ed..f431180 100644
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketRepository.java
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestBucketRepository.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.registry.db.repository;
 
+import org.apache.nifi.registry.db.DatabaseBaseTest;
 import org.apache.nifi.registry.db.entity.BucketEntity;
 import org.apache.nifi.registry.db.entity.BucketItemEntity;
 import org.junit.Test;
@@ -35,7 +36,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-public class TestBucketRepository extends RepositoryBaseTest {
+public class TestBucketRepository extends DatabaseBaseTest {
 
     @Autowired
     private BucketRepository bucketRepository;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowRepository.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowRepository.java
index b176f1e..dbffb7a 100644
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowRepository.java
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowRepository.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.registry.db.repository;
 
+import org.apache.nifi.registry.db.DatabaseBaseTest;
 import org.apache.nifi.registry.db.entity.BucketEntity;
 import org.apache.nifi.registry.db.entity.BucketItemEntityType;
 import org.apache.nifi.registry.db.entity.FlowEntity;
@@ -30,7 +31,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-public class TestFlowRepository extends RepositoryBaseTest {
+public class TestFlowRepository extends DatabaseBaseTest {
 
     @Autowired
     private BucketRepository bucketRepository;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowSnapshotRepository.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowSnapshotRepository.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowSnapshotRepository.java
index 2b30272..dcf2236 100644
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowSnapshotRepository.java
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/repository/TestFlowSnapshotRepository.java
@@ -16,20 +16,23 @@
  */
 package org.apache.nifi.registry.db.repository;
 
+import org.apache.nifi.registry.db.DatabaseBaseTest;
 import org.apache.nifi.registry.db.entity.BucketEntity;
 import org.apache.nifi.registry.db.entity.FlowEntity;
+import org.apache.nifi.registry.db.entity.FlowSnapshotCount;
 import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
 import org.apache.nifi.registry.db.entity.FlowSnapshotEntityKey;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import java.util.Date;
+import java.util.List;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-public class TestFlowSnapshotRepository extends RepositoryBaseTest {
+public class TestFlowSnapshotRepository extends DatabaseBaseTest {
 
     @Autowired
     private BucketRepository bucketRepository;
@@ -106,4 +109,15 @@ public class TestFlowSnapshotRepository extends RepositoryBaseTest {
         assertNull(flowSnapshotRepository.findOne(key));
     }
 
+    @Test
+    public void testCountByFlow() {
+        final List<FlowSnapshotCount> counts = flowSnapshotRepository.countByFlow();
+        assertNotNull(counts);
+        assertEquals(1, counts.size());
+
+        final FlowSnapshotCount count = counts.get(0);
+        assertEquals("1", count.getFlowIdentifier());
+        assertEquals(3, count.getSnapshotCount());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-framework/src/test/java/org/apache/nifi/registry/service/TestRegistryService.java
----------------------------------------------------------------------
diff --git a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/service/TestRegistryService.java b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/service/TestRegistryService.java
index 2efa320..e29bbaa 100644
--- a/nifi-registry-framework/src/test/java/org/apache/nifi/registry/service/TestRegistryService.java
+++ b/nifi-registry-framework/src/test/java/org/apache/nifi/registry/service/TestRegistryService.java
@@ -30,7 +30,6 @@ import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
 import org.apache.nifi.registry.flow.VersionedProcessGroup;
 import org.apache.nifi.registry.serialization.FlowSnapshotSerializer;
 import org.apache.nifi.registry.serialization.Serializer;
-import org.apache.nifi.registry.service.params.QueryParameters;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
@@ -46,7 +45,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -137,7 +135,7 @@ public class TestRegistryService {
 
         when(metadataService.getBucketById(existingBucket.getId())).thenReturn(existingBucket);
 
-        final Bucket bucket = registryService.getBucket(existingBucket.getId(), true);
+        final Bucket bucket = registryService.getBucket(existingBucket.getId());
         assertNotNull(bucket);
         assertEquals(existingBucket.getId(), bucket.getIdentifier());
         assertEquals(existingBucket.getName(), bucket.getName());
@@ -148,7 +146,7 @@ public class TestRegistryService {
     @Test(expected = ResourceNotFoundException.class)
     public void testGetBucketDoesNotExist() {
         when(metadataService.getBucketById(any(String.class))).thenReturn(null);
-        registryService.getBucket("does-not-exist", true);
+        registryService.getBucket("does-not-exist");
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -376,7 +374,7 @@ public class TestRegistryService {
         flowEntity.setModified(new Date());
         flowEntity.setBucket(existingBucket);
 
-        when(metadataService.getFlowById(existingBucket.getId(), flowEntity.getId())).thenReturn(flowEntity);
+        when(metadataService.getFlowByIdWithSnapshotCounts(existingBucket.getId(), flowEntity.getId())).thenReturn(flowEntity);
 
         final VersionedFlow versionedFlow = registryService.getFlow(existingBucket.getId(), flowEntity.getId(), false);
         assertNotNull(versionedFlow);
@@ -388,42 +386,6 @@ public class TestRegistryService {
         assertEquals(flowEntity.getModified().getTime(), versionedFlow.getModifiedTimestamp());
     }
 
-    @Test
-    public void testGetFlows() {
-        final BucketEntity existingBucket = new BucketEntity();
-        existingBucket.setId("b1");
-        existingBucket.setName("My Bucket");
-        existingBucket.setDescription("This is my bucket");
-        existingBucket.setCreated(new Date());
-
-        final FlowEntity flowEntity1 = new FlowEntity();
-        flowEntity1.setId("flow1");
-        flowEntity1.setName("My Flow");
-        flowEntity1.setDescription("This is my flow.");
-        flowEntity1.setCreated(new Date());
-        flowEntity1.setModified(new Date());
-        flowEntity1.setBucket(existingBucket);
-
-        final FlowEntity flowEntity2 = new FlowEntity();
-        flowEntity2.setId("flow2");
-        flowEntity2.setName("My Flow 2");
-        flowEntity2.setDescription("This is my flow 2.");
-        flowEntity2.setCreated(new Date());
-        flowEntity2.setModified(new Date());
-        flowEntity2.setBucket(existingBucket);
-
-        final List<FlowEntity> flows = new ArrayList<>();
-        flows.add(flowEntity1);
-        flows.add(flowEntity2);
-
-        when(metadataService.getFlows(any(QueryParameters.class))).thenReturn(flows);
-
-        final QueryParameters queryParameters = new QueryParameters.Builder().build();
-        final List<VersionedFlow> allFlows = registryService.getFlows(queryParameters);
-        assertNotNull(allFlows);
-        assertEquals(2, allFlows.size());
-    }
-
     @Test(expected = ResourceNotFoundException.class)
     public void testGetFlowsByBucketDoesNotExist() {
         when(metadataService.getBucketById(any(String.class))).thenReturn(null);
@@ -438,6 +400,8 @@ public class TestRegistryService {
         existingBucket.setDescription("This is my bucket");
         existingBucket.setCreated(new Date());
 
+        when(metadataService.getBucketById(existingBucket.getId())).thenReturn(existingBucket);
+
         final FlowEntity flowEntity1 = new FlowEntity();
         flowEntity1.setId("flow1");
         flowEntity1.setName("My Flow");
@@ -454,12 +418,11 @@ public class TestRegistryService {
         flowEntity2.setModified(new Date());
         flowEntity2.setBucket(existingBucket);
 
-        final Set<BucketItemEntity> flows = new LinkedHashSet<>();
+        final List<FlowEntity> flows = new ArrayList<>();
         flows.add(flowEntity1);
         flows.add(flowEntity2);
-        existingBucket.setItems(flows);
 
-        when(metadataService.getBucketById(existingBucket.getId())).thenReturn(existingBucket);
+        when(metadataService.getFlowsByBucket(eq(existingBucket))).thenReturn(flows);
 
         final List<VersionedFlow> allFlows = registryService.getFlows(existingBucket.getId());
         assertNotNull(allFlows);

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java
index 59452f9..5baea4b 100644
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java
@@ -20,7 +20,6 @@ import org.apache.nifi.registry.web.api.AccessPolicyResource;
 import org.apache.nifi.registry.web.api.AccessResource;
 import org.apache.nifi.registry.web.api.BucketFlowResource;
 import org.apache.nifi.registry.web.api.BucketResource;
-import org.apache.nifi.registry.web.api.FlowResource;
 import org.apache.nifi.registry.web.api.ItemResource;
 import org.apache.nifi.registry.web.api.ResourceResource;
 import org.apache.nifi.registry.web.api.TenantResource;
@@ -78,7 +77,6 @@ public class NiFiRegistryResourceConfig extends ResourceConfig {
         register(BucketResource.class);
         register(BucketFlowResource.class);
         register(ItemResource.class);
-        register(FlowResource.class);
         register(ResourceResource.class);
         register(TenantResource.class);
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
index 8c8c493..907a63a 100644
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
+++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketResource.java
@@ -27,6 +27,7 @@ import org.apache.nifi.registry.authorization.RequestAction;
 import org.apache.nifi.registry.authorization.resource.Authorizable;
 import org.apache.nifi.registry.authorization.user.NiFiUserUtils;
 import org.apache.nifi.registry.bucket.Bucket;
+import org.apache.nifi.registry.bucket.BucketItem;
 import org.apache.nifi.registry.service.AuthorizationService;
 import org.apache.nifi.registry.service.RegistryService;
 import org.apache.nifi.registry.service.params.QueryParameters;
@@ -41,7 +42,6 @@ import org.springframework.stereotype.Component;
 import javax.ws.rs.BadRequestException;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -53,6 +53,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
@@ -121,12 +122,19 @@ public class BucketResource extends AuthorizableApplicationResource {
             final List<String> sortParameters) {
         authorizeAccess(RequestAction.READ);
 
+        final Set<String> authorizedBucketIds = getAuthorizedBucketIds();
+
+        if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) {
+            // not authorized for any bucket, return empty list of items
+            return Response.status(Response.Status.OK).entity(new ArrayList<BucketItem>()).build();
+        }
+
         final QueryParameters.Builder paramsBuilder = new QueryParameters.Builder();
         for (String sortParam : sortParameters) {
             paramsBuilder.addSort(SortParameter.fromString(sortParam));
         }
 
-        final List<Bucket> buckets = registryService.getBuckets(paramsBuilder.build());
+        final List<Bucket> buckets = registryService.getBuckets(paramsBuilder.build(), authorizedBucketIds);
         linkService.populateBucketLinks(buckets);
 
         return Response.status(Response.Status.OK).entity(buckets).build();
@@ -145,10 +153,9 @@ public class BucketResource extends AuthorizableApplicationResource {
             @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401),
             @ApiResponse(code = 403, message = HttpStatusMessages.MESSAGE_403),
             @ApiResponse(code = 404, message = HttpStatusMessages.MESSAGE_404) })
-    public Response getBucket(@PathParam("bucketId") final String bucketId,
-                              @QueryParam("verbose") @DefaultValue("false") boolean verbose) {
+    public Response getBucket(@PathParam("bucketId") final String bucketId) {
         authorizeBucketAccess(RequestAction.READ, bucketId);
-        final Bucket bucket = registryService.getBucket(bucketId, verbose);
+        final Bucket bucket = registryService.getBucket(bucketId);
         linkService.populateBucketLinks(bucket);
 
         if (bucket.getVersionedFlows() != null) {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2f752353/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java
----------------------------------------------------------------------
diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java
deleted file mode 100644
index b7a0217..0000000
--- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java
+++ /dev/null
@@ -1,128 +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.web.api;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-import org.apache.nifi.registry.authorization.Authorizer;
-import org.apache.nifi.registry.flow.VersionedFlow;
-import org.apache.nifi.registry.service.AuthorizationService;
-import org.apache.nifi.registry.service.RegistryService;
-import org.apache.nifi.registry.service.params.QueryParameters;
-import org.apache.nifi.registry.service.params.SortParameter;
-import org.apache.nifi.registry.web.link.LinkService;
-import org.apache.nifi.registry.web.response.FieldsEntity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-@Component
-@Path("/flows")
-@Api(
-        value = "/flows",
-        description = "Create named flows that can be versioned. Search for and retrieve existing flows."
-)
-public class FlowResource extends AuthorizableApplicationResource {
-
-    private static final Logger logger = LoggerFactory.getLogger(FlowResource.class);
-
-    @Context
-    UriInfo uriInfo;
-
-    private final LinkService linkService;
-
-    private final RegistryService registryService;
-
-    @Autowired
-    public FlowResource(
-            final RegistryService registryService,
-            final LinkService linkService,
-            final AuthorizationService authorizationService,
-            final Authorizer authorizer) {
-        super(authorizer, authorizationService);
-        this.registryService = registryService;
-        this.linkService = linkService;
-    }
-
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.APPLICATION_JSON)
-    @ApiOperation(
-            value = "Get metadata for all flows in all buckets that the registry has stored for which the client is authorized. The information about " +
-                    "the versions of each flow should be obtained by requesting a specific flow by id.",
-            response = VersionedFlow.class,
-            responseContainer = "List"
-    )
-    @ApiResponses({
-            @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400),
-            @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401),
-            @ApiResponse(code = 403, message = HttpStatusMessages.MESSAGE_403) })
-    public Response getAuthorizedFlows(
-            @ApiParam(value = SortParameter.API_PARAM_DESCRIPTION, format = "field:order", allowMultiple = true, example = "name:ASC")
-            @QueryParam("sort")
-            final List<String> sortParameters) {
-
-        Set<String> authorizedBucketIds = getAuthorizedBucketIds();
-
-        if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) {
-            // not authorized for any bucket, return empty list of items
-            return Response.status(Response.Status.OK).entity(new ArrayList<VersionedFlow>()).build();
-        }
-
-        final QueryParameters.Builder paramsBuilder = new QueryParameters.Builder();
-        for (String sortParam : sortParameters) {
-            paramsBuilder.addSort(SortParameter.fromString(sortParam));
-        }
-
-        final List<VersionedFlow> flows = registryService.getFlows(paramsBuilder.build(), authorizedBucketIds);
-        linkService.populateFlowLinks(flows);
-
-        return Response.status(Response.Status.OK).entity(flows).build();
-    }
-
-    @GET
-    @Path("fields")
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.APPLICATION_JSON)
-    @ApiOperation(
-            value = "Retrieves the available field names that can be used for searching or sorting on flows.",
-            response = FieldsEntity.class
-    )
-    public Response getAvailableFlowFields() {
-        final Set<String> flowFields = registryService.getFlowFields();
-        final FieldsEntity fieldsEntity = new FieldsEntity(flowFields);
-        return Response.status(Response.Status.OK).entity(fieldsEntity).build();
-    }
-
-}


Mime
View raw message