You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2016/02/06 04:36:00 UTC

[04/50] nifi git commit: NIFI-259: - Initial implementation of viewing and clearing state for a processor.

NIFI-259:
- Initial implementation of viewing and clearing state for a processor.


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

Branch: refs/heads/master
Commit: d05314c54ba0b9cd8b3f19cb3267706ec02f2b4a
Parents: d39067e
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Jan 13 13:35:24 2016 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Wed Jan 13 13:35:24 2016 -0500

----------------------------------------------------------------------
 .../nifi/web/api/dto/ComponentStateDTO.java     |  15 +
 .../nifi/web/api/dto/ControllerServiceDTO.java  |  15 +
 .../apache/nifi/web/api/dto/ProcessorDTO.java   |  15 +
 .../nifi/web/api/dto/ReportingTaskDTO.java      |  15 +
 .../nifi/web/StandardNiFiServiceFacade.java     |  22 +-
 .../org/apache/nifi/web/api/dto/DtoFactory.java |  26 +-
 .../nifi-framework/nifi-web/nifi-web-ui/pom.xml |   1 +
 .../main/resources/filters/canvas.properties    |   1 +
 .../src/main/webapp/WEB-INF/pages/canvas.jsp    |   1 +
 .../partials/canvas/component-state-dialog.jsp  |  45 +++
 .../nifi-web-ui/src/main/webapp/css/canvas.css  |   1 +
 .../src/main/webapp/css/component-state.css     |  88 +++++
 .../src/main/webapp/images/iconViewState.png    | Bin 0 -> 1245 bytes
 .../src/main/webapp/js/nf/canvas/nf-actions.js  |  17 +
 .../src/main/webapp/js/nf/canvas/nf-canvas.js   |   1 +
 .../webapp/js/nf/canvas/nf-component-state.js   | 358 +++++++++++++++++++
 .../main/webapp/js/nf/canvas/nf-context-menu.js |  20 ++
 .../js/nf/canvas/nf-processor-configuration.js  |  21 +-
 18 files changed, 649 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentStateDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentStateDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentStateDTO.java
