Repository: nifi-registry
Updated Branches:
  refs/heads/master f2d712f32 -> 2e35235d5


NIFIREG-73 Making flow/item name be unique per bucket instead of globally. This 
closes #59


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

Branch: refs/heads/master
Commit: 2e35235d5cfc094f0120b6a77db4c1d1c3f15721
Parents: f2d712f
Author: Bryan Bende <[email protected]>
Authored: Fri Dec 15 13:25:24 2017 -0500
Committer: Matt Gilman <[email protected]>
Committed: Mon Dec 18 10:28:44 2017 -0500

----------------------------------------------------------------------
 .../nifi/registry/client/ItemsClient.java       | 22 ---------
 .../registry/client/impl/JerseyItemsClient.java | 31 ++----------
 .../registry/db/DatabaseMetadataService.java    | 42 +++++++++++++++-
 .../registry/db/entity/BucketItemEntity.java    | 10 ++++
 .../db/mapper/BucketItemEntityRowMapper.java    |  1 +
 .../nifi/registry/service/DataModelMapper.java  |  2 +
 .../nifi/registry/service/MetadataService.java  |  9 ++++
 .../nifi/registry/service/RegistryService.java  |  8 +--
 .../V1.3__DropBucketItemNameUniqueness.sql      | 27 +++++++++++
 .../db/TestDatabaseMetadataService.java         | 18 +++++++
 .../registry/service/TestRegistryService.java   |  4 +-
 .../db/migration/V999999.1__test-setup.sql      |  6 +--
 .../apache/nifi/registry/web/api/FlowsIT.java   | 51 ++++++++++++++++++++
 .../web/api/UnsecuredNiFiRegistryClientIT.java  | 16 ++----
 .../registry/nf-registry-grid-list-viewer.html  |  2 +-
 15 files changed, 174 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ItemsClient.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ItemsClient.java
 
b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ItemsClient.java
index f862f03..96fa801 100644
--- 
a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ItemsClient.java
+++ 
b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ItemsClient.java
@@ -18,7 +18,6 @@ package org.apache.nifi.registry.client;
 
 import org.apache.nifi.registry.bucket.BucketItem;
 import org.apache.nifi.registry.field.Fields;
-import org.apache.nifi.registry.params.SortParameter;
 
 import java.io.IOException;
 import java.util.List;
