From ae344806c0cdbe81104c339d9e810fb3cff1a3c1 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Tue, 26 Jul 2016 13:59:30 -0400 Subject: [PATCH] NIFI-2224: - Ensuring the template form is reset when the upload template dialog is closed. NIFI-2175: - Not submitting the template form is a template isn't choosen. NIFI-2176: - Ensuring a template is specified during creation. NIFI-2223: - Ensuring templates with the same name cannot be added. NIFI-2296: - Updating the tooltip for the upload template browse button. - Cleaning up un-used parameters to REST endpoints. This closes #725 Signed-off-by: jpercivall --- .../nifi/web/api/dto/ProcessGroupDTO.java | 4 +- .../org/apache/nifi/groups/ProcessGroup.java | 7 ++ .../nifi/groups/StandardProcessGroup.java | 27 ++++- .../service/mock/MockProcessGroup.java | 18 ++-- .../nifi/audit/AccessPolicyAuditor.java | 1 - .../apache/nifi/audit/ProcessorAuditor.java | 1 - .../org/apache/nifi/audit/UserAuditor.java | 1 - .../apache/nifi/audit/UserGroupAuditor.java | 1 - .../apache/nifi/web/NiFiServiceFacade.java | 12 ++- .../nifi/web/StandardNiFiServiceFacade.java | 7 +- .../StandardNiFiWebConfigurationContext.java | 38 +++---- .../org/apache/nifi/web/api/FlowResource.java | 16 +-- .../nifi/web/api/ProcessGroupResource.java | 30 ++---- .../web/api/RemoteProcessGroupResource.java | 15 --- .../org/apache/nifi/web/dao/TemplateDAO.java | 8 ++ .../web/dao/impl/StandardTemplateDAO.java | 16 +++ .../canvas/upload-template-dialog.jsp | 2 +- .../nifi-web-ui/src/main/webapp/css/main.css | 6 ++ .../nf-ng-canvas-operate-controller.js | 18 ++-- .../main/webapp/js/nf/canvas/nf-actions.js | 102 ++++++++++-------- .../src/main/webapp/js/nf/canvas/nf-canvas.js | 3 - .../nf/canvas/nf-connection-configuration.js | 9 -- .../canvas/nf-remote-process-group-ports.js | 3 - .../webapp/js/nf/nf-connection-details.js | 12 --- .../js/nf/templates/nf-templates-table.js | 3 - 25 files changed, 191 insertions(+), 169 deletions(-) diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java index dd18cc48fa..4efb77bdb4 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java @@ -75,10 +75,10 @@ public class ProcessGroupDTO extends ComponentDTO { } /** - * @return contents of this process group. This field will be populated if the request is marked verbose + * @return contents of this process group. */ @ApiModelProperty( - value = "The contents of this process group. This field will be populated if the request is marked verbose." + value = "The contents of this process group." ) public FlowSnippetDTO getContents() { return contents; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java index 455a3c59bd..e989c84086 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java @@ -747,6 +747,13 @@ public interface ProcessGroup extends Authorizable, Positionable { */ void move(final Snippet snippet, final ProcessGroup destination); + /** + * Verifies a template with the specified name can be created. + * + * @param name name of the template + */ + void verifyCanAddTemplate(String name); + void verifyCanDelete(); /** diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java index 8017abdff8..80e898a241 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java @@ -59,6 +59,7 @@ import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.util.ReflectionUtils; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.api.dto.TemplateDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -126,6 +127,14 @@ public final class StandardProcessGroup implements ProcessGroup { return parent.get(); } + private ProcessGroup getRoot() { + ProcessGroup root = this; + while (root.getParent() != null) { + root = root.getParent(); + } + return root; + } + @Override public void setParent(final ProcessGroup newParent) { parent.set(newParent); @@ -1856,7 +1865,6 @@ public final class StandardProcessGroup implements ProcessGroup { } } - @Override public void addTemplate(final Template template) { requireNonNull(template); @@ -2216,6 +2224,23 @@ public final class StandardProcessGroup implements ProcessGroup { } } + @Override + public void verifyCanAddTemplate(final String name) { + // ensure the name is specified + if (StringUtils.isBlank(name)) { + throw new IllegalArgumentException("Template name cannot be blank."); + } + + for (final Template template : getRoot().findAllTemplates()) { + final TemplateDTO existingDto = template.getDetails(); + + // ensure a template with this name doesnt already exist + if (name.equals(existingDto.getName())) { + throw new IllegalStateException(String.format("A template named '%s' already exists.", name)); + } + } + } + @Override public void verifyCanDelete() { verifyCanDelete(false); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java index 2e60c314b4..fddba053a1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java @@ -17,13 +17,6 @@ package org.apache.nifi.controller.service.mock; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.apache.nifi.authorization.Resource; import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.connectable.Connectable; @@ -41,6 +34,13 @@ import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.ProcessGroupCounts; import org.apache.nifi.groups.RemoteProcessGroup; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + public class MockProcessGroup implements ProcessGroup { private final Map serviceMap = new HashMap<>(); private final Map processorMap = new HashMap<>(); @@ -537,6 +537,10 @@ public class MockProcessGroup implements ProcessGroup { } + @Override + public void verifyCanAddTemplate(String name) { + } + @Override public void addTemplate(final Template template) { throw new UnsupportedOperationException(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/AccessPolicyAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/AccessPolicyAuditor.java index 9636e5a610..c84f7fdc99 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/AccessPolicyAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/AccessPolicyAuditor.java @@ -104,7 +104,6 @@ public class AccessPolicyAuditor extends NiFiAuditor { final AccessPolicy updatedAccessPolicy = (AccessPolicy) proceedingJoinPoint.proceed(); // if no exceptions were thrown, add the policy action... - // get the updated verbose state accessPolicy = accessPolicyDAO.getAccessPolicy(updatedAccessPolicy.getIdentifier()); // get the current user diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java index 32aab33c8a..ee093deee2 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java @@ -119,7 +119,6 @@ public class ProcessorAuditor extends NiFiAuditor { final ProcessorNode updatedProcessor = (ProcessorNode) proceedingJoinPoint.proceed(); // if no exceptions were thrown, add the processor action... - // get the updated verbose state processor = processorDAO.getProcessor(updatedProcessor.getIdentifier()); // get the current user diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserAuditor.java index 843184dbc1..8582e19007 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserAuditor.java @@ -98,7 +98,6 @@ public class UserAuditor extends NiFiAuditor { final User updatedUser = (User) proceedingJoinPoint.proceed(); // if no exceptions were thrown, add the user action... - // get the updated verbose state user = userDAO.getUser(updatedUser.getIdentifier()); // get the current user diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserGroupAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserGroupAuditor.java index f039d88f93..2c0bbaba68 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserGroupAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/UserGroupAuditor.java @@ -104,7 +104,6 @@ public class UserGroupAuditor extends NiFiAuditor { final Group updatedUserGroup = (Group) proceedingJoinPoint.proceed(); // if no exceptions were thrown, add the user group action... - // get the updated verbose state user = userGroupDAO.getUserGroup(updatedUserGroup.getIdentifier()); // get the current user diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java index bba2ff2e41..08a56e249e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java @@ -354,6 +354,15 @@ public interface NiFiServiceFacade { // ---------------------------------------- // Template methods // ---------------------------------------- + + /** + * Verifies a template with the specified name can be created. + * + * @param groupId the id of the group for the template + * @param name name of purposed template + */ + void verifyCanAddTemplate(String groupId, String name); + /** * Creates a new Template based off the specified snippet. * @@ -816,10 +825,9 @@ public interface NiFiServiceFacade { * Returns the flow. * * @param groupId group - * @param recurse recurse * @return the flow */ - ProcessGroupFlowEntity getProcessGroupFlow(String groupId, boolean recurse); + ProcessGroupFlowEntity getProcessGroupFlow(String groupId); // ---------------------------------------- // ProcessGroup methods diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index b2b93db677..77696dfef9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -1428,6 +1428,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { return entityFactory.createRemoteProcessGroupEntity(snapshot.getComponent(), dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions, status, bulletins); } + @Override + public void verifyCanAddTemplate(String groupId, String name) { + templateDAO.verifyCanAddTemplate(name, groupId); + } + @Override public TemplateDTO createTemplate(final String name, final String description, final String snippetId, final String groupId, final Optional idGenerationSeed) { // get the specified snippet @@ -2531,7 +2536,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ProcessGroupFlowEntity getProcessGroupFlow(final String groupId, final boolean recurse) { + public ProcessGroupFlowEntity getProcessGroupFlow(final String groupId) { // get all identifiers for every child component final Set identifiers = new HashSet<>(); final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java index fd3c474b6c..20a641be35 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java @@ -16,24 +16,7 @@ */ package org.apache.nifi.web; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.util.Collection; -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.Objects; -import java.util.Set; - -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; - +import com.sun.jersey.core.util.MultivaluedMapImpl; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.action.Action; import org.apache.nifi.action.Component; @@ -76,7 +59,22 @@ import org.apache.nifi.web.util.ClientResponseUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sun.jersey.core.util.MultivaluedMapImpl; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.util.Collection; +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.Objects; +import java.util.Set; /** * Implements the NiFiWebConfigurationContext interface to support a context in both standalone and clustered environments. @@ -84,7 +82,6 @@ import com.sun.jersey.core.util.MultivaluedMapImpl; public class StandardNiFiWebConfigurationContext implements NiFiWebConfigurationContext { private static final Logger logger = LoggerFactory.getLogger(StandardNiFiWebConfigurationContext.class); - public static final String VERBOSE_PARAM = "verbose"; private NiFiProperties properties; private NiFiServiceFacade serviceFacade; @@ -353,7 +350,6 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration // set the request parameters final MultivaluedMap parameters = new MultivaluedMapImpl(); - parameters.add(VERBOSE_PARAM, "true"); // replicate request NodeResponse nodeResponse; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java index 8a17e6505a..f9c67085c3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java @@ -337,8 +337,6 @@ public class FlowResource extends ApplicationResource { /** * Retrieves the contents of the specified group. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. - * @param recursive Optional recursive flag that defaults to false. If set to true, all descendent groups and their content will be included if the verbose flag is also set to true. * @param groupId The id of the process group. * @return A processGroupEntity. * @throws InterruptedException if interrupted @@ -366,21 +364,11 @@ public class FlowResource extends ApplicationResource { } ) public Response getFlow( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = false ) - @PathParam("id") String groupId, - @ApiParam( - value = "Whether the response should contain all encapsulated components or just the immediate children.", - required = false - ) - @QueryParam("recursive") @DefaultValue(RECURSIVE) Boolean recursive) throws InterruptedException { + @PathParam("id") String groupId) throws InterruptedException { authorizeFlow(); @@ -389,7 +377,7 @@ public class FlowResource extends ApplicationResource { } // get this process group flow - final ProcessGroupFlowEntity entity = serviceFacade.getProcessGroupFlow(groupId, recursive); + final ProcessGroupFlowEntity entity = serviceFacade.getProcessGroupFlow(groupId); populateRemainingFlowContent(entity.getProcessGroupFlow()); return clusterContext(generateOkResponse(entity)).build(); } 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 a4933a58fb..549e31208a 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 @@ -1402,7 +1402,6 @@ public class ProcessGroupResource extends ApplicationResource { /** * Retrieves all the of remote process groups in this NiFi. * - * @param verbose Optional verbose flag that defaults to false. If the verbose flag is set to true remote group contents (ports) will be included. * @return A remoteProcessGroupEntity. */ @GET @@ -1429,11 +1428,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getRemoteProcessGroups( - @ApiParam( - value = "Whether to include any encapulated ports or just details about the remote process group.", - required = false - ) - @QueryParam("verbose") @DefaultValue(VERBOSE) final Boolean verbose, @ApiParam( value = "The process group id.", required = true @@ -1454,11 +1448,9 @@ public class ProcessGroupResource extends ApplicationResource { final Set remoteProcessGroups = serviceFacade.getRemoteProcessGroups(groupId); // prune response as necessary - if (!verbose) { - for (RemoteProcessGroupEntity remoteProcessGroupEntity : remoteProcessGroups) { - if (remoteProcessGroupEntity.getComponent() != null) { - remoteProcessGroupEntity.getComponent().setContents(null); - } + for (RemoteProcessGroupEntity remoteProcessGroupEntity : remoteProcessGroups) { + if (remoteProcessGroupEntity.getComponent() != null) { + remoteProcessGroupEntity.getComponent().setContents(null); } } @@ -1893,6 +1885,7 @@ public class ProcessGroupResource extends ApplicationResource { }); } if (validationPhase) { + serviceFacade.verifyCanAddTemplate(groupId, createTemplateRequestEntity.getName()); return generateContinueResponse().build(); } @@ -1913,9 +1906,6 @@ public class ProcessGroupResource extends ApplicationResource { * Imports the specified template. * * @param httpServletRequest request - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param in The template stream * @return A templateEntity or an errorResponse XML snippet. * @throws InterruptedException if interrupted @@ -1932,7 +1922,6 @@ public class ProcessGroupResource extends ApplicationResource { required = true ) @PathParam("id") final String groupId, - @FormDataParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId, @FormDataParam("template") final InputStream in) throws InterruptedException { // unmarshal the template @@ -2009,6 +1998,11 @@ public class ProcessGroupResource extends ApplicationResource { @PathParam("id") final String groupId, final TemplateEntity templateEntity) { + // verify the template was specified + if (templateEntity == null || templateEntity.getTemplate() == null || templateEntity.getTemplate().getSnippet() == null) { + throw new IllegalArgumentException("Template details must be specified."); + } + if (isReplicateRequest()) { return replicate(HttpMethod.POST, templateEntity); } @@ -2023,15 +2017,11 @@ public class ProcessGroupResource extends ApplicationResource { }); } if (validationPhase) { + serviceFacade.verifyCanAddTemplate(groupId, templateEntity.getTemplate().getName()); return generateContinueResponse().build(); } try { - // verify the template was specified - if (templateEntity == null || templateEntity.getTemplate() == null) { - throw new IllegalArgumentException("Template details must be specified."); - } - // import the template final TemplateDTO template = serviceFacade.importTemplate(templateEntity.getTemplate(), groupId, getIdGenerationSeed()); templateResource.populateRemainingTemplateContent(template); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java index 6bb999f8b2..15ae5991ae 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java @@ -64,8 +64,6 @@ import java.util.Set; ) public class RemoteProcessGroupResource extends ApplicationResource { - private static final String VERBOSE_DEFAULT_VALUE = "false"; - private NiFiServiceFacade serviceFacade; private Authorizer authorizer; @@ -96,7 +94,6 @@ public class RemoteProcessGroupResource extends ApplicationResource { /** * Retrieves the specified remote process group. * - * @param verbose Optional verbose flag that defaults to false. If the verbose flag is set to true remote group contents (ports) will be included. * @param id The id of the remote process group to retrieve * @return A remoteProcessGroupEntity. */ @@ -124,11 +121,6 @@ public class RemoteProcessGroupResource extends ApplicationResource { } ) public Response getRemoteProcessGroup( - @ApiParam( - value = "Whether to include any encapulated ports or just details about the remote process group.", - required = false - ) - @QueryParam("verbose") @DefaultValue(VERBOSE_DEFAULT_VALUE) final Boolean verbose, @ApiParam( value = "The remote process group id.", required = true @@ -149,13 +141,6 @@ public class RemoteProcessGroupResource extends ApplicationResource { final RemoteProcessGroupEntity entity = serviceFacade.getRemoteProcessGroup(id); populateRemainingRemoteProcessGroupEntityContent(entity); - // prune the response as necessary - if (!verbose) { - if (entity.getComponent() != null) { - entity.getComponent().setContents(null); - } - } - return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java index 9f44f8a20e..9cebebec28 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java @@ -24,6 +24,14 @@ import java.util.Set; public interface TemplateDAO { + /** + * Verifies a new template can be created with the specifed name in the specified group. + * + * @param name template name + * @param groupId group id + */ + void verifyCanAddTemplate(String name, String groupId); + /** * Creates a template. * 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/StandardTemplateDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardTemplateDAO.java index 55d2ecbb3f..682b93a4cb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardTemplateDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardTemplateDAO.java @@ -55,6 +55,20 @@ public class StandardTemplateDAO extends ComponentDAO implements TemplateDAO { return template; } + @Override + public void verifyCanAddTemplate(String name, String groupId) { + final ProcessGroup processGroup = flowController.getGroup(groupId); + if (processGroup == null) { + throw new ResourceNotFoundException("Could not find Process Group with ID " + groupId); + } + + verifyAdd(name, processGroup); + } + + private void verifyAdd(final String name, final ProcessGroup processGroup) { + processGroup.verifyCanAddTemplate(name); + } + @Override public Template createTemplate(TemplateDTO templateDTO, String groupId) { final ProcessGroup processGroup = flowController.getGroup(groupId); @@ -62,6 +76,8 @@ public class StandardTemplateDAO extends ComponentDAO implements TemplateDAO { throw new ResourceNotFoundException("Could not find Process Group with ID " + groupId); } + verifyAdd(templateDTO.getName(), processGroup); + TemplateUtils.scrubTemplate(templateDTO); final Template template = new Template(templateDTO); processGroup.addTemplate(template); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-dialog.jsp index 0469885a3b..d5c4a79593 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-dialog.jsp +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-dialog.jsp @@ -23,7 +23,7 @@
- +
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css index 3332072181..aa8de53fdc 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css @@ -280,6 +280,12 @@ span.details-title { margin-left: 1px; } +#upload-template-button { + color: #004849; + font-size: 16px; + cursor: pointer; +} + #template-file-upload { position: absolute; top: 0; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js index 9ae29009ea..dd4ae023a5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js @@ -141,7 +141,7 @@ nf.ng.Canvas.OperateCtrl = function () { } }, error: function (xhr, statusText, error) { - $('#upload-template-status').text(error); + $('#upload-template-status').text(xhr.responseText); } }); @@ -157,8 +157,14 @@ nf.ng.Canvas.OperateCtrl = function () { }, handler: { click: function () { - // submit the template - templateForm.submit(); + var selectedTemplate = $('#selected-template-name').text(); + + // submit the template if necessary + if (nf.Common.isBlank(selectedTemplate)) { + $('#upload-template-status').text('No template selected. Please browse to select a template.'); + } else { + templateForm.submit(); + } } } }, { @@ -172,9 +178,6 @@ nf.ng.Canvas.OperateCtrl = function () { click: function () { // hide the dialog $('#upload-template-dialog').modal('hide'); - - // reset the form to ensure that the change fire will fire - templateForm.resetForm(); } } }], @@ -183,6 +186,9 @@ nf.ng.Canvas.OperateCtrl = function () { // set the filename $('#selected-template-name').text(''); $('#upload-template-status').text(''); + + // reset the form to ensure that the change fire will fire + templateForm.resetForm(); } } }); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js index aee9aafbe6..a5b8873319 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js @@ -71,9 +71,6 @@ nf.Actions = (function () { $.ajax({ type: 'GET', url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(response.id), - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { nf.Graph.set(response.processGroupFlow.flow); @@ -1233,58 +1230,73 @@ nf.Actions = (function () { }, handler: { click: function () { + // get the template details + var templateName = $('#new-template-name').val(); + + // ensure the template name is not blank + if (nf.Common.isBlank(templateName)) { + nf.Dialog.showOkDialog({ + headerText: 'Create Template', + dialogContent: "The template name cannot be blank." + }); + return; + } + // hide the dialog $('#new-template-dialog').modal('hide'); - // get the template details - var templateName = $('#new-template-name').val(); + // get the description var templateDescription = $('#new-template-description').val(); - // create a snippet - var snippet = nf.Snippet.marshal(selection); + // create a snippet + var snippet = nf.Snippet.marshal(selection); - // create the snippet - nf.Snippet.create(snippet).done(function (response) { - var createSnippetEntity = { - 'name': templateName, - 'description': templateDescription, - 'snippetId': response.snippet.id - }; + // create the snippet + nf.Snippet.create(snippet).done(function (response) { + var createSnippetEntity = { + 'name': templateName, + 'description': templateDescription, + 'snippetId': response.snippet.id + }; - // create the template - $.ajax({ - type: 'POST', - url: config.urls.api + '/process-groups/' + encodeURIComponent(nf.Canvas.getGroupId()) + '/templates', - data: JSON.stringify(createSnippetEntity), - dataType: 'json', - contentType: 'application/json' - }).done(function () { - // show the confirmation dialog - nf.Dialog.showOkDialog({ - headerText: 'Create Template', - dialogContent: "Template '" + nf.Common.escapeHtml(templateName) + "' was successfully created." - }); - }).always(function () { - // clear the template dialog fields - $('#new-template-name').val(''); - $('#new-template-description').val(''); - }).fail(nf.Common.handleAjaxError); + // create the template + $.ajax({ + type: 'POST', + url: config.urls.api + '/process-groups/' + encodeURIComponent(nf.Canvas.getGroupId()) + '/templates', + data: JSON.stringify(createSnippetEntity), + dataType: 'json', + contentType: 'application/json' + }).done(function () { + // show the confirmation dialog + nf.Dialog.showOkDialog({ + headerText: 'Create Template', + dialogContent: "Template '" + nf.Common.escapeHtml(templateName) + "' was successfully created." + }); + }).always(function () { + // clear the template dialog fields + $('#new-template-name').val(''); + $('#new-template-description').val(''); }).fail(nf.Common.handleAjaxError); - } + }).fail(nf.Common.handleAjaxError); } - }, { - buttonText: 'Cancel', - color: { - base: '#E3E8EB', - hover: '#C7D2D7', - text: '#004849' - }, - handler: { - click: function () { - $('#new-template-dialog').modal('hide'); - } + } + }, { + buttonText: 'Cancel', + color: { + base: '#E3E8EB', + hover: '#C7D2D7', + text: '#004849' + }, + handler: { + click: function () { + // clear the template dialog fields + $('#new-template-name').val(''); + $('#new-template-description').val(''); + + $('#new-template-dialog').modal('hide'); } - }]).modal('show'); + } + }]).modal('show'); // auto focus on the template name $('#new-template-name').focus(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js index 819aac11a2..6f54962c7c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js @@ -621,9 +621,6 @@ nf.Canvas = (function () { return $.ajax({ type: 'GET', url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupId), - data: { - verbose: true - }, dataType: 'json' }).done(function (flowResponse) { // get the controller and its contents diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js index 5f7d308318..b9672a26d9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js @@ -275,9 +275,6 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupData.id), - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var processGroup = response.processGroupFlow; @@ -363,9 +360,6 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', url: remoteProcessGroupData.uri, - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var remoteProcessGroup = response.component; @@ -591,9 +585,6 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', url: remoteProcessGroupData.uri, - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var remoteProcessGroup = response.component; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js index 2c949aaed8..4cad5e925a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js @@ -471,9 +471,6 @@ nf.RemoteProcessGroupPorts = (function () { $.ajax({ type: 'GET', url: selectionData.uri, - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var remoteProcessGroup = response.component; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js index 1821aa7b8e..7c671ab634 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js @@ -108,9 +108,6 @@ nf.ConnectionDetails = (function () { $.ajax({ type: 'GET', url: '../nifi-api/remote-process-groups/' + encodeURIComponent(source.groupId), - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var remoteProcessGroup = response.component; @@ -154,9 +151,6 @@ nf.ConnectionDetails = (function () { $.ajax({ type: 'GET', url: '../nifi-api/process-groups/' + encodeURIComponent(source.groupId), - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var processGroup = response.component; @@ -272,9 +266,6 @@ nf.ConnectionDetails = (function () { $.ajax({ type: 'GET', url: '../nifi-api/remote-process-groups/' + encodeURIComponent(destination.groupId), - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var remoteProcessGroup = response.component; @@ -320,9 +311,6 @@ nf.ConnectionDetails = (function () { $.ajax({ type: 'GET', url: '../nifi-api/process-groups/' + encodeURIComponent(destination.groupId), - data: { - verbose: true - }, dataType: 'json' }).done(function (response) { var processGroup = response.component; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js index e81e332495..272a1fe6c9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js @@ -394,9 +394,6 @@ nf.TemplatesTable = (function () { return $.ajax({ type: 'GET', url: config.urls.templates, - data: { - verbose: false - }, dataType: 'json' }).done(function (response) { // ensure there are groups specified