diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java index 93416a20ba..0ececa1273 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java @@ -35,6 +35,7 @@ import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.protocol.NodeIdentifier; import org.apache.nifi.controller.Snippet; import org.apache.nifi.web.NiFiServiceFacade; +import org.apache.nifi.web.ResourceNotFoundException; import org.apache.nifi.web.Revision; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.ProcessGroupDTO; @@ -109,8 +110,6 @@ public class ProcessGroupResource extends ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(ProcessGroupResource.class); - private static final String VERBOSE = "false"; - @Context private ResourceContext resourceContext; @@ -1530,10 +1529,17 @@ public class ProcessGroupResource extends ApplicationResource { // ensure write access to the source final Authorizable source = lookup.getConnectable(connection.getSource().getId()); + if (source == null) { + throw new ResourceNotFoundException("Cannot find source component with ID [" + connection.getSource().getId() + "]"); + } source.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser()); // ensure write access to the destination final Authorizable destination = lookup.getConnectable(connection.getDestination().getId()); + if (destination == null) { + throw new ResourceNotFoundException("Cannot find destination component with ID [" + connection.getDestination().getId() + "]"); + } + destination.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser()); }); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java index 16cf03f8d7..7fc09da061 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java @@ -378,6 +378,34 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO if (!validationErrors.isEmpty()) { throw new ValidationException(validationErrors); } + + // Ensure that both the source and the destination for the connection exist. + // In the case that the source or destination is a port in a Remote Process Group, + // this is necessary because the ports can change in the background. It may still be + // possible for a port to disappear between the 'verify' stage and the creation stage, + // but this prevents the case where some nodes already know about the port while other + // nodes in the cluster do not. This is a more common case, as users may try to connect + // to the port as soon as the port is created. + final ConnectableDTO sourceDto = connectionDTO.getSource(); + if (sourceDto == null || sourceDto.getId() == null) { + throw new IllegalArgumentException("Cannot create connection without specifying source"); + } + + final ConnectableDTO destinationDto = connectionDTO.getDestination(); + if (destinationDto == null || destinationDto.getId() == null) { + throw new IllegalArgumentException("Cannot create connection without specifying destination"); + } + + final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId()); + final Connectable sourceConnectable = rootGroup.findConnectable(sourceDto.getId()); + if (sourceConnectable == null) { + throw new IllegalArgumentException("The specified source for the connection does not exist"); + } + + final Connectable destinationConnectable = rootGroup.findConnectable(destinationDto.getId()); + if (destinationConnectable == null) { + throw new IllegalArgumentException("The specified destination for the connection does not exist"); + } } private void verifyList(final FlowFileQueue queue) {