You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2015/01/26 21:17:28 UTC

[4/5] incubator-nifi git commit: NIFI-250: Serialize and deserialize controller services and reporting tasks in the flow.xml

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 <ma...@hotmail.com>
Authored: Mon Jan 26 13:55:55 2015 -0500
Committer: Mark Payne <ma...@hotmail.com>
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) {