@@ -44,16 +43,6 @@ public interface ItemsClient {
     List<BucketItem> getAll() throws NiFiRegistryException, IOException;
 
     /**
-     * Gets all bucket items in the registry in sorted order.
-     *
-     * @param sortParameters the sort parameters
-     * @return the sorted list of items
-     * @throws NiFiRegistryException if an error is encountered other than 
IOException
-     * @throws IOException if an I/O error is encountered
-     */
-    List<BucketItem> getAll(List<SortParameter> sortParameters) throws 
NiFiRegistryException, IOException;
-
-    /**
      * Gets all bucket items for the given bucket.
      *
      * @param bucketId the bucket id
@@ -64,17 +53,6 @@ public interface ItemsClient {
     List<BucketItem> getByBucket(String bucketId) throws 
NiFiRegistryException, IOException;
 
     /**
-     * Gets all bucket items in the given bucket in sorted order.
-     *
-     * @param bucketId the bucket id
-     * @param sortParameters the sort parameters
-     * @return the list of items
-     * @throws NiFiRegistryException if an error is encountered other than 
IOException
-     * @throws IOException if an I/O error is encountered
-     */
-    List<BucketItem> getByBucket(String bucketId, List<SortParameter> 
sortParameters) throws NiFiRegistryException, IOException;
-
-    /**
      * Gets the field info for bucket items.
      *
      * @return the list of field info

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyItemsClient.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyItemsClient.java
 
b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyItemsClient.java
index 05fb613..6b01fc4 100644
--- 
a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyItemsClient.java
+++ 
b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyItemsClient.java
@@ -21,7 +21,6 @@ import org.apache.nifi.registry.bucket.BucketItem;
 import org.apache.nifi.registry.client.ItemsClient;
 import org.apache.nifi.registry.client.NiFiRegistryException;
 import org.apache.nifi.registry.field.Fields;
-import org.apache.nifi.registry.params.SortParameter;
 
 import javax.ws.rs.client.WebTarget;
 import java.io.IOException;
@@ -46,53 +45,29 @@ public class JerseyItemsClient extends AbstractJerseyClient 
implements ItemsClie
         this.itemsTarget = baseTarget.path("/items");
     }
 
-    @Override
-    public List<BucketItem> getAll() throws NiFiRegistryException, IOException 
{
-        return getAll(Collections.emptyList());
-    }
 
-    @Override
-    public List<BucketItem> getAll(final List<SortParameter> sorts) throws 
NiFiRegistryException, IOException {
-        if (sorts == null) {
-            throw new IllegalArgumentException("Sort Parameters cannot be 
null");
-        }
 
+    @Override
+    public List<BucketItem> getAll() throws NiFiRegistryException, IOException 
{
         return executeAction("", () -> {
             WebTarget target = itemsTarget;
-            for (final SortParameter sortParam : sorts) {
-                target = target.queryParam("sort", sortParam.toString());
-            }
-
             final BucketItem[] bucketItems = 
getRequestBuilder(target).get(BucketItem[].class);
             return bucketItems == null ? Collections.emptyList() : 
Arrays.asList(bucketItems);
         });
     }
 
     @Override
-    public List<BucketItem> getByBucket(final String bucketId) throws 
NiFiRegistryException, IOException {
-        return getByBucket(bucketId, Collections.emptyList());
-    }
-
-    @Override
-    public List<BucketItem> getByBucket(final String bucketId, final 
List<SortParameter> sorts)
+    public List<BucketItem> getByBucket(final String bucketId)
             throws NiFiRegistryException, IOException {
         if (StringUtils.isBlank(bucketId)) {
             throw new IllegalArgumentException("Bucket Identifier cannot be 
blank");
         }
 
-        if (sorts == null) {
-            throw new IllegalArgumentException("Sort Parameters cannot be 
null");
-        }
-
         return executeAction("", () -> {
             WebTarget target = itemsTarget
                     .path("/{bucketId}")
                     .resolveTemplate("bucketId", bucketId);
 
-            for (final SortParameter sortParam : sorts) {
-                target = target.queryParam("sort", sortParam.toString());
-            }
-
             final BucketItem[] bucketItems = 
getRequestBuilder(target).get(BucketItem[].class);
             return bucketItems == null ? Collections.emptyList() : 
Arrays.asList(bucketItems);
         });

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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 1481ccd..a3fe74f 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
@@ -129,7 +129,23 @@ public class DatabaseMetadataService implements 
MetadataService {
 
     @Override
     public List<BucketItemEntity> getBucketItems(final String 
bucketIdentifier) {
-        final String sql = "SELECT * FROM bucket_item WHERE bucket_id = ?";
+        final String sql =
+                "SELECT " +
+                    "item.id as ID, " +
+                    "item.name as NAME, " +
+                    "item.description as DESCRIPTION, " +
+                    "item.created as CREATED, " +
+                    "item.modified as MODIFIED, " +
+                    "item.item_type as ITEM_TYPE, " +
+                    "b.id as BUCKET_ID, " +
+                    "b.name as BUCKET_NAME " +
+                "FROM " +
+                        "bucket_item item, bucket b " +
+                "WHERE " +
+                        "item.bucket_id = b.id " +
+                "AND " +
+                        "item.bucket_id = ?";
+
         final List<BucketItemEntity> items = jdbcTemplate.query(sql, new 
Object[] { bucketIdentifier }, new BucketItemEntityRowMapper());
         return getItemsWithCounts(items);
     }
@@ -140,7 +156,23 @@ public class DatabaseMetadataService implements 
MetadataService {
             return Collections.emptyList();
         }
 
-        final StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM 
bucket_item WHERE bucket_id IN (");
+        final StringBuilder sqlBuilder = new StringBuilder(
+                "SELECT " +
+                        "item.id as ID, " +
+                        "item.name as NAME, " +
+                        "item.description as DESCRIPTION, " +
+                        "item.created as CREATED, " +
+                        "item.modified as MODIFIED, " +
+                        "item.item_type as ITEM_TYPE, " +
+                        "b.id as BUCKET_ID, " +
+                        "b.name as BUCKET_NAME " +
+                "FROM " +
+                        "bucket_item item, bucket b " +
+                "WHERE " +
+                        "item.bucket_id = b.id " +
+                "AND " +
+                        "item.bucket_id IN (");
+
         for (int i=0; i < bucketIds.size(); i++) {
             if (i > 0) {
                 sqlBuilder.append(", ");
@@ -244,6 +276,12 @@ public class DatabaseMetadataService implements 
MetadataService {
     }
 
     @Override
+    public List<FlowEntity> getFlowsByName(final String bucketIdentifier, 
final String name) {
+        final String sql = "SELECT * FROM flow f, bucket_item item WHERE 
item.name = ? AND item.id = f.id AND item.bucket_id = ?";
+        return jdbcTemplate.query(sql, new Object[] {name, bucketIdentifier}, 
new FlowEntityRowMapper());
+    }
+
+    @Override
     public List<FlowEntity> getFlowsByBucket(final String bucketIdentifier) {
         final String sql = "SELECT * FROM flow f, bucket_item item WHERE 
item.bucket_id = ? AND item.id = f.id";
         final List<FlowEntity> flows = jdbcTemplate.query(sql, new Object[] 
{bucketIdentifier}, new FlowEntityRowMapper());

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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
index 0c61a26..cdfa963 100644
--- 
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
@@ -36,6 +36,8 @@ public class BucketItemEntity {
 
     private String bucketId;
 
+    private String bucketName;
+
 
     public String getId() {
         return id;
@@ -93,6 +95,14 @@ public class BucketItemEntity {
         this.bucketId = bucketId;
     }
 
+    public String getBucketName() {
+        return bucketName;
+    }
+
+    public void setBucketName(String bucketName) {
+        this.bucketName = bucketName;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hashCode(this.id);

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketItemEntityRowMapper.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketItemEntityRowMapper.java
 
b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketItemEntityRowMapper.java
index 2ebe094..7b3df05 100644
--- 
a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketItemEntityRowMapper.java
+++ 
b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketItemEntityRowMapper.java
@@ -51,6 +51,7 @@ public class BucketItemEntityRowMapper implements 
RowMapper<BucketItemEntity> {
         item.setCreated(rs.getTimestamp("CREATED"));
         item.setModified(rs.getTimestamp("MODIFIED"));
         item.setBucketId(rs.getString("BUCKET_ID"));
+        item.setBucketName(rs.getString("BUCKET_NAME"));
         item.setType(type);
         return item;
     }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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 80c8582..1dbf49a 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
@@ -78,6 +78,8 @@ public class DataModelMapper {
 
         if (bucketEntity != null) {
             versionedFlow.setBucketName(bucketEntity.getName());
+        } else {
+            versionedFlow.setBucketName(flowEntity.getBucketName());
         }
 
         return versionedFlow;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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 453271a..ea0b214 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
@@ -138,6 +138,15 @@ public interface MetadataService {
     List<FlowEntity> getFlowsByName(String name);
 
     /**
+     * Retrieves the versioned flows with the given name in the given bucket. 
The name comparison must be case-insensitive.
+     *
+     * @param  bucketIdentifier the identifier of the bucket
+     * @param name the name of the flow to retrieve
+     * @return the versioned flows with the given name in the given bucket, or 
empty list if no flows with the given name exists
+     */
+    List<FlowEntity> getFlowsByName(String bucketIdentifier, String name);
+
+    /**
      * Retrieves the versioned flows for the given bucket.
      *
      * @param bucketIdentifier the bucket id to retrieve flows for

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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 1717776..8a96d20 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
@@ -323,9 +323,9 @@ public class RegistryService {
             }
 
             // ensure another flow with the same name doesn't exist
-            final List<FlowEntity> flowsWithSameName = 
metadataService.getFlowsByName(versionedFlow.getName());
+            final List<FlowEntity> flowsWithSameName = 
metadataService.getFlowsByName(existingBucket.getId(), versionedFlow.getName());
             if (flowsWithSameName != null && flowsWithSameName.size() > 0) {
-                throw new IllegalStateException("A versioned flow with the 
same name already exists");
+                throw new IllegalStateException("A versioned flow with the 
same name already exists in the selected bucket");
             }
 
             // convert from dto to entity and set the bucket relationship
@@ -425,11 +425,11 @@ public class RegistryService {
             // ensure a different flow with the same name does not exist
             // since we're allowing partial updates here, only check this if a 
non-null name is provided
             if (StringUtils.isNotBlank(versionedFlow.getName())) {
-                final List<FlowEntity> flowsWithSameName = 
metadataService.getFlowsByName(versionedFlow.getName());
+                final List<FlowEntity> flowsWithSameName = 
metadataService.getFlowsByName(existingBucket.getId(), versionedFlow.getName());
                 if (flowsWithSameName != null) {
                     for (final FlowEntity flowWithSameName : 
flowsWithSameName) {
                          
if(!flowWithSameName.getId().equals(existingFlow.getId())) {
-                            throw new IllegalStateException("A versioned flow 
with the same name already exists - " + versionedFlow.getName());
+                            throw new IllegalStateException("A versioned flow 
with the same name already exists in the selected bucket");
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-framework/src/main/resources/db/migration/V1.3__DropBucketItemNameUniqueness.sql
----------------------------------------------------------------------
diff --git 
a/nifi-registry-framework/src/main/resources/db/migration/V1.3__DropBucketItemNameUniqueness.sql
 
b/nifi-registry-framework/src/main/resources/db/migration/V1.3__DropBucketItemNameUniqueness.sql
new file mode 100644
index 0000000..f29b4d0
--- /dev/null
+++ 
b/nifi-registry-framework/src/main/resources/db/migration/V1.3__DropBucketItemNameUniqueness.sql
@@ -0,0 +1,27 @@
+-- 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.
+
+CREATE ALIAS IF NOT EXISTS EXECUTE AS $$ void executeSql(Connection conn, 
String sql)
+throws SQLException { conn.createStatement().executeUpdate(sql); } $$;
+
+call execute('ALTER TABLE BUCKET_ITEM DROP CONSTRAINT ' ||
+    (
+     SELECT DISTINCT CONSTRAINT_NAME
+     FROM INFORMATION_SCHEMA.CONSTRAINTS
+     WHERE TABLE_NAME = 'BUCKET_ITEM'
+     AND COLUMN_LIST = 'NAME'
+     AND CONSTRAINT_TYPE = 'UNIQUE'
+     )
+);

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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
index dfdeef4..35ba757 100644
--- 
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
@@ -150,6 +150,8 @@ public class TestDatabaseMetadataService extends 
DatabaseBaseTest {
         final List<BucketItemEntity> items = 
metadataService.getBucketItems(bucket.getId());
         assertNotNull(items);
         assertEquals(2, items.size());
+
+        items.stream().forEach(i -> assertNotNull(i.getBucketName()));
     }
 
     @Test
@@ -157,6 +159,8 @@ public class TestDatabaseMetadataService extends 
DatabaseBaseTest {
         final List<BucketItemEntity> items = 
metadataService.getBucketItems(new HashSet<>(Arrays.asList("1", "2")));
         assertNotNull(items);
         assertEquals(3, items.size());
+
+        items.stream().forEach(i -> assertNotNull(i.getBucketName()));
     }
 
     @Test
@@ -173,6 +177,8 @@ public class TestDatabaseMetadataService extends 
DatabaseBaseTest {
 
         final FlowEntity flowEntity = (FlowEntity) item1;
         assertEquals(3, flowEntity.getSnapshotCount());
+
+        items.stream().forEach(i -> assertNotNull(i.getBucketName()));
     }
 
     @Test
@@ -189,6 +195,8 @@ public class TestDatabaseMetadataService extends 
DatabaseBaseTest {
 
         final FlowEntity flowEntity = (FlowEntity) item1;
         assertEquals(3, flowEntity.getSnapshotCount());
+
+        items.stream().forEach(i -> assertNotNull(i.getBucketName()));
     }
 
     //----------------- Flows ---------------------------------
@@ -255,8 +263,18 @@ public class TestDatabaseMetadataService extends 
DatabaseBaseTest {
     public void testGetFlowsByName() {
         final List<FlowEntity> flows = metadataService.getFlowsByName("Flow 
1");
         assertNotNull(flows);
+        assertEquals(2, flows.size());
+        assertEquals("Flow 1", flows.get(0).getName());
+        assertEquals("Flow 1", flows.get(1).getName());
+    }
+
+    @Test
+    public void testGetFlowsByNameByBucket() {
+        final List<FlowEntity> flows = 
metadataService.getFlowsByName("2","Flow 1");
+        assertNotNull(flows);
         assertEquals(1, flows.size());
         assertEquals("Flow 1", flows.get(0).getName());
+        assertEquals("2", flows.get(0).getBucketId());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/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 3d25dae..26467ca 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
@@ -318,7 +318,7 @@ public class TestRegistryService {
         flowWithSameName.setCreated(new Date());
         flowWithSameName.setModified(new Date());
 
-        
when(metadataService.getFlowsByName(flowWithSameName.getName())).thenReturn(Collections.singletonList(flowWithSameName));
+        when(metadataService.getFlowsByName(existingBucket.getId(), 
flowWithSameName.getName())).thenReturn(Collections.singletonList(flowWithSameName));
 
         final VersionedFlow versionedFlow = new VersionedFlow();
         versionedFlow.setName(flowWithSameName.getName());
@@ -478,7 +478,7 @@ public class TestRegistryService {
         otherFlow.setModified(new Date());
         otherFlow.setBucketId(existingBucket.getId());
 
-        
when(metadataService.getFlowsByName(otherFlow.getName())).thenReturn(Collections.singletonList(otherFlow));
+        when(metadataService.getFlowsByName(existingBucket.getId(), 
otherFlow.getName())).thenReturn(Collections.singletonList(otherFlow));
 
         final VersionedFlow versionedFlow = new VersionedFlow();
         versionedFlow.setIdentifier(flowToUpdate.getId());

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
----------------------------------------------------------------------
diff --git 
a/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
 
b/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
index 6a10a87..8f3cfa8 100644
--- 
a/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
+++ 
b/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
@@ -37,17 +37,17 @@ insert into bucket (id, name, description, created)
 -- test data for flows
 
 insert into bucket_item (id, name, description, created, modified, item_type, 
bucket_id)
-  values ('1', 'Flow 1', 'This is flow 1', parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), 'FLOW', '1');
+  values ('1', 'Flow 1', 'This is flow 1 bucket 1', parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), 'FLOW', '1');
 
 insert into flow (id) values ('1');
 
 insert into bucket_item (id, name, description, created, modified, item_type, 
bucket_id)
-  values ('2', 'Flow 2', 'This is flow 2', parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), 'FLOW', '1');
+  values ('2', 'Flow 2', 'This is flow 2 bucket 1', parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), 'FLOW', '1');
 
 insert into flow (id) values ('2');
 
 insert into bucket_item (id, name, description, created, modified, item_type, 
bucket_id)
-  values ('3', 'Flow 3', 'This is flow 3', parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), 'FLOW', '2');
+  values ('3', 'Flow 1', 'This is flow 1 bucket 2', parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), parsedatetime('2017-09-11 
12:56:00.000 UTC', 'yyyy-MM-dd hh:mm:ss.SSS z'), 'FLOW', '2');
 
 insert into flow (id) values ('3');
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/FlowsIT.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/FlowsIT.java
 
b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/FlowsIT.java
index 854c9c1..d0d02ce 100644
--- 
a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/FlowsIT.java
+++ 
b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/FlowsIT.java
@@ -21,10 +21,12 @@ import org.apache.nifi.registry.flow.VersionedFlow;
 import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
 import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
 import org.apache.nifi.registry.flow.VersionedProcessGroup;
+import org.junit.Assert;
 import org.junit.Test;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.springframework.test.context.jdbc.Sql;
 
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
@@ -390,4 +392,53 @@ public class FlowsIT extends UnsecuredITBase {
 
     }
 
+    @Test
+    public void testFlowNameUniquePerBucket() throws Exception {
+
+        final String flowName = "Flow 1";
+
+        // verify we have an existing flow with the name "Flow 1" in bucket 1
+        final VersionedFlow existingFlow = client
+                .target(createURL("buckets/1/flows/1"))
+                .request()
+                .get(VersionedFlow.class);
+
+        assertNotNull(existingFlow);
+        assertEquals(flowName, existingFlow.getName());
+
+        // create a new flow with the same name
+
+        final String bucketId = "3";
+
+        final VersionedFlow flow = new VersionedFlow();
+        flow.setBucketIdentifier(bucketId);
+        flow.setName(flowName);
+        flow.setDescription("This is a flow created by an integration test.");
+
+        // saving this flow to bucket 3 should work because bucket 3 is empty
+
+        final VersionedFlow createdFlow = client
+                .target(createURL("buckets/3/flows"))
+                .resolveTemplate("bucketId", bucketId)
+                .request()
+                .post(Entity.entity(flow, MediaType.APPLICATION_JSON), 
VersionedFlow.class);
+
+        assertNotNull(createdFlow);
+
+        // saving the flow to bucket 1 should not work because there is a flow 
with the same name
+        flow.setBucketIdentifier("1");
+        try {
+            client.target(createURL("buckets/1/flows"))
+                    .resolveTemplate("bucketId", bucketId)
+                    .request()
+                    .post(Entity.entity(flow, MediaType.APPLICATION_JSON), 
VersionedFlow.class);
+
+            Assert.fail("Should have thrown exception");
+        } catch (WebApplicationException e) {
+            final String errorMessage = 
e.getResponse().readEntity(String.class);
+            Assert.assertEquals("A versioned flow with the same name already 
exists in the selected bucket", errorMessage);
+        }
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
 
b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
index 184a54d..a12056b 100644
--- 
a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
+++ 
b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.registry.web.api;
 
+import org.apache.nifi.registry.authorization.CurrentUser;
 import org.apache.nifi.registry.authorization.Permissions;
 import org.apache.nifi.registry.bucket.Bucket;
 import org.apache.nifi.registry.bucket.BucketItem;
@@ -34,9 +35,6 @@ import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
 import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
 import org.apache.nifi.registry.flow.VersionedProcessGroup;
 import org.apache.nifi.registry.flow.VersionedProcessor;
-import org.apache.nifi.registry.authorization.CurrentUser;
-import org.apache.nifi.registry.params.SortOrder;
-import org.apache.nifi.registry.params.SortParameter;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,7 +44,6 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -259,22 +256,15 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
         // get all items
         final List<BucketItem> allItems = itemsClient.getAll();
         Assert.assertEquals(2, allItems.size());
+        allItems.stream().forEach(i -> 
Assert.assertNotNull(i.getBucketName()));
         allItems.stream().forEach(i -> LOGGER.info("All items, item " + 
i.getIdentifier()));
 
-        // get all items with sorting
-        final SortParameter itemsSortParam = new SortParameter("created", 
SortOrder.ASC);
-        final List<BucketItem> allItemsSorted = 
itemsClient.getAll(Arrays.asList(itemsSortParam));
-        Assert.assertEquals(2, allItemsSorted.size());
-
         // get items for bucket
         final List<BucketItem> bucketItems = 
itemsClient.getByBucket(flowsBucket.getIdentifier());
         Assert.assertEquals(2, bucketItems.size());
+        allItems.stream().forEach(i -> 
Assert.assertNotNull(i.getBucketName()));
         bucketItems.stream().forEach(i -> LOGGER.info("Items in bucket, item " 
+ i.getIdentifier()));
 
-        // get items for bucket with sorting
-        final List<BucketItem> bucketItemsSorted = 
itemsClient.getByBucket(flowsBucket.getIdentifier(), 
Arrays.asList(itemsSortParam));
-        Assert.assertEquals(2, bucketItemsSorted.size());
-
         // ---------------------- DELETE DATA --------------------------//
 
         final VersionedFlow deletedFlow1 = 
flowClient.delete(flowsBucket.getIdentifier(), flow1.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/2e35235d/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html
 
b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html
index 8e336ab..f1d58f3 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html
@@ -44,7 +44,7 @@ limitations under the License.
                             [disabled]="disabled" 
(expanded)="nfRegistryService.getDropletSnapshotMetadata(droplet)">
             <ng-template td-expansion-panel-label>
                 <div fxLayout="column" fxLayoutAlign="space-between start">
-                    <span class="md-title capitalize">{{droplet.name}}</span>
+                    <span class="md-title capitalize">{{droplet.name}} - 
{{droplet.bucketName}}</span>
                     <span class="md-subhead">{{droplet.type}}</span>
                 </div>
             </ng-template>

Reply via email to