NIFI-250: Serialize and deserialize controller services and reporting tasks in 
the flow.xml


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

Branch: refs/heads/NIFI-250
Commit: 86d15f9e1c3b28a9ae587a1cb0c73cd2b6e8b51c
Parents: ff43b03
Author: Mark Payne <[email protected]>
Authored: Mon Jan 26 13:55:55 2015 -0500
Committer: Mark Payne <[email protected]>
Committed: Mon Jan 26 13:55:55 2015 -0500

----------------------------------------------------------------------
 .../nifi/web/api/dto/ControllerServiceDTO.java  |  16 +-
 .../nifi/web/api/dto/ProcessorConfigDTO.java    |   6 +-
 .../nifi/web/api/dto/ReportingTaskDTO.java      | 166 +++++++++++++++++++
 .../cluster/manager/impl/WebClusterManager.java |   4 +
 .../nifi/controller/ReportingTaskNode.java      |   4 +
 .../service/ControllerServiceNode.java          |   3 +
 .../service/ControllerServiceProvider.java      |   8 +
 .../apache/nifi/controller/FlowController.java  |  31 +++-
 .../nifi/controller/FlowFromDOMFactory.java     |  59 +++++--
 .../nifi/controller/StandardFlowSerializer.java |  62 ++++++-
 .../controller/StandardFlowSynchronizer.java    |  61 ++++++-
 .../reporting/AbstractReportingTaskNode.java    |  16 +-
 .../service/ControllerServiceLoader.java        |   3 +-
 .../service/StandardControllerServiceNode.java  |  21 +++
 .../StandardControllerServiceProvider.java      |  10 +-
 .../StandardXMLFlowConfigurationDAO.java        |  10 +-
 .../nifi/web/controller/ControllerFacade.java   |   4 +
 17 files changed, 439 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/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/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
