NIFIREG-63 Added ability to get latest snapshot metadata - Created a way to retrieve latest snapshot directly from the DB - Increased sizes of DB columns to avoid hitting max sizes - Improving error messages returned from NiFiRegistryClient to include the underlying response from the server This closes #48. Signed-off-by: Bryan Bende Project: http://git-wip-us.apache.org/repos/asf/nifi-registry/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi-registry/commit/be2b013b Tree: http://git-wip-us.apache.org/repos/asf/nifi-registry/tree/be2b013b Diff: http://git-wip-us.apache.org/repos/asf/nifi-registry/diff/be2b013b Branch: refs/heads/master Commit: be2b013bf6d73928145d9dacf8474af174454ac8 Parents: b2ff7b5 Author: Bryan Bende Authored: Tue Dec 5 10:13:26 2017 -0500 Committer: Bryan Bende Committed: Thu Dec 7 14:38:05 2017 -0500 ---------------------------------------------------------------------- .../registry/client/FlowSnapshotClient.java | 11 +++ .../client/impl/AbstractJerseyClient.java | 15 +++- .../client/impl/JerseyFlowSnapshotClient.java | 20 +++++ .../registry/db/DatabaseMetadataService.java | 13 +++ .../db/repository/FlowSnapshotRepository.java | 3 + .../nifi/registry/service/MetadataService.java | 10 ++- .../nifi/registry/service/RegistryService.java | 85 +++++++++++++------- .../db/migration/V1.2__IncreaseColumnSizes.sql | 25 ++++++ .../db/TestDatabaseMetadataService.java | 11 +++ .../repository/TestFlowSnapshotRepository.java | 10 +++ .../registry/web/api/BucketFlowResource.java | 42 ++++++++-- .../web/api/UnsecuredNiFiRegistryClientIT.java | 15 ++++ 12 files changed, 225 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/FlowSnapshotClient.java ---------------------------------------------------------------------- diff --git a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/FlowSnapshotClient.java b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/FlowSnapshotClient.java index 48d1877..1141753 100644 --- a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/FlowSnapshotClient.java +++ b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/FlowSnapshotClient.java @@ -64,6 +64,17 @@ public interface FlowSnapshotClient { VersionedFlowSnapshot getLatest(String bucketId, String flowId) throws NiFiRegistryException, IOException; /** + * Gets the latest snapshot metadata for the given flow. + * + * @param bucketId the bucket id + * @param flowId the flow id + * @return the snapshot metadata for the latest version of the given flow + * @throws NiFiRegistryException if an error is encountered other than IOException + * @throws IOException if an I/O error is encountered + */ + VersionedFlowSnapshotMetadata getLatestMetadata(String bucketId, String flowId) throws NiFiRegistryException, IOException; + + /** * Gets a list of the metadata for all snapshots of a given flow. * * The contents of each snapshot are not part of the response. http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/AbstractJerseyClient.java ---------------------------------------------------------------------- diff --git a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/AbstractJerseyClient.java b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/AbstractJerseyClient.java index b31cdfa..479699e 100644 --- a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/AbstractJerseyClient.java +++ b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/AbstractJerseyClient.java @@ -18,8 +18,10 @@ package org.apache.nifi.registry.client.impl; import org.apache.nifi.registry.client.NiFiRegistryException; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -69,14 +71,25 @@ public class AbstractJerseyClient { return action.execute(); } catch (final Exception e) { final Throwable ioeCause = getIOExceptionCause(e); + if (ioeCause == null) { - throw new NiFiRegistryException(errorMessage, e); + final StringBuilder errorMessageBuilder = new StringBuilder(errorMessage); + + // see if we have a WebApplicationException, and if so add the response body to the error message + if (e instanceof WebApplicationException) { + final Response response = ((WebApplicationException) e).getResponse(); + final String responseBody = response.readEntity(String.class); + errorMessageBuilder.append(": ").append(responseBody); + } + + throw new NiFiRegistryException(errorMessageBuilder.toString(), e); } else { throw (IOException) ioeCause; } } } + /** * An action to execute with the given return type. * http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyFlowSnapshotClient.java ---------------------------------------------------------------------- diff --git a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyFlowSnapshotClient.java b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyFlowSnapshotClient.java index bf9ad2d..deddd5e 100644 --- a/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyFlowSnapshotClient.java +++ b/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyFlowSnapshotClient.java @@ -126,6 +126,26 @@ public class JerseyFlowSnapshotClient extends AbstractJerseyClient implements Fl } @Override + public VersionedFlowSnapshotMetadata getLatestMetadata(String bucketId, String flowId) throws NiFiRegistryException, IOException { + if (StringUtils.isBlank(bucketId)) { + throw new IllegalArgumentException("Bucket Identifier cannot be blank"); + } + + if (StringUtils.isBlank(flowId)) { + throw new IllegalArgumentException("Flow Identifier cannot be blank"); + } + + return executeAction("Error retrieving latest snapshot metadata", () -> { + final WebTarget target = flowSnapshotTarget + .path("/latest/metadata") + .resolveTemplate("bucketId", bucketId) + .resolveTemplate("flowId", flowId); + + return getRequestBuilder(target).get(VersionedFlowSnapshotMetadata.class); + }); + } + + @Override @SuppressWarnings("unchecked") public List getSnapshotMetadata(final String bucketId, final String flowId) throws NiFiRegistryException, IOException { http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 3f0373a..6f8415f 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 @@ -375,6 +375,19 @@ public class DatabaseMetadataService implements MetadataService { } @Override + public FlowSnapshotEntity getLatestSnapshot(final FlowEntity flowEntity) { + if (flowEntity == null) { + return null; + } + + final FlowSnapshotEntity flowSnapshot = flowSnapshotRepository.findFirstByFlowOrderByIdVersionDesc(flowEntity); + if (flowSnapshot == null) { + return null; + } + return flowSnapshot; + } + + @Override public void deleteFlowSnapshot(final FlowSnapshotEntity flowSnapshot) { flowSnapshotRepository.delete(flowSnapshot); } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 817048f..255a511 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,6 +16,7 @@ */ package org.apache.nifi.registry.db.repository; +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; @@ -32,4 +33,6 @@ public interface FlowSnapshotRepository extends PagingAndSortingRepository countByFlow(); + FlowSnapshotEntity findFirstByFlowOrderByIdVersionDesc(FlowEntity flowEntity); + } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 1c6e918..0613aa5 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 @@ -179,7 +179,7 @@ public interface MetadataService { /** * Retrieves the snapshot for the given flow identifier and snapshot version. * - * @param bucketIdentifier the identifier of the bucket storign the flow + * @param bucketIdentifier the identifier of the bucket storing the flow * @param flowIdentifier the identifier of the flow the snapshot belongs to * @param version the version of the snapshot * @return the versioned flow snapshot for the given flow identifier and version, or null if none exists @@ -187,6 +187,14 @@ public interface MetadataService { FlowSnapshotEntity getFlowSnapshot(String bucketIdentifier, String flowIdentifier, Integer version); /** + * Retrieves the snapshot with the latest version number for the given flow in the given bucket. + * + * @param flowEntity the flow to retrieve the latest snapshot for + * @return the latest snapshot for the flow, or null if one doesn't exist + */ + FlowSnapshotEntity getLatestSnapshot(FlowEntity flowEntity); + + /** * Deletes the flow snapshot. * * @param flowSnapshot the flow snapshot to delete http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 348518f..7021f38 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 @@ -130,14 +130,14 @@ public class RegistryService { public Bucket getBucket(final String bucketIdentifier) { if (bucketIdentifier == null) { - throw new IllegalArgumentException("Bucket Identifier cannot be null"); + throw new IllegalArgumentException("Bucket identifier cannot be null"); } readLock.lock(); try { final BucketEntity bucket = metadataService.getBucketById(bucketIdentifier); if (bucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketIdentifier); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketIdentifier); } return DataModelMapper.map(bucket); @@ -172,7 +172,7 @@ public class RegistryService { } if (bucket.getIdentifier() == null) { - throw new IllegalArgumentException("Bucket Identifier cannot be null"); + throw new IllegalArgumentException("Bucket identifier cannot be null"); } writeLock.lock(); @@ -180,7 +180,7 @@ public class RegistryService { // ensure a bucket with the given id exists final BucketEntity existingBucketById = metadataService.getBucketById(bucket.getIdentifier()); if (existingBucketById == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucket.getIdentifier()); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucket.getIdentifier()); } // ensure a different bucket with the same name does not exist @@ -190,7 +190,7 @@ public class RegistryService { if (bucketsWithSameName != null) { for (final BucketEntity bucketWithSameName : bucketsWithSameName) { if (!bucketWithSameName.getId().equals(existingBucketById.getId())){ - throw new IllegalStateException("A bucket with the same name already exists: " + bucket.getName()); + throw new IllegalStateException("A bucket with the same name already exists - " + bucket.getName()); } } } @@ -215,7 +215,7 @@ public class RegistryService { public Bucket deleteBucket(final String bucketIdentifier) { if (bucketIdentifier == null) { - throw new IllegalArgumentException("Bucket Identifier cannot be null"); + throw new IllegalArgumentException("Bucket identifier cannot be null"); } writeLock.lock(); @@ -223,7 +223,7 @@ public class RegistryService { // ensure the bucket exists final BucketEntity existingBucket = metadataService.getBucketById(bucketIdentifier); if (existingBucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketIdentifier); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketIdentifier); } // for each flow in the bucket, delete all snapshots from the flow persistence provider @@ -244,14 +244,14 @@ public class RegistryService { public List getBucketItems(final QueryParameters queryParameters, final String bucketIdentifier) { if (bucketIdentifier == null) { - throw new IllegalArgumentException("Bucket Identifier cannot be null"); + throw new IllegalArgumentException("Bucket identifier cannot be null"); } readLock.lock(); try { final BucketEntity bucket = metadataService.getBucketById(bucketIdentifier); if (bucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketIdentifier); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketIdentifier); } final List bucketItems = new ArrayList<>(); @@ -264,7 +264,7 @@ public class RegistryService { public List getBucketItems(final QueryParameters queryParameters, final Set bucketIdentifiers) { if (bucketIdentifiers == null || bucketIdentifiers.isEmpty()) { - throw new IllegalArgumentException("Bucket Identifiers cannot be null or empty"); + throw new IllegalArgumentException("Bucket identifiers cannot be null or empty"); } readLock.lock(); @@ -290,7 +290,7 @@ public class RegistryService { public VersionedFlow createFlow(final String bucketIdentifier, final VersionedFlow versionedFlow) { if (StringUtils.isBlank(bucketIdentifier)) { - throw new IllegalArgumentException("Bucket Identifier cannot be null or blank"); + throw new IllegalArgumentException("Bucket identifier cannot be null or blank"); } if (versionedFlow == null) { @@ -318,7 +318,7 @@ public class RegistryService { // ensure the bucket exists final BucketEntity existingBucket = metadataService.getBucketById(bucketIdentifier); if (existingBucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketIdentifier); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketIdentifier); } // ensure another flow with the same name doesn't exist @@ -341,18 +341,18 @@ public class RegistryService { public VersionedFlow getFlow(final String bucketIdentifier, final String flowIdentifier) { if (StringUtils.isBlank(bucketIdentifier)) { - throw new IllegalArgumentException("Bucket Identifier Identifier cannot be null or blank"); + throw new IllegalArgumentException("Bucket identifier cannot be null or blank"); } if (StringUtils.isBlank(flowIdentifier)) { - throw new IllegalArgumentException("Flow Identifier cannot be null or blank"); + throw new IllegalArgumentException("Flow identifier cannot be null or blank"); } readLock.lock(); try { final FlowEntity flowEntity = metadataService.getFlowByIdWithSnapshotCounts(bucketIdentifier, flowIdentifier); if (flowEntity == null) { - throw new ResourceNotFoundException("VersionedFlow does not exist for identifier: " + flowIdentifier); + throw new ResourceNotFoundException("VersionedFlow does not exist for identifier " + flowIdentifier); } return DataModelMapper.map(flowEntity); @@ -363,14 +363,14 @@ public class RegistryService { public List getFlows(final String bucketId) { if (StringUtils.isBlank(bucketId)) { - throw new IllegalArgumentException("Bucket Identifier cannot be null"); + throw new IllegalArgumentException("Bucket identifier cannot be null"); } readLock.lock(); try { final BucketEntity existingBucket = metadataService.getBucketById(bucketId); if (existingBucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketId); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketId); } // return non-verbose set of flows for the given bucket @@ -399,7 +399,7 @@ public class RegistryService { // ensure a flow with the given id exists final FlowEntity existingFlow = metadataService.getFlowById(versionedFlow.getBucketIdentifier(), versionedFlow.getIdentifier()); if (existingFlow == null) { - throw new ResourceNotFoundException("VersionedFlow does not exist for identifier: " + versionedFlow.getIdentifier()); + throw new ResourceNotFoundException("VersionedFlow does not exist for identifier " + versionedFlow.getIdentifier()); } // ensure a different flow with the same name does not exist @@ -409,7 +409,7 @@ public class RegistryService { if (flowsWithSameName != null) { for (final FlowEntity flowWithSameName : flowsWithSameName) { if(!flowWithSameName.getId().equals(existingFlow.getId())) { - throw new IllegalStateException("A VersionedFlow with the same name already exists: " + versionedFlow.getName()); + throw new IllegalStateException("A VersionedFlow with the same name already exists - " + versionedFlow.getName()); } } } @@ -434,10 +434,10 @@ public class RegistryService { public VersionedFlow deleteFlow(final String bucketIdentifier, final String flowIdentifier) { if (StringUtils.isBlank(bucketIdentifier)) { - throw new IllegalArgumentException("Bucket Identifier cannot be null or blank"); + throw new IllegalArgumentException("Bucket identifier cannot be null or blank"); } if (StringUtils.isBlank(flowIdentifier)) { - throw new IllegalArgumentException("Flow Identifier cannot be null or blank"); + throw new IllegalArgumentException("Flow identifier cannot be null or blank"); } writeLock.lock(); @@ -445,7 +445,7 @@ public class RegistryService { // ensure the flow exists final FlowEntity existingFlow = metadataService.getFlowById(bucketIdentifier, flowIdentifier); if (existingFlow == null) { - throw new ResourceNotFoundException("VersionedFlow does not exist for identifier: " + flowIdentifier); + throw new ResourceNotFoundException("VersionedFlow does not exist for identifier " + flowIdentifier); } // delete all snapshots from the flow persistence provider @@ -485,13 +485,13 @@ public class RegistryService { // ensure the bucket exists final BucketEntity existingBucket = metadataService.getBucketById(snapshotMetadata.getBucketIdentifier()); if (existingBucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + snapshotMetadata.getBucketIdentifier()); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + snapshotMetadata.getBucketIdentifier()); } // ensure the flow exists, we need to use "with counts" here so we can return this is a part of the response final FlowEntity existingFlow = metadataService.getFlowByIdWithSnapshotCounts(snapshotMetadata.getBucketIdentifier(), snapshotMetadata.getFlowIdentifier()); if (existingFlow == null) { - throw new ResourceNotFoundException("VersionedFlow does not exist for identifier: " + snapshotMetadata.getFlowIdentifier()); + throw new ResourceNotFoundException("VersionedFlow does not exist for identifier " + snapshotMetadata.getFlowIdentifier()); } // convert the set of FlowSnapshotEntity to set of VersionedFlowSnapshotMetadata @@ -560,7 +560,7 @@ public class RegistryService { // we need to populate the version count here so we have to do this retrieval instead of snapshotEntity.getFlow() final FlowEntity flowEntityWithCount = metadataService.getFlowByIdWithSnapshotCounts(bucketIdentifier, flowIdentifier); if (flowEntityWithCount == null) { - throw new ResourceNotFoundException("VersionedFlow does not exist for flow " + flowIdentifier); + throw new ResourceNotFoundException("VersionedFlow does not exist with identifier " + flowIdentifier); } // ensure the snapshot exists @@ -619,13 +619,13 @@ public class RegistryService { // ensure the bucket exists final BucketEntity existingBucket = metadataService.getBucketById(bucketIdentifier); if (existingBucket == null) { - throw new ResourceNotFoundException("Bucket does not exist for identifier: " + bucketIdentifier); + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketIdentifier); } // ensure the flow exists final FlowEntity existingFlow = metadataService.getFlowById(bucketIdentifier, flowIdentifier); if (existingFlow == null) { - throw new ResourceNotFoundException("VersionedFlow does not exist for identifier: " + flowIdentifier); + throw new ResourceNotFoundException("VersionedFlow does not exist for identifier " + flowIdentifier); } // convert the set of FlowSnapshotEntity to set of VersionedFlowSnapshotMetadata, ordered by version descending @@ -641,6 +641,37 @@ public class RegistryService { } } + public VersionedFlowSnapshotMetadata getLatestFlowSnapshotMetadata(final String bucketIdentifier, final String flowIdentifier) { + if (StringUtils.isBlank(bucketIdentifier)) { + throw new IllegalArgumentException("Bucket identifier cannot be null or blank"); + } + + if (StringUtils.isBlank(flowIdentifier)) { + throw new IllegalArgumentException("Flow identifier cannot be null or blank"); + } + + readLock.lock(); + try { + // ensure the bucket exists + final BucketEntity existingBucket = metadataService.getBucketById(bucketIdentifier); + if (existingBucket == null) { + throw new ResourceNotFoundException("Bucket does not exist for identifier " + bucketIdentifier); + } + + // ensure the flow exists + final FlowEntity existingFlow = metadataService.getFlowById(bucketIdentifier, flowIdentifier); + if (existingFlow == null) { + throw new ResourceNotFoundException("VersionedFlow does not exist for identifier " + flowIdentifier); + } + + // get latest snapshot for the flow + final FlowSnapshotEntity latestSnapshot = metadataService.getLatestSnapshot(existingFlow); + return DataModelMapper.map(latestSnapshot); + } finally { + readLock.unlock(); + } + } + public VersionedFlowSnapshotMetadata deleteFlowSnapshot(final String bucketIdentifier, final String flowIdentifier, final Integer version) { if (StringUtils.isBlank(bucketIdentifier)) { throw new IllegalArgumentException("Bucket identifier cannot be null or blank"); http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/nifi-registry-framework/src/main/resources/db/migration/V1.2__IncreaseColumnSizes.sql ---------------------------------------------------------------------- diff --git a/nifi-registry-framework/src/main/resources/db/migration/V1.2__IncreaseColumnSizes.sql b/nifi-registry-framework/src/main/resources/db/migration/V1.2__IncreaseColumnSizes.sql new file mode 100644 index 0000000..b2e92d5 --- /dev/null +++ b/nifi-registry-framework/src/main/resources/db/migration/V1.2__IncreaseColumnSizes.sql @@ -0,0 +1,25 @@ +-- 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. + +ALTER TABLE BUCKET ALTER COLUMN NAME VARCHAR2(1000); +ALTER TABLE BUCKET ALTER COLUMN DESCRIPTION VARCHAR2(65535); + +ALTER TABLE BUCKET_ITEM ALTER COLUMN NAME VARCHAR2(1000); +ALTER TABLE BUCKET_ITEM ALTER COLUMN DESCRIPTION VARCHAR2(65535); + +ALTER TABLE FLOW_SNAPSHOT ALTER COLUMN CREATED_BY VARCHAR2(4096); +ALTER TABLE FLOW_SNAPSHOT ALTER COLUMN COMMENTS VARCHAR2(65535); + +ALTER TABLE SIGNING_KEY ALTER COLUMN TENANT_IDENTITY VARCHAR2(4096); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 4fab280..b07e4ed 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 @@ -20,6 +20,7 @@ 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.service.QueryParameters; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -101,4 +102,14 @@ public class TestDatabaseMetadataService extends DatabaseBaseTest { assertEquals(3, flowEntity.getSnapshotCount()); } + @Test + public void testGetLatestSnapshot() { + final FlowEntity flowEntity = metadataService.getFlowById("1", "1"); + assertNotNull(flowEntity); + + final FlowSnapshotEntity flowSnapshotEntity = metadataService.getLatestSnapshot(flowEntity); + assertNotNull(flowSnapshotEntity); + assertEquals(3, flowSnapshotEntity.getId().getVersion().intValue()); + } + } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 2dc74b9..c6bd827 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 @@ -121,4 +121,14 @@ public class TestFlowSnapshotRepository extends DatabaseBaseTest { assertEquals(3, count.getSnapshotCount()); } + @Test + public void testFindFirstByFlow() { + final FlowEntity flowEntity = flowRepository.findById("1").orElse(null); + assertNotNull(flowEntity); + + final FlowSnapshotEntity latest = flowSnapshotRepository.findFirstByFlowOrderByIdVersionDesc(flowEntity); + assertNotNull(latest); + assertEquals(3, latest.getId().getVersion().intValue()); + } + } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java index c8a8844..2b10919 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java @@ -325,20 +325,50 @@ public class BucketFlowResource extends AuthorizableApplicationResource { authorizeBucketAccess(RequestAction.READ, bucketId); - final SortedSet snapshots = registryService.getFlowSnapshots(bucketId, flowId); - if (snapshots == null || snapshots.size() == 0) { - throw new ResourceNotFoundException("Not flow versions found for flow with id " + flowId); + final VersionedFlowSnapshotMetadata latest = registryService.getLatestFlowSnapshotMetadata(bucketId, flowId); + if (latest == null) { + throw new ResourceNotFoundException("No flow versions found for flow with id " + flowId); } - final VersionedFlowSnapshotMetadata lastSnapshotMetadata = snapshots.first(); - - final VersionedFlowSnapshot lastSnapshot = registryService.getFlowSnapshot(bucketId, flowId, lastSnapshotMetadata.getVersion()); + final VersionedFlowSnapshot lastSnapshot = registryService.getFlowSnapshot(bucketId, flowId, latest.getVersion()); populateLinks(lastSnapshot); return Response.status(Response.Status.OK).entity(lastSnapshot).build(); } @GET + @Path("{flowId}/versions/latest/metadata") + @Consumes(MediaType.WILDCARD) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + value = "Get the metadata for the latest version of a flow", + response = VersionedFlowSnapshotMetadata.class + ) + @ApiResponses({ + @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401), + @ApiResponse(code = 403, message = HttpStatusMessages.MESSAGE_403), + @ApiResponse(code = 404, message = HttpStatusMessages.MESSAGE_404), + @ApiResponse(code = 409, message = HttpStatusMessages.MESSAGE_409) }) + public Response getLatestFlowVersionMetadata( + @PathParam("bucketId") + @ApiParam("The bucket identifier") + final String bucketId, + @PathParam("flowId") + @ApiParam("The flow identifier") + final String flowId) { + + authorizeBucketAccess(RequestAction.READ, bucketId); + + final VersionedFlowSnapshotMetadata latest = registryService.getLatestFlowSnapshotMetadata(bucketId, flowId); + if (latest == null) { + throw new ResourceNotFoundException("No flow versions found for flow with id " + flowId); + } + + linkService.populateSnapshotLinks(latest); + return Response.status(Response.Status.OK).entity(latest).build(); + } + + @GET @Path("{flowId}/versions/{versionNumber: \\d+}") @Consumes(MediaType.WILDCARD) @Produces(MediaType.APPLICATION_JSON) http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/be2b013b/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 bcc2c0a..8a2a920 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 @@ -237,8 +237,23 @@ public class UnsecuredNiFiRegistryClientIT extends UnsecuredITBase { final List retrievedMetadata = snapshotClient.getSnapshotMetadata(snapshotFlow.getBucketIdentifier(), snapshotFlow.getIdentifier()); Assert.assertNotNull(retrievedMetadata); Assert.assertEquals(2, retrievedMetadata.size()); + Assert.assertEquals(2, retrievedMetadata.get(0).getVersion()); + Assert.assertEquals(1, retrievedMetadata.get(1).getVersion()); retrievedMetadata.stream().forEach(s -> LOGGER.info("Retrieved snapshot metadata " + s.getVersion())); + // get latest metadata + final VersionedFlowSnapshotMetadata latestMetadata = snapshotClient.getLatestMetadata(snapshotFlow.getBucketIdentifier(), snapshotFlow.getIdentifier()); + Assert.assertNotNull(latestMetadata); + Assert.assertEquals(2, latestMetadata.getVersion()); + + // get latest metadata that doesn't exist + try { + snapshotClient.getLatestMetadata(snapshotFlow.getBucketIdentifier(), "DOES-NOT-EXIST"); + Assert.fail("Should have thrown exception"); + } catch (NiFiRegistryException nfe) { + Assert.assertEquals("Error retrieving latest snapshot metadata: VersionedFlow does not exist for identifier DOES-NOT-EXIST", nfe.getMessage()); + } + // ---------------------- TEST ITEMS --------------------------// final ItemsClient itemsClient = client.getItemsClient();