index d585768..9036d53 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentStateDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentStateDTO.java
@@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlType;
 public class ComponentStateDTO {
 
     private String componentId;
+    private String stateDescription;
     private StateMapDTO clusterState;
     private StateMapDTO localState;
 
@@ -45,6 +46,20 @@ public class ComponentStateDTO {
     }
 
     /**
+     * @return Description of the state this component persists.
+     */
+    @ApiModelProperty(
+        value = "Description of the state this component persists."
+    )
+    public String getStateDescription() {
+        return stateDescription;
+    }
+
+    public void setStateDescription(String stateDescription) {
+        this.stateDescription = stateDescription;
+    }
+
+    /**
      * @return The cluster state for this component, or null if this NiFi is a standalone instance
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
index 659be91..5d51698 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
@@ -33,6 +33,7 @@ public class ControllerServiceDTO extends NiFiComponentDTO {
     private String comments;
     private String availability;
     private String state;
+    private Boolean persistsState;
 
     private Map<String, String> properties;
     private Map<String, PropertyDescriptorDTO> descriptors;
@@ -102,6 +103,20 @@ public class ControllerServiceDTO extends NiFiComponentDTO {
     }
 
     /**
+     * @return whether this controller service persists state
+     */
+    @ApiModelProperty(
+        value = "Whether the controller service persists state."
+    )
+    public Boolean getPersistsState() {
+        return persistsState;
+    }
+
+    public void setPersistsState(Boolean persistsState) {
+        this.persistsState = persistsState;
+    }
+
+    /**
      * @return The state of this controller service. Possible values are ENABLED, ENABLING, DISABLED, DISABLING
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
index 0e4ddde..b0b9daa 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
@@ -37,6 +37,7 @@ public class ProcessorDTO extends NiFiComponentDTO {
     private Boolean supportsParallelProcessing;
     private Boolean supportsEventDriven;
     private Boolean supportsBatching;
+    private Boolean persistsState;
     private String inputRequirement;
 
     private ProcessorConfigDTO config;
@@ -123,6 +124,20 @@ public class ProcessorDTO extends NiFiComponentDTO {
     }
 
     /**
+     * @return whether this processor persists state
+     */
+    @ApiModelProperty(
+        value = "Whether the processor persists state."
+    )
+    public Boolean getPersistsState() {
+        return persistsState;
+    }
+
+    public void setPersistsState(Boolean persistsState) {
+        this.persistsState = persistsState;
+    }
+
+    /**
      * @return the input requirement of this processor
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
index b826829..182535d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
@@ -33,6 +33,7 @@ public class ReportingTaskDTO extends NiFiComponentDTO {
     private String state;
     private String availability;
     private String comments;
+    private Boolean persistsState;
 
     private String schedulingPeriod;
     private String schedulingStrategy;
@@ -106,6 +107,20 @@ public class ReportingTaskDTO extends NiFiComponentDTO {
     }
 
     /**
+     * @return whether this reporting task persists state
+     */
+    @ApiModelProperty(
+        value = "Whether the reporting task persists state."
+    )
+    public Boolean getPersistsState() {
+        return persistsState;
+    }
+
+    public void setPersistsState(Boolean persistsState) {
+        this.persistsState = persistsState;
+    }
+
+    /**
      * @return current scheduling state of the reporting task
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
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 41318a1..4f6f58a 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
@@ -18,6 +18,7 @@ package org.apache.nifi.web;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.lf5.util.Resource;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
@@ -2168,23 +2169,32 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
 
     @Override
     public ComponentStateDTO getProcessorState(String groupId, String processorId) {
-        final StateMap clusterState = processorDAO.getState(groupId, processorId, Scope.CLUSTER);
+        final StateMap clusterState = isClustered() ? processorDAO.getState(groupId, processorId, Scope.CLUSTER) : null;
         final StateMap localState = processorDAO.getState(groupId, processorId, Scope.LOCAL);
-        return dtoFactory.createComponentStateDTO(processorId, localState, clusterState);
+
+        // processor will be non null as it was already found when getting the state
+        final ProcessorNode processor = processorDAO.getProcessor(groupId, processorId);
+        return dtoFactory.createComponentStateDTO(processorId, processor.getProcessor().getClass(), localState, clusterState);
     }
 
     @Override
     public ComponentStateDTO getControllerServiceState(String controllerServiceId) {
-        final StateMap clusterState = controllerServiceDAO.getState(controllerServiceId, Scope.CLUSTER);
+        final StateMap clusterState = isClustered() ? controllerServiceDAO.getState(controllerServiceId, Scope.CLUSTER) : null;
         final StateMap localState = controllerServiceDAO.getState(controllerServiceId, Scope.LOCAL);
-        return dtoFactory.createComponentStateDTO(controllerServiceId, localState, clusterState);
+
+        // controller service will be non null as it was already found when getting the state
+        final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(controllerServiceId);
+        return dtoFactory.createComponentStateDTO(controllerServiceId, controllerService.getControllerServiceImplementation().getClass(), localState, clusterState);
     }
 
     @Override
     public ComponentStateDTO getReportingTaskState(String reportingTaskId) {
-        final StateMap clusterState = reportingTaskDAO.getState(reportingTaskId, Scope.CLUSTER);
+        final StateMap clusterState = isClustered() ? reportingTaskDAO.getState(reportingTaskId, Scope.CLUSTER) : null;
         final StateMap localState = reportingTaskDAO.getState(reportingTaskId, Scope.LOCAL);
-        return dtoFactory.createComponentStateDTO(reportingTaskId, localState, clusterState);
+
+        // reporting task will be non null as it was already found when getting the state
+        final ReportingTaskNode reportingTask = reportingTaskDAO.getReportingTask(reportingTaskId);
+        return dtoFactory.createComponentStateDTO(reportingTaskId, reportingTask.getReportingTask().getClass(), localState, clusterState);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index e2be595..6ed39a2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -32,6 +32,7 @@ import org.apache.nifi.action.details.FlowChangeMoveDetails;
 import org.apache.nifi.action.details.FlowChangePurgeDetails;
 import org.apache.nifi.action.details.MoveDetails;
 import org.apache.nifi.action.details.PurgeDetails;
+import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
 import org.apache.nifi.authorization.Authority;
@@ -279,15 +280,31 @@ public final class DtoFactory {
      * @param clusterState cluster state
      * @return dto
      */
-    public ComponentStateDTO createComponentStateDTO(final String componentId, final StateMap localState, final StateMap clusterState) {
+    public ComponentStateDTO createComponentStateDTO(final String componentId, final Class<?> componentClass, final StateMap localState, final StateMap clusterState) {
         final ComponentStateDTO dto = new ComponentStateDTO();
         dto.setComponentId(componentId);
+        dto.setStateDescription(getStateDescription(componentClass));
         dto.setLocalState(createStateMapDTO(Scope.LOCAL, localState));
         dto.setClusterState(createStateMapDTO(Scope.CLUSTER, clusterState));
         return dto;
     }
 
     /**
+     * Gets the description of the state this component persists.
+     *
+     * @param componentClass the component class
+     * @return state description
+     */
+    private String getStateDescription(final Class<?> componentClass) {
+        final Stateful capabilityDesc = componentClass.getAnnotation(Stateful.class);
+        if (capabilityDesc != null) {
+            return capabilityDesc.description();
+        } else {
+            return null;
+        }
+    }
+
+    /**
      * Creates a StateMapDTO for the given scope and state map.
      *
      * @param scope the scope
@@ -295,6 +312,10 @@ public final class DtoFactory {
      * @return dto
      */
     public StateMapDTO createStateMapDTO(final Scope scope, final StateMap stateMap) {
+        if (stateMap == null) {
+            return null;
+        }
+
         final StateMapDTO dto = new StateMapDTO();
         dto.setScope(scope.toString());
 
@@ -1066,6 +1087,7 @@ public final class DtoFactory {
         dto.setActiveThreadCount(reportingTaskNode.getActiveThreadCount());
         dto.setAnnotationData(reportingTaskNode.getAnnotationData());
         dto.setComments(reportingTaskNode.getComments());
+        dto.setPersistsState(reportingTaskNode.getReportingTask().getClass().isAnnotationPresent(Stateful.class));
 
         final Map<String, String> defaultSchedulingPeriod = new HashMap<>();
         defaultSchedulingPeriod.put(SchedulingStrategy.TIMER_DRIVEN.name(), SchedulingStrategy.TIMER_DRIVEN.getDefaultSchedulingPeriod());
@@ -1133,6 +1155,7 @@ public final class DtoFactory {
         dto.setState(controllerServiceNode.getState().name());
         dto.setAnnotationData(controllerServiceNode.getAnnotationData());
         dto.setComments(controllerServiceNode.getComments());
+        dto.setPersistsState(controllerServiceNode.getControllerServiceImplementation().getClass().isAnnotationPresent(Stateful.class));
 
         // sort a copy of the properties
         final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
@@ -1610,6 +1633,7 @@ public final class DtoFactory {
         dto.setStyle(node.getStyle());
         dto.setParentGroupId(node.getProcessGroup().getIdentifier());
         dto.setInputRequirement(node.getInputRequirement().name());
+        dto.setPersistsState(node.getProcessor().getClass().isAnnotationPresent(Stateful.class));
 
         dto.setType(node.getProcessor().getClass().getCanonicalName());
         dto.setName(node.getName());

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
index 8e87131..2a8d7ea 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
@@ -281,6 +281,7 @@
                                                 <include>${staging.dir}/js/nf/canvas/nf-canvas-toolbox.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-custom-ui.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-queue-listing.js</include>
+                                                <include>${staging.dir}/js/nf/canvas/nf-component-state.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-controller-service.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-reporting-task.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-processor-configuration.js</include>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
index 43e60f4..b239dd2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
@@ -22,6 +22,7 @@ nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-snippet.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-queue-listing.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/canvas/nf-component-state.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-canvas-toolbox.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-custom-ui.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-controller-service.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index 5a9eab7..287a58c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -122,6 +122,7 @@
         <jsp:include page="/WEB-INF/partials/canvas/flowfile-details-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/listing-request-status-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/queue-listing.jsp"/>
+        <jsp:include page="/WEB-INF/partials/canvas/component-state-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/connection-details.jsp"/>
         <div id="faded-background"></div>
         <div id="glass-pane"></div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/component-state-dialog.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/component-state-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/component-state-dialog.jsp
new file mode 100644
index 0000000..725234f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/component-state-dialog.jsp
@@ -0,0 +1,45 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="component-state-dialog">
+    <div class="dialog-content">
+        <div class="setting">
+            <div class="setting-name">Name</div>
+            <div class="setting-field">
+                <span id="component-state-name"></span>
+            </div>
+        </div>
+        <div class="setting">
+            <div class="setting-name">Description</div>
+            <div class="setting-field">
+                <span id="component-state-description"></span>
+            </div>
+        </div>
+        <div id="component-state-filter-controls">
+            <div id="component-state-filter-container">
+                <input type="text" id="component-state-filter"/>
+            </div>
+            <div id="component-state-filter-status">
+                Displaying&nbsp;<span id="displayed-component-state-entries"></span>&nbsp;of&nbsp;<span id="total-component-state-entries"></span>
+            </div>
+        </div>
+        <div id="component-state-table"></div>
+        <div id="clear-link-container">
+            <span id="clear-link" class="link">Clear state</span>
+        </div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
index 2df31d6..1a4eb66 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
@@ -22,6 +22,7 @@
 @import url(queue-listing.css);
 @import url(remote-process-group-configuration.css);
 @import url(controller-service.css);
+@import url(component-state.css);
 @import url(reporting-task.css);
 @import url(port-configuration.css);
 @import url(port-details.css);

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/component-state.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/component-state.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/component-state.css
new file mode 100644
index 0000000..35efca3
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/component-state.css
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/*
+    Component state
+*/
+
+#component-state-dialog {
+    position: absolute;
+    overflow: hidden;
+    width: 600px;
+    height: 500px;
+    font-size: 10px;
+    z-index: 1301;
+    display: none;
+}
+
+#component-state-description {
+    height: 50px;
+}
+
+/*
+    Component state filter
+*/
+
+#component-state-filter-controls {
+    float: right;
+    margin-top: 10px;
+    margin-right: 2px;
+    margin-bottom: 7px;
+}
+
+#component-state-filter-status {
+    font-size: 9px;
+    font-weight: bold;
+    color: #9f6000;
+    clear: left;
+    line-height: normal;
+    margin-left: 5px;
+}
+
+#component-state-filter {
+    padding: 3px 0px 1px 3px;
+    font-size: 12px;
+    height: 18px;
+    line-height: 20px;
+    width: 173px;
+    border: 1px solid #ccc;
+    float: left;
+}
+
+/*
+    Component state table
+*/
+
+#component-state-table {
+    width: 578px;
+    height: 235px;
+    border: 1px solid #666;
+}
+
+/*
+    Clear
+*/
+
+#clear-link-container {
+    margin-top: 16px;
+}
+
+#clear-link.disabled {
+    color: #bbb;
+    font-style: italic;
+    text-decoration: none !important;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconViewState.png
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconViewState.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconViewState.png
new file mode 100644
index 0000000..c9ffb38
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconViewState.png differ

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
----------------------------------------------------------------------
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 2f1bbd3..d003fa7 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
@@ -1064,6 +1064,23 @@ nf.Actions = (function () {
         },
 
         /**
+         * Views the state for the specified processor.
+         *
+         * @param {selection} selection
+         */
+        viewState: function (selection) {
+            if (selection.size() !== 1 || !nf.CanvasUtils.isProcessor(selection)) {
+                return;
+            }
+
+            // get the processor data
+            var processor = selection.datum();
+
+            // view the state for the selected processor
+            nf.ComponentState.showState(processor.component, nf.CanvasUtils.supportsModification(selection));
+        },
+
+        /**
          * Opens the fill color dialog for the component in the specified selection.
          * 
          * @param {type} selection      The selection

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
----------------------------------------------------------------------
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 005f7e3..fb002be 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
@@ -1151,6 +1151,7 @@ nf.Canvas = (function () {
                             nf.Settings.init();
                             nf.Actions.init();
                             nf.QueueListing.init();
+                            nf.ComponentState.init();
 
                             // initialize the component behaviors
                             nf.Draggable.init();

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js
new file mode 100644
index 0000000..d4fb63c
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js
@@ -0,0 +1,358 @@
+/*
+ * 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.
+ */
+
+/* global nf */
+
+/**
+ * Views state for a given component.
+ */
+nf.ComponentState = (function () {
+
+    var config = {
+        filterText: 'Filter',
+        styles: {
+            filterList: 'filter-list'
+        }
+    };
+
+    /**
+     * Filters the component state table.
+     */
+    var applyFilter = function () {
+        // get the dataview
+        var componentStateTable = $('#component-state-table').data('gridInstance');
+
+        // ensure the grid has been initialized
+        if (nf.Common.isDefinedAndNotNull(componentStateTable)) {
+            var componentStateData = componentStateTable.getData();
+
+            // update the search criteria
+            componentStateData.setFilterArgs({
+                searchString: getFilterText()
+            });
+            componentStateData.refresh();
+        }
+    };
+
+    /**
+     * Determines if the item matches the filter.
+     *
+     * @param {object} item     The item to filter
+     * @param {object} args     The filter criteria
+     * @returns {boolean}       Whether the item matches the filter
+     */
+    var filter = function (item, args) {
+        if (args.searchString === '') {
+            return true;
+        }
+
+        try {
+            // perform the row filtering
+            var filterExp = new RegExp(args.searchString, 'i');
+        } catch (e) {
+            // invalid regex
+            return false;
+        }
+
+        // determine if the item matches the filter
+        var matchesKey = item['key'].search(filterExp) >= 0;
+        var matchesValue = item['value'].search(filterExp) >= 0;
+
+        // conditionally consider the scope
+        var matchesScope = false;
+        if (nf.Common.isDefinedAndNotNull(item['scope'])) {
+            matchesScope = item['scope'].search(filterExp) >= 0;
+        }
+
+        return matchesKey || matchesValue || matchesScope;
+    };
+
+    /**
+     * Sorts the specified data using the specified sort details.
+     *
+     * @param {object} sortDetails
+     * @param {object} data
+     */
+    var sort = function (sortDetails, data) {
+        // defines a function for sorting
+        var comparer = function (a, b) {
+            var aString = nf.Common.isDefinedAndNotNull(a[sortDetails.columnId]) ? a[sortDetails.columnId] : '';
+            var bString = nf.Common.isDefinedAndNotNull(b[sortDetails.columnId]) ? b[sortDetails.columnId] : '';
+            return aString === bString ? 0 : aString > bString ? 1 : -1;
+        };
+
+        // perform the sort
+        data.sort(comparer, sortDetails.sortAsc);
+    };
+
+    /**
+     * Get the text out of the filter field. If the filter field doesn't
+     * have any text it will contain the text 'filter list' so this method
+     * accounts for that.
+     */
+    var getFilterText = function () {
+        var filterText = '';
+        var filterField = $('#component-state-filter');
+        if (!filterField.hasClass(config.styles.filterList)) {
+            filterText = filterField.val();
+        }
+        return filterText;
+    };
+
+    /**
+     * Clears the component state table.
+     */
+    var clearTable = function () {
+        var componentStateGrid = $('#component-state-table').data('gridInstance');
+        var componentStateData = componentStateGrid.getData();
+        componentStateData.setItems([]);
+    };
+
+    /**
+     * Loads the table with the component state.
+     *
+     * @param {object} componentState
+     */
+    var loadComponentState = function (localState, clusterState) {
+        var count = 0;
+
+        var componentStateGrid = $('#component-state-table').data('gridInstance');
+        var componentStateData = componentStateGrid.getData();
+
+        // begin the update
+        componentStateData.beginUpdate();
+
+        // local state
+        if (nf.Common.isDefinedAndNotNull(localState)) {
+            $.each(localState.state, function (i, stateEntry) {
+                componentStateData.addItem($.extend({
+                    id: count++,
+                    scope: stateEntry.nodeAddress
+                }, stateEntry));
+            });
+        }
+
+        if (nf.Common.isDefinedAndNotNull(clusterState)) {
+            $.each(clusterState.state, function (i, stateEntry) {
+                componentStateData.addItem($.extend({
+                    id: count++,
+                    scope: 'Cluster'
+                }, stateEntry));
+            });
+        }
+
+        // complete the update
+        componentStateData.endUpdate();
+
+        // update the total number of state entries
+        $('#total-component-state-entries').text(count);
+    };
+
+    /**
+     * Reset the dialog.
+     */
+    var resetDialog = function () {
+        // clear the fields
+        $('#component-state-name').text('');
+        $('#component-state-description').text('');
+        $('#total-component-state-entries').text('');
+
+        // clear any filter strings
+        $('#component-state-filter').addClass(config.styles.filterList).val(config.filterText);
+
+        // reset clear link
+        $('#clear-link').removeClass('disabled').attr('title', '');
+
+        // clear the table
+        clearTable();
+
+        // clear the component
+        $('#component-state-table').removeData('component');
+    };
+
+    return {
+        init: function () {
+            // intialize the component state filter
+            $('#component-state-filter').on('focus', function () {
+                if ($(this).hasClass(config.styles.filterList)) {
+                    $(this).removeClass(config.styles.filterList).val('');
+                }
+            }).on('blur', function () {
+                if ($(this).val() === '') {
+                    $(this).addClass(config.styles.filterList).val(config.filterText);
+                }
+            }).on('keyup', function () {
+                applyFilter();
+            }).addClass(config.styles.filterList).val(config.filterText);
+
+            // initialize the processor configuration dialog
+            $('#component-state-dialog').modal({
+                headerText: 'Component State',
+                overlayBackground: true,
+                buttons: [{
+                    buttonText: 'Ok',
+                    handler: {
+                        click: function () {
+                            $(this).modal('hide');
+                        }
+                    }
+                }],
+                handler: {
+                    close: function () {
+                        resetDialog();
+                    }
+                }
+            }).draggable({
+                containment: 'parent',
+                handle: '.dialog-header'
+            });
+
+            // clear state link
+            $('#clear-link').on('click', function () {
+                if ($(this).hasClass('disabled') === false) {
+                    // clear the table
+                    clearTable();
+
+                    // clear the state
+                    var revision = nf.Client.getRevision();
+                    var component = $('#component-state-table').data('component');
+                    $.ajax({
+                        type: 'POST',
+                        url: component.uri + '/state/clear-requests',
+                        data: {
+                            version: revision.version,
+                            clientId: revision.clientId
+                        },
+                        dataType: 'json'
+                    }).done(function (response) {
+                        // update the revision
+                        nf.Client.setRevision(response.revision);
+
+                        // reload the table with no state
+                        loadComponentState()
+                    }).fail(nf.Common.handleAjaxError);
+                }
+            });
+
+            // initialize the queue listing table
+            var componentStateColumns = [
+                {id: 'key', field: 'key', name: 'Key', sortable: true, resizable: true},
+                {id: 'value', field: 'value', name: 'Value', sortable: true, resizable: true}
+            ];
+
+            // conditionally show the cluster node identifier
+            if (nf.Canvas.isClustered()) {
+                componentStateColumns.push({id: 'scope', field: 'scope', name: 'Scope', sortable: true, resizable: true, formatter: scopeFormatter});
+            }
+
+            var componentStateOptions = {
+                forceFitColumns: true,
+                enableTextSelectionOnCells: true,
+                enableCellNavigation: false,
+                enableColumnReorder: false,
+                autoEdit: false
+            };
+
+            // initialize the dataview
+            var componentStateData = new Slick.Data.DataView({
+                inlineFilters: false
+            });
+            componentStateData.setItems([]);
+            componentStateData.setFilterArgs({
+                searchString: '',
+                property: 'key'
+            });
+            componentStateData.setFilter(filter);
+
+            // initialize the sort
+            sort({
+                columnId: 'key',
+                sortAsc: true
+            }, componentStateData);
+
+            // initialize the grid
+            var componentStateGrid = new Slick.Grid('#component-state-table', componentStateData, componentStateColumns, componentStateOptions);
+            componentStateGrid.setSelectionModel(new Slick.RowSelectionModel());
+            componentStateGrid.registerPlugin(new Slick.AutoTooltips());
+            componentStateGrid.setSortColumn('key', true);
+            componentStateGrid.onSort.subscribe(function (e, args) {
+                sort({
+                    columnId: args.sortCol.field,
+                    sortAsc: args.sortAsc
+                }, componentStateData);
+            });
+
+            // wire up the dataview to the grid
+            componentStateData.onRowCountChanged.subscribe(function (e, args) {
+                componentStateGrid.updateRowCount();
+                componentStateGrid.render();
+
+                // update the total number of displayed items
+                $('#displayed-component-state-entries').text(args.current);
+            });
+            componentStateData.onRowsChanged.subscribe(function (e, args) {
+                componentStateGrid.invalidateRows(args.rows);
+                componentStateGrid.render();
+            });
+
+            // hold onto an instance of the grid
+            $('#component-state-table').data('gridInstance', componentStateGrid);
+
+            // initialize the number of display items
+            $('#displayed-component-state-entries').text('0');
+        },
+
+        /**
+         * Shows the state for a given component.
+         *
+         * @param {object} component
+         * @param {boolean} canClear
+         */
+        showState: function (component, canClear) {
+            return $.ajax({
+                type: 'GET',
+                url: component.uri + '/state',
+                dataType: 'json'
+            }).done(function (response) {
+                var componentState = response.componentState;
+                var componentStateTable = $('#component-state-table');
+
+                // load the table
+                loadComponentState(componentState.localState, componentState.clusterState);
+
+                // populate the name/description
+                $('#component-state-name').text(component.name);
+                $('#component-state-description').text(componentState.stateDescription);
+
+                // store the component
+                componentStateTable.data('component', component);
+
+                // show the dialog
+                $('#component-state-dialog').modal('show');
+
+                // only activate the link when appropriate
+                if (canClear === false) {
+                    $('#clear-link').addClass('disabled').attr('title', 'Component state can only be cleared when the component is not actively running');
+                }
+
+                // reset the grid size
+                var componentStateGrid = componentStateTable.data('gridInstance');
+                componentStateGrid.resizeCanvas();
+            }).fail(nf.Common.handleAjaxError);
+        }
+    };
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
index 55df1e9..990ca07 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
@@ -232,6 +232,25 @@ nf.ContextMenu = (function () {
     };
 
     /**
+     * Determines whether the current selection is a processor.
+     *
+     * @param {selection} selection
+     */
+    var isStatefulProcessor = function (selection) {
+        // ensure the correct number of components are selected
+        if (selection.size() !== 1) {
+            return false;
+        }
+
+        if (nf.CanvasUtils.isProcessor(selection)) {
+            var processorData = selection.datum();
+            return processorData.component.persistsState === true;
+        } else {
+            return false;
+        }
+    };
+
+    /**
      * Determines whether the current selection is a process group.
      * 
      * @param {selection} selection
@@ -399,6 +418,7 @@ nf.ContextMenu = (function () {
         {condition: canStopTransmission, menuItem: {img: 'images/iconTransmissionInactive.png', text: 'Disable transmission', action: 'disableTransmission'}},
         {condition: supportsStats, menuItem: {img: 'images/iconChart.png', text: 'Stats', action: 'showStats'}},
         {condition: canAccessProvenance, menuItem: {img: 'images/iconProvenance.png', imgStyle: 'context-menu-provenance', text: 'Data provenance', action: 'openProvenance'}},
+        {condition: isStatefulProcessor, menuItem: {img: 'images/iconViewState.png', text: 'View state', action: 'viewState'}},
         {condition: canMoveToFront, menuItem: {img: 'images/iconToFront.png', text: 'Bring to front', action: 'toFront'}},
         {condition: isConnection, menuItem: {img: 'images/iconGoTo.png', text: 'Go to source', action: 'showSource'}},
         {condition: isConnection, menuItem: {img: 'images/iconGoTo.png', text: 'Go to destination', action: 'showDestination'}},

http://git-wip-us.apache.org/repos/asf/nifi/blob/d05314c5/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
index 6d04a00..2318720 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
@@ -572,24 +572,33 @@ nf.ProcessorConfiguration = (function () {
                 // get the processor details
                 var processor = selectionData.component;
 
+                var requests = [];
+
                 // reload the processor in case an property descriptors have updated
-                var reloadProcessor = nf.Processor.reload(processor);
-                
+                requests.push(nf.Processor.reload(processor));
+
                 // get the processor history
-                var loadHistory = $.ajax({
+                requests.push($.ajax({
                     type: 'GET',
                     url: '../nifi-api/controller/history/processors/' + encodeURIComponent(processor.id),
                     dataType: 'json'
-                });
+                }));
+
+                // get the processor state if we're a DFM
+                if (nf.Common.isDFM()) {
+                    requests.push();
+                }
                 
                 // once everything is loaded, show the dialog
-                $.when(reloadProcessor, loadHistory).done(function (processorResponse, historyResponse) {
+                $.when.apply(window, requests).done(function (processorResponse, historyResponse, stateResponse) {
                     // get the updated processor
                     processor = processorResponse[0].processor;
                     
                     // get the processor history
                     var processorHistory = historyResponse[0].componentHistory;
-                    
+
+                    console.log(stateResponse);
+
                     // record the processor details
                     $('#processor-configuration').data('processorDetails', processor);