index 7662594..94ac55a 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
@@ -20,13 +20,14 @@ import java.util.Map;
 import javax.xml.bind.annotation.XmlType;
 
 /**
- * A connection between two connectable components.
+ * A Controller Service that can be shared by other components
  */
 @XmlType(name = "controllerService")
 public class ControllerServiceDTO extends NiFiComponentDTO {
 
     private String name;
     private String type;
+    private String comment;
     private String availability;
     private Boolean enabled;
     
@@ -60,8 +61,21 @@ public class ControllerServiceDTO extends NiFiComponentDTO {
     public void setType(String type) {
         this.type = type;
     }
+    
 
     /**
+     * The comment for the Controller Service
+     * @return
+     */
+    public String getComment() {
+               return comment;
+       }
+
+       public void setComment(String comment) {
+               this.comment = comment;
+       }
+
+       /**
      * Where this service is available. Possible values are 
CLUSTER_MANAGER_ONLY, NODE_ONLY, BOTH.
      * 
      * @return 

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorConfigDTO.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorConfigDTO.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorConfigDTO.java
index 5978041..d1a44b8 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorConfigDTO.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorConfigDTO.java
@@ -54,10 +54,10 @@ public class ProcessorConfigDTO {
     }
 
     /**
-     * The amount of time that should elapse between task executions. This will
-     * not affect currently scheduled tasks.
+     * The frequency with which to schedule the processor. The format of the 
value will
+     * depend on the value of {@link #getSchedulingStrategy()}.
      *
-     * @return The scheduling period in seconds
+     * @return The scheduling period
      */
     public String getSchedulingPeriod() {
         return schedulingPeriod;

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/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/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
new file mode 100644
index 0000000..a04e9bb
--- /dev/null
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.web.api.dto;
+
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Component that is capable of reporting internal NiFi state to an external 
service
+ */
+@XmlType(name = "reportingTask")
+public class ReportingTaskDTO extends NiFiComponentDTO {
+       private String name;
+       private String comment;
+       private String type;
+       private String schedulingPeriod;
+       private String scheduledState;
+       private String schedulingStrategy;
+       private String availability;
+       
+       private Map<String, String> properties;
+    private Map<String, PropertyDescriptorDTO> descriptors;
+ 
+    private String annotationData;
+
+    /**
+     * The user-defined name of the reporting task
+     * @return
+     */
+       public String getName() {
+               return name;
+       }
+
+       public void setName(String name) {
+               this.name = name;
+       }
+
+       /**
+        * The user-defined comment for the reporting task
+        * @return
+        */
+       public String getComment() {
+               return comment;
+       }
+
+       public void setComment(String comment) {
+               this.comment = comment;
+       }
+
+       /**
+        * The type of reporting task
+        * @return
+        */
+       public String getType() {
+               return type;
+       }
+
+       public void setType(String type) {
+               this.type = type;
+       }
+
+       /**
+     * The frequency with which to schedule the reporting task. The format of 
the value will
+     * depend on the value of {@link #getSchedulingStrategy()}.
+     *
+     * @return The scheduling period
+     */
+       public String getSchedulingPeriod() {
+               return schedulingPeriod;
+       }
+
+       public void setSchedulingPeriod(String schedulingPeriod) {
+               this.schedulingPeriod = schedulingPeriod;
+       }
+
+       /**
+        * The current scheduling state of the reporting task
+        * @return
+        */
+       public String getScheduledState() {
+               return scheduledState;
+       }
+
+       public void setScheduledState(String scheduledState) {
+               this.scheduledState = scheduledState;
+       }
+
+       /**
+        * The scheduling strategy that determines how the {@link 
#getSchedulingPeriod()} value should
+        * be interpreted
+        * 
+        * @return
+        */
+       public String getSchedulingStrategy() {
+               return schedulingStrategy;
+       }
+
+       public void setSchedulingStrategy(String schedulingStrategy) {
+               this.schedulingStrategy = schedulingStrategy;
+       }
+
+       /**
+     * Where this service is available. Possible values are 
CLUSTER_MANAGER_ONLY, NODE_ONLY, BOTH.
+     * 
+     * @return 
+     */
+       public String getAvailability() {
+               return availability;
+       }
+
+       public void setAvailability(String availability) {
+               this.availability = availability;
+       }
+
+       /**
+        * The reporting task's properties
+        * @return
+        */
+       public Map<String, String> getProperties() {
+               return properties;
+       }
+
+       public void setProperties(Map<String, String> properties) {
+               this.properties = properties;
+       }
+
+       /**
+        * Map of property name to descriptor
+        * @return
+        */
+       public Map<String, PropertyDescriptorDTO> getDescriptors() {
+               return descriptors;
+       }
+
+       public void setDescriptors(Map<String, PropertyDescriptorDTO> 
descriptors) {
+               this.descriptors = descriptors;
+       }
+
+       /**
+        * The currently configured annotation data for the reporting task
+        * @return
+        */
+       public String getAnnotationData() {
+               return annotationData;
+       }
+
+       public void setAnnotationData(String annotationData) {
+               this.annotationData = annotationData;
+       }
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java
index 5f1c460..54c2b55 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java
@@ -1342,6 +1342,10 @@ public class WebClusterManager implements 
HttpClusterManager, ProtocolHandler, C
         controllerServiceProvider.disableControllerService(serviceNode);
     }
     
+    @Override
+    public Set<ControllerServiceNode> getAllControllerServices() {
+       return controllerServiceProvider.getAllControllerServices();
+    }
     
     /**
      * Handle a bulletins message.

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ReportingTaskNode.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ReportingTaskNode.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ReportingTaskNode.java
index fa48cb3..cf81352 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ReportingTaskNode.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ReportingTaskNode.java
@@ -68,6 +68,10 @@ public interface ReportingTaskNode extends 
ConfiguredComponent {
     
     void setScheduledState(ScheduledState state);
     
+    String getComment();
+    
+    void setComment(String comment);
+    
     void verifyCanStart();
     void verifyCanStop();
     void verifyCanDisable();

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java
index 66bad39..32b9d9e 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java
@@ -40,6 +40,9 @@ public interface ControllerServiceNode extends 
ConfiguredComponent {
 
     void removeReference(ConfiguredComponent referringComponent);
     
+    void setComment(String comment);
+    String getComment();
+    
     void verifyCanEnable();
     void verifyCanDisable();
     void verifyCanDelete();

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceProvider.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceProvider.java
index 54a506e..60ff6c9 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceProvider.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceProvider.java
@@ -16,6 +16,8 @@
  */
 package org.apache.nifi.controller.service;
 
+import java.util.Set;
+
 import org.apache.nifi.annotation.lifecycle.OnAdded;
 import org.apache.nifi.controller.ControllerServiceLookup;
 
@@ -65,4 +67,10 @@ public interface ControllerServiceProvider extends 
ControllerServiceLookup {
      * @param serviceNode
      */
     void disableControllerService(ControllerServiceNode serviceNode);
+    
+    /**
+     * Returns a Set of all Controller Services that exist for this service 
provider.
+     * @return
+     */
+    Set<ControllerServiceNode> getAllControllerServices();
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
index 38c8d42..92975ad 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
@@ -2464,16 +2464,16 @@ public class FlowController implements EventAccess, 
ControllerServiceProvider, H
         lookupGroup(groupId).stopProcessing();
     }
 
-    public ReportingTaskNode createReportingTask(final String type, String id) 
throws ReportingTaskInstantiationException {
-        return createReportingTask(type, id, true);
+    public ReportingTaskNode createReportingTask(final String type) throws 
ReportingTaskInstantiationException {
+        return createReportingTask(type, true);
     }
     
-    public ReportingTaskNode createReportingTask(final String type, String id, 
final boolean firstTimeAdded) throws ReportingTaskInstantiationException {
+    public ReportingTaskNode createReportingTask(final String type, final 
boolean firstTimeAdded) throws ReportingTaskInstantiationException {
         if (type == null) {
             throw new NullPointerException();
         }
-
-        id = requireNonNull(id).intern();
+        
+        final String id = UUID.randomUUID().toString();
 
         ReportingTask task = null;
         final ClassLoader ctxClassLoader = 
Thread.currentThread().getContextClassLoader();
@@ -2563,18 +2563,28 @@ public class FlowController implements EventAccess, 
ControllerServiceProvider, H
      * @param serviceNode
      */
     public void deactiveReferencingComponents(final ControllerServiceNode 
serviceNode) {
+       // TODO: Should stop all Processors and Reporting Tasks, and then wait 
for them to
+       // finish, rather than stopping & waiting serially.
        final ControllerServiceReference reference = 
serviceNode.getReferences();
        
        final Set<ConfiguredComponent> components = 
reference.getActiveReferences();
        for (final ConfiguredComponent component : components) {
                if ( component instanceof ControllerServiceNode ) {
                        deactiveReferencingComponents((ControllerServiceNode) 
component);
-                       // TODO: DISABLE CONTROLLER SERVICE!
+                       
+                       if 
(isControllerServiceEnabled(serviceNode.getIdentifier())) {
+                               disableControllerService(serviceNode);
+                       }
                } else if ( component instanceof ReportingTaskNode ) {
-                       stopReportingTask((ReportingTaskNode) component);
+                       final ReportingTaskNode taskNode = (ReportingTaskNode) 
component;
+                       if (taskNode.isRunning()) {
+                               stopReportingTask((ReportingTaskNode) 
component);
+                       }
                } else if ( component instanceof ProcessorNode ) {
                        final ProcessorNode procNode = (ProcessorNode) 
component;
-                       
stopProcessor(procNode.getProcessGroup().getIdentifier(), 
procNode.getIdentifier());
+                       if ( procNode.isRunning() ) {
+                               
stopProcessor(procNode.getProcessGroup().getIdentifier(), 
procNode.getIdentifier());
+                       }
                }
        }
     }
@@ -2637,6 +2647,11 @@ public class FlowController implements EventAccess, 
ControllerServiceProvider, H
         controllerServiceProvider.removeControllerService(serviceNode);
     }
     
+    @Override
+    public Set<ControllerServiceNode> getAllControllerServices() {
+       return controllerServiceProvider.getAllControllerServices();
+    }
+    
     //
     // Counters
     //

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowFromDOMFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowFromDOMFactory.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowFromDOMFactory.java
index c67181a..d0dc83e 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowFromDOMFactory.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowFromDOMFactory.java
@@ -33,6 +33,7 @@ import org.apache.nifi.scheduling.SchedulingStrategy;
 import org.apache.nifi.util.DomUtils;
 import org.apache.nifi.web.api.dto.ConnectableDTO;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
+import org.apache.nifi.web.api.dto.ControllerServiceDTO;
 import org.apache.nifi.web.api.dto.FlowSnippetDTO;
 import org.apache.nifi.web.api.dto.FunnelDTO;
 import org.apache.nifi.web.api.dto.LabelDTO;
@@ -42,7 +43,7 @@ import org.apache.nifi.web.api.dto.ProcessGroupDTO;
 import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
 import org.apache.nifi.web.api.dto.ProcessorDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
-
+import org.apache.nifi.web.api.dto.ReportingTaskDTO;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
@@ -77,6 +78,40 @@ public class FlowFromDOMFactory {
 
         return styles;
     }
+    
+    public static ControllerServiceDTO getControllerService(final Element 
element, final StringEncryptor encryptor) {
+       final ControllerServiceDTO dto = new ControllerServiceDTO();
+       
+       dto.setId(getString(element, "id"));
+       dto.setName(getString(element, "name"));
+       dto.setComment(getString(element, "comment"));
+       dto.setType(getString(element, "class"));
+       dto.setEnabled(getBoolean(element, "enabled"));
+       dto.setAvailability(getString(element, "availability"));
+       
+        dto.setProperties(getProperties(element, encryptor));
+        dto.setAnnotationData(getString(element, "annotationData"));
+
+        return dto;
+    }
+    
+    public static ReportingTaskDTO getReportingTask(final Element element, 
final StringEncryptor encryptor) {
+       final ReportingTaskDTO dto = new ReportingTaskDTO();
+       
+       dto.setId(getString(element, "id"));
+       dto.setName(getString(element, "name"));
+       dto.setComment(getString(element, "comment"));
+       dto.setType(getString(element, "class"));
+       dto.setSchedulingPeriod(getString(element, "schedulingPeriod"));
+       dto.setScheduledState(getString(element, "scheduledState"));
+       dto.setSchedulingStrategy(getString(element, "schedulingStrategy"));
+       dto.setAvailability(getString(element, "availability"));
+       
+       dto.setProperties(getProperties(element, encryptor));
+       dto.setAnnotationData(getString(element, "annotationData"));
+
+       return dto;
+    }
 
     public static ProcessGroupDTO getProcessGroup(final String parentId, final 
Element element, final StringEncryptor encryptor) {
         final ProcessGroupDTO dto = new ProcessGroupDTO();
@@ -310,7 +345,6 @@ public class FlowFromDOMFactory {
         final ProcessorConfigDTO configDto = new ProcessorConfigDTO();
         dto.setConfig(configDto);
         configDto.setComments(getString(element, "comment"));
-        configDto.setAnnotationData(getString(element, "annotationData"));
         configDto.setConcurrentlySchedulableTaskCount(getInt(element, 
"maxConcurrentTasks"));
         final String schedulingPeriod = getString(element, "schedulingPeriod");
         configDto.setSchedulingPeriod(schedulingPeriod);
@@ -334,14 +368,8 @@ public class FlowFromDOMFactory {
             
configDto.setRunDurationMillis(TimeUnit.NANOSECONDS.toMillis(runDurationNanos));
         }
 
-        final LinkedHashMap<String, String> properties = new LinkedHashMap<>();
-        final List<Element> propertyNodeList = getChildrenByTagName(element, 
"property");
-        for (final Element propertyElement : propertyNodeList) {
-            final String name = getString(propertyElement, "name");
-            final String value = decrypt(getString(propertyElement, "value"), 
encryptor);
-            properties.put(name, value);
-        }
-        configDto.setProperties(properties);
+        configDto.setProperties(getProperties(element, encryptor));
+        configDto.setAnnotationData(getString(element, "annotationData"));
 
         final Set<String> autoTerminatedRelationships = new HashSet<>();
         final List<Element> autoTerminateList = getChildrenByTagName(element, 
"autoTerminatedRelationship");
@@ -353,6 +381,17 @@ public class FlowFromDOMFactory {
         return dto;
     }
 
+    private static LinkedHashMap<String, String> getProperties(final Element 
element, final StringEncryptor encryptor) {
+       final LinkedHashMap<String, String> properties = new LinkedHashMap<>();
+        final List<Element> propertyNodeList = getChildrenByTagName(element, 
"property");
+        for (final Element propertyElement : propertyNodeList) {
+            final String name = getString(propertyElement, "name");
+            final String value = decrypt(getString(propertyElement, "value"), 
encryptor);
+            properties.put(name, value);
+        }
+        return properties;
+    }
+    
     private static String getString(final Element element, final String 
childElementName) {
         final List<Element> nodeList = getChildrenByTagName(element, 
childElementName);
         if (nodeList == null || nodeList.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSerializer.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSerializer.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSerializer.java
index e08a94d..218813a 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSerializer.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSerializer.java
@@ -40,6 +40,7 @@ import org.apache.nifi.connectable.Port;
 import org.apache.nifi.connectable.Position;
 import org.apache.nifi.connectable.Size;
 import org.apache.nifi.controller.label.Label;
+import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.encrypt.StringEncryptor;
 import org.apache.nifi.flowfile.FlowFilePrioritizer;
 import org.apache.nifi.groups.ProcessGroup;
@@ -47,7 +48,6 @@ import org.apache.nifi.groups.RemoteProcessGroup;
 import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.remote.RemoteGroupPort;
 import org.apache.nifi.remote.RootGroupPort;
-
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -79,6 +79,18 @@ public class StandardFlowSerializer implements 
FlowSerializer {
             addTextElement(rootNode, "maxTimerDrivenThreadCount", 
controller.getMaxTimerDrivenThreadCount());
             addTextElement(rootNode, "maxEventDrivenThreadCount", 
controller.getMaxEventDrivenThreadCount());
             addProcessGroup(rootNode, 
controller.getGroup(controller.getRootGroupId()), "rootGroup");
+            
+            final Element controllerServicesNode = 
doc.createElement("controllerServices");
+            rootNode.appendChild(controllerServicesNode);
+            for ( final ControllerServiceNode serviceNode : 
controller.getAllControllerServices() ) {
+               addControllerService(controllerServicesNode, serviceNode);
+            }
+            
+            final Element reportingTasksNode = 
doc.createElement("reportingTasks");
+            rootNode.appendChild(reportingTasksNode);
+            for ( final ReportingTaskNode taskNode : 
controller.getReportingTasks() ) {
+               addReportingTask(reportingTasksNode, taskNode);
+            }
 
             final DOMSource domSource = new DOMSource(doc);
             final StreamResult streamResult = new StreamResult(new 
BufferedOutputStream(os));
@@ -300,8 +312,16 @@ public class StandardFlowSerializer implements 
FlowSerializer {
         addTextElement(element, "schedulingStrategy", 
processor.getSchedulingStrategy().name());
         addTextElement(element, "runDurationNanos", 
processor.getRunDuration(TimeUnit.NANOSECONDS));
 
-        // properties.
-        for (final Map.Entry<PropertyDescriptor, String> entry : 
processor.getProperties().entrySet()) {
+        addConfiguration(element, processor.getProperties(), 
processor.getAnnotationData());
+        
+        for (final Relationship rel : 
processor.getAutoTerminatedRelationships()) {
+            addTextElement(element, "autoTerminatedRelationship", 
rel.getName());
+        }
+    }
+    
+    private void addConfiguration(final Element element, final 
Map<PropertyDescriptor, String> properties, final String annotationData) {
+       final Document doc = element.getOwnerDocument();
+       for (final Map.Entry<PropertyDescriptor, String> entry : 
properties.entrySet()) {
             final PropertyDescriptor descriptor = entry.getKey();
             String value = entry.getValue();
 
@@ -322,14 +342,9 @@ public class StandardFlowSerializer implements 
FlowSerializer {
             element.appendChild(propElement);
         }
 
-        final String annotationData = processor.getAnnotationData();
         if (annotationData != null) {
             addTextElement(element, "annotationData", annotationData);
         }
-
-        for (final Relationship rel : 
processor.getAutoTerminatedRelationships()) {
-            addTextElement(element, "autoTerminatedRelationship", 
rel.getName());
-        }
     }
 
     private void addConnection(final Element parentElement, final Connection 
connection) {
@@ -390,6 +405,37 @@ public class StandardFlowSerializer implements 
FlowSerializer {
         parentElement.appendChild(element);
     }
 
+    
+    private void addControllerService(final Element element, final 
ControllerServiceNode serviceNode) {
+       final Element serviceElement = 
element.getOwnerDocument().createElement("controllerService");
+       addTextElement(serviceElement, "id", serviceNode.getIdentifier());
+       addTextElement(serviceElement, "name", serviceNode.getName());
+       addTextElement(serviceElement, "comment", serviceNode.getComment());
+       addTextElement(serviceElement, "class", 
serviceNode.getControllerServiceImplementation().getClass().getCanonicalName());
+        addTextElement(serviceElement, "enabled", 
String.valueOf(!serviceNode.isDisabled()));
+        addTextElement(serviceElement, "availability", 
serviceNode.getAvailability().toString());
+        
+        addConfiguration(serviceElement, serviceNode.getProperties(), 
serviceNode.getAnnotationData());
+        
+       element.appendChild(serviceElement);
+    }
+    
+    private void addReportingTask(final Element element, final 
ReportingTaskNode taskNode) {
+       final Element taskElement = 
element.getOwnerDocument().createElement("reportingTask");
+       addTextElement(taskElement, "id", taskNode.getIdentifier());
+       addTextElement(taskElement, "name", taskNode.getName());
+       addTextElement(taskElement, "comment", taskNode.getComment());
+       addTextElement(taskElement, "class", 
taskNode.getReportingTask().getClass().getCanonicalName());
+        addTextElement(taskElement, "schedulingPeriod", 
taskNode.getSchedulingPeriod());
+        addTextElement(taskElement, "scheduledState", 
taskNode.getScheduledState().name());
+        addTextElement(taskElement, "schedulingStrategy", 
taskNode.getSchedulingStrategy().name());
+       addTextElement(taskElement, "availability", 
taskNode.getAvailability().toString());
+       
+       addConfiguration(taskElement, taskNode.getProperties(), 
taskNode.getAnnotationData());
+       
+       element.appendChild(taskElement);
+    }
+    
     private void addTextElement(final Element element, final String name, 
final long value) {
         addTextElement(element, name, String.valueOf(value));
     }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
index b60d187..0964a91 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
@@ -40,6 +40,7 @@ import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.nifi.cluster.protocol.DataFlow;
 import org.apache.nifi.cluster.protocol.StandardDataFlow;
 import org.apache.nifi.connectable.Connectable;
@@ -51,8 +52,10 @@ import org.apache.nifi.connectable.Position;
 import org.apache.nifi.connectable.Size;
 import org.apache.nifi.controller.exception.ProcessorInstantiationException;
 import org.apache.nifi.controller.label.Label;
+import 
org.apache.nifi.controller.reporting.ReportingTaskInstantiationException;
+import org.apache.nifi.controller.service.ControllerServiceNode;
+import org.apache.nifi.encrypt.StringEncryptor;
 import org.apache.nifi.events.BulletinFactory;
-import org.apache.nifi.util.file.FileUtils;
 import org.apache.nifi.fingerprint.FingerprintException;
 import org.apache.nifi.fingerprint.FingerprintFactory;
 import org.apache.nifi.flowfile.FlowFilePrioritizer;
@@ -65,9 +68,12 @@ import org.apache.nifi.remote.RemoteGroupPort;
 import org.apache.nifi.remote.RootGroupPort;
 import org.apache.nifi.reporting.Severity;
 import org.apache.nifi.scheduling.SchedulingStrategy;
+import org.apache.nifi.util.DomUtils;
 import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.file.FileUtils;
 import org.apache.nifi.web.api.dto.ConnectableDTO;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
+import org.apache.nifi.web.api.dto.ControllerServiceDTO;
 import org.apache.nifi.web.api.dto.FlowSnippetDTO;
 import org.apache.nifi.web.api.dto.FunnelDTO;
 import org.apache.nifi.web.api.dto.LabelDTO;
@@ -77,9 +83,7 @@ import org.apache.nifi.web.api.dto.ProcessGroupDTO;
 import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
 import org.apache.nifi.web.api.dto.ProcessorDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
-
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.nifi.encrypt.StringEncryptor;
+import org.apache.nifi.web.api.dto.ReportingTaskDTO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -229,6 +233,22 @@ public class StandardFlowSynchronizer implements 
FlowSynchronizer {
                     logger.trace("Updating root process group");
                     updateProcessGroup(controller, /* parent group */ null, 
rootGroupElement, encryptor);
                 }
+                
+                final Element controllerServicesElement = (Element) 
DomUtils.getChild(rootElement, "controllerServices");
+                   if ( controllerServicesElement != null ) {
+                       final List<Element> serviceElements = 
DomUtils.getChildElementsByTagName(controllerServicesElement, 
"controllerService");
+                       for ( final Element serviceElement : serviceElements ) {
+                               addControllerService(controller, 
serviceElement, encryptor);
+                       }
+                }
+                
+                final Element reportingTasksElement = (Element) 
DomUtils.getChild(rootElement, "reportingTasks");
+                if ( reportingTasksElement != null ) {
+                       final List<Element> taskElements = 
DomUtils.getChildElementsByTagName(reportingTasksElement, "reportingTask");
+                       for ( final Element taskElement : taskElements ) {
+                               addReportingTask(controller, taskElement, 
encryptor);
+                       }
+                }
             }
 
             logger.trace("Synching templates");
@@ -313,6 +333,39 @@ public class StandardFlowSynchronizer implements 
FlowSynchronizer {
 
         return baos.toByteArray();
     }
+    
+    private void addControllerService(final FlowController controller, final 
Element controllerServiceElement, final StringEncryptor encryptor) {
+       final ControllerServiceDTO dto = 
FlowFromDOMFactory.getControllerService(controllerServiceElement, encryptor);
+       
+       final ControllerServiceNode node = 
controller.createControllerService(dto.getType(), false);
+       node.setName(dto.getName());
+       node.setAvailability(Availability.valueOf(dto.getAvailability()));
+       node.setComment(dto.getComment());
+       node.setDisabled(dto.getEnabled() != Boolean.TRUE);
+       node.setAnnotationData(dto.getAnnotationData());
+       
+       for ( final Map.Entry<String, String> property : 
dto.getProperties().entrySet() ) {
+               node.setProperty(property.getKey(), property.getValue());
+       }
+    }
+    
+    private void addReportingTask(final FlowController controller, final 
Element reportingTaskElement, final StringEncryptor encryptor) throws 
ReportingTaskInstantiationException {
+       final ReportingTaskDTO dto = 
FlowFromDOMFactory.getReportingTask(reportingTaskElement, encryptor);
+       
+       final ReportingTaskNode reportingTask = 
controller.createReportingTask(dto.getType(), false);
+       reportingTask.setName(dto.getName());
+       reportingTask.setComment(dto.getComment());
+       
reportingTask.setAvailability(Availability.valueOf(dto.getAvailability()));
+       reportingTask.setScheduldingPeriod(dto.getSchedulingPeriod());
+       
reportingTask.setScheduledState(ScheduledState.valueOf(dto.getScheduledState()));
+       
reportingTask.setSchedulingStrategy(SchedulingStrategy.valueOf(dto.getSchedulingStrategy()));
+       
+       reportingTask.setAnnotationData(dto.getAnnotationData());
+       
+       for ( final Map.Entry<String, String> entry : 
dto.getProperties().entrySet() ) {
+               reportingTask.setProperty(entry.getKey(), entry.getValue());
+       }
+    }
 
     private ProcessGroup updateProcessGroup(final FlowController controller, 
final ProcessGroup parentGroup, final Element processGroupElement, final 
StringEncryptor encryptor) throws ProcessorInstantiationException {
 

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java
index 7c3734a..014fe55 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java
@@ -46,7 +46,8 @@ public abstract class AbstractReportingTaskNode extends 
AbstractConfiguredCompon
     private final AtomicReference<SchedulingStrategy> schedulingStrategy = new 
AtomicReference<>(SchedulingStrategy.TIMER_DRIVEN);
     private final AtomicReference<String> schedulingPeriod = new 
AtomicReference<>("5 mins");
     private final AtomicReference<Availability> availability = new 
AtomicReference<>(Availability.NODE_ONLY);
-
+    
+    private volatile String comment;
     private volatile ScheduledState scheduledState = ScheduledState.STOPPED;
     
     public AbstractReportingTaskNode(final ReportingTask reportingTask, final 
String id,
@@ -142,7 +143,8 @@ public abstract class AbstractReportingTaskNode extends 
AbstractConfiguredCompon
         return removed;
     }
     
-    private void onConfigured() {
+    @SuppressWarnings("deprecation")
+       private void onConfigured() {
         // We need to invoke any method annotation with the OnConfigured 
annotation in order to
         // maintain backward compatibility. This will be removed when we 
remove the old, deprecated annotations.
         try (final NarCloseable x = NarCloseable.withNarLoader()) {
@@ -158,6 +160,16 @@ public abstract class AbstractReportingTaskNode extends 
AbstractConfiguredCompon
     }
     
     @Override
+    public String getComment() {
+               return comment;
+       }
+
+    @Override
+       public void setComment(final String comment) {
+               this.comment = comment;
+       }
+
+       @Override
     public void verifyCanDelete() {
         if (isRunning()) {
             throw new IllegalStateException("Cannot delete " + reportingTask + 
" because it is currently running");

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
index db44b5f..7504d13 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
@@ -122,11 +122,10 @@ public class ControllerServiceLoader {
                 for (final Element serviceElement : serviceNodes) {
                     //get properties for the specific controller task - id, 
name, class,
                     //and schedulingPeriod must be set
-                    final String serviceId = DomUtils.getChild(serviceElement, 
"identifier").getTextContent().trim();
                     final String serviceClass = 
DomUtils.getChild(serviceElement, "class").getTextContent().trim();
 
                     //set the class to be used for the configured controller 
task
-                    final ControllerServiceNode serviceNode = 
provider.createControllerService(serviceClass, serviceId, false);
+                    final ControllerServiceNode serviceNode = 
provider.createControllerService(serviceClass, false);
 
                     //optional task-specific properties
                     for (final Element optionalProperty : 
DomUtils.getChildElementsByTagName(serviceElement, "property")) {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
index b829bbd..f5776ce 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
@@ -49,6 +49,7 @@ public class StandardControllerServiceNode extends 
AbstractConfiguredComponent i
     private final Lock writeLock = rwLock.writeLock();
 
     private final Set<ConfiguredComponent> referencingComponents = new 
HashSet<>();
+    private String comment;
 
     public StandardControllerServiceNode(final ControllerService 
proxiedControllerService, final ControllerService implementation, final String 
id,
             final ValidationContextFactory validationContextFactory, final 
ControllerServiceProvider serviceProvider) {
@@ -193,4 +194,24 @@ public class StandardControllerServiceNode extends 
AbstractConfiguredComponent i
             throw new IllegalStateException(implementation + " cannot be 
updated because it is not disabled");
         }
     }
+    
+    @Override
+    public String getComment() {
+       readLock.lock();
+       try {
+               return comment;
+       } finally {
+               readLock.unlock();
+       }
+    }
+    
+    @Override
+    public void setComment(final String comment) {
+       writeLock.lock();
+       try {
+               this.comment = comment;
+       } finally {
+               writeLock.unlock();
+       }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceProvider.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceProvider.java
index b07fc3f..75de4b9 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceProvider.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceProvider.java
@@ -30,10 +30,11 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.nifi.annotation.lifecycle.OnAdded;
-import org.apache.nifi.annotation.lifecycle.OnEnabled;
 import org.apache.nifi.annotation.lifecycle.OnDisabled;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
 import org.apache.nifi.annotation.lifecycle.OnRemoved;
 import org.apache.nifi.controller.ConfigurationContext;
 import org.apache.nifi.controller.ControllerService;
@@ -55,7 +56,7 @@ public class StandardControllerServiceProvider implements 
ControllerServiceProvi
 
     private static final Logger logger = 
LoggerFactory.getLogger(StandardControllerServiceProvider.class);
 
-    private final Map<String, ControllerServiceNode> controllerServices;
+    private final ConcurrentMap<String, ControllerServiceNode> 
controllerServices;
     private static final Set<Method> validDisabledMethods;
 
     static {
@@ -245,4 +246,9 @@ public class StandardControllerServiceProvider implements 
ControllerServiceProvi
         
         controllerServices.remove(serviceNode.getIdentifier());
     }
+    
+    @Override
+    public Set<ControllerServiceNode> getAllControllerServices() {
+       return new HashSet<>(controllerServices.values());
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/persistence/StandardXMLFlowConfigurationDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/persistence/StandardXMLFlowConfigurationDAO.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/persistence/StandardXMLFlowConfigurationDAO.java
index c11aa72..039b2c2 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/persistence/StandardXMLFlowConfigurationDAO.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/persistence/StandardXMLFlowConfigurationDAO.java
@@ -219,7 +219,6 @@ public final class StandardXMLFlowConfigurationDAO 
implements FlowConfigurationD
 
                 //get properties for the specific reporting task - id, name, 
class,
                 //and schedulingPeriod must be set
-                final String taskId = DomUtils.getChild(taskElement, 
"id").getTextContent().trim();
                 final String taskName = DomUtils.getChild(taskElement, 
"name").getTextContent().trim();
 
                 final List<Element> schedulingStrategyNodeList = 
DomUtils.getChildElementsByTagName(taskElement, "schedulingStrategy");
@@ -230,7 +229,7 @@ public final class StandardXMLFlowConfigurationDAO 
implements FlowConfigurationD
                     try {
                         schedulingStrategyValue = 
SchedulingStrategy.valueOf(specifiedValue).name();
                     } catch (final Exception e) {
-                        throw new RuntimeException("Cannot start Reporting 
Task with id " + taskId + " because its Scheduling Strategy does not have a 
valid value", e);
+                        throw new RuntimeException("Cannot start Reporting 
Task with name " + taskName + " because its Scheduling Strategy does not have a 
valid value", e);
                     }
                 }
 
@@ -248,9 +247,9 @@ public final class StandardXMLFlowConfigurationDAO 
implements FlowConfigurationD
                 //set the class to be used for the configured reporting task
                 final ReportingTaskNode reportingTaskNode;
                 try {
-                    reportingTaskNode = 
controller.createReportingTask(taskClass, taskId);
+                    reportingTaskNode = 
controller.createReportingTask(taskClass);
                 } catch (final ReportingTaskInstantiationException e) {
-                    LOG.error("Unable to load reporting task {} due to {}", 
new Object[]{taskId, e});
+                    LOG.error("Unable to load reporting task {} due to {}", 
new Object[]{taskName, e});
                     if (LOG.isDebugEnabled()) {
                         LOG.error("", e);
                     }
@@ -263,7 +262,8 @@ public final class StandardXMLFlowConfigurationDAO 
implements FlowConfigurationD
 
                 final ReportingTask reportingTask = 
reportingTaskNode.getReportingTask();
 
-                final ReportingInitializationContext config = new 
StandardReportingInitializationContext(taskId, taskName, schedulingStrategy, 
taskSchedulingPeriod, controller);
+                final ReportingInitializationContext config = new 
StandardReportingInitializationContext(
+                               reportingTask.getIdentifier(), taskName, 
schedulingStrategy, taskSchedulingPeriod, controller);
                 reportingTask.initialize(config);
 
                 final Map<PropertyDescriptor, String> resolvedProps;

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/86d15f9e/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 603c1d2..5ed25e6 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -438,6 +438,10 @@ public class ControllerFacade implements 
ControllerServiceProvider {
        return flowController.getControllerServiceName(serviceIdentifier);
     }
 
+    @Override
+    public Set<ControllerServiceNode> getAllControllerServices() {
+       return flowController.getAllControllerServices();
+    }
 
     @Override
     public void enableControllerService(final ControllerServiceNode 
serviceNode) {

Reply via email to