You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2015/01/13 20:54:06 UTC

incubator-nifi git commit: NIFI-250: - Creating endpoints for returning the available controller services and reporting tasks. - Made the Setting tabbed to provide a place for configuring controller services and reporting tasks.

Repository: incubator-nifi
Updated Branches:
  refs/heads/NIFI-250 [created] 03d422e4d


NIFI-250:
- Creating endpoints for returning the available controller services and reporting tasks.
- Made the Setting tabbed to provide a place for configuring controller services and reporting tasks.

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

Branch: refs/heads/NIFI-250
Commit: 03d422e4d4d65ebe4b080fc5ec88cc7aae30ae82
Parents: b6b1859
Author: Matt Gilman <ma...@gmail.com>
Authored: Tue Jan 13 14:52:23 2015 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Tue Jan 13 14:52:23 2015 -0500

----------------------------------------------------------------------
 .../web/api/dto/DocumentedChildTypeDTO.java     |  43 ++++
 .../entity/ControllerServiceTypesEntity.java    |  46 ++++
 .../api/entity/ReportingTaskTypesEntity.java    |  46 ++++
 .../org/apache/nifi/web/NiFiServiceFacade.java  |  16 +-
 .../nifi/web/StandardNiFiServiceFacade.java     |  12 +-
 .../apache/nifi/web/api/ControllerResource.java |  68 +++++
 .../org/apache/nifi/web/api/dto/DtoFactory.java |  50 ++++
 .../nifi/web/controller/ControllerFacade.java   |  22 ++
 .../partials/canvas/settings-content.jsp        |  82 ++++---
 .../src/main/webapp/css/settings.css            |  84 ++++++-
 .../src/main/webapp/js/nf/canvas/nf-canvas.js   |   1 +
 .../src/main/webapp/js/nf/canvas/nf-settings.js | 246 +++++++++++++------
 12 files changed, 603 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedChildTypeDTO.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedChildTypeDTO.java b/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedChildTypeDTO.java
new file mode 100644
index 0000000..f34798a
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedChildTypeDTO.java
@@ -0,0 +1,43 @@
+/*
+ * 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.Set;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Class used for providing documentation of a specified child type that may be
+ * instantiated. Also supports specifying what the underlying base classes are.
+ */
+@XmlType(name = "documentedChildType")
+public class DocumentedChildTypeDTO extends DocumentedTypeDTO {
+
+    private Set<String> baseTypes;
+
+    /**
+     * The type is the fully-qualified name of a Java class.
+     *
+     * @return
+     */
+    public Set<String> getBaseType() {
+        return baseTypes;
+    }
+
+    public void setBaseType(Set<String> baseTypes) {
+        this.baseTypes = baseTypes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java b/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java
new file mode 100644
index 0000000..622d1dc
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceTypesEntity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.entity;
+
+import java.util.Set;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.nifi.web.api.dto.DocumentedTypeDTO;
+
+/**
+ * A serialized representation of this class can be placed in the entity body of
+ * a response to the API. This particular entity holds a reference to a list of
+ * controller service types.
+ */
+@XmlRootElement(name = "controllerServiceTypesEntity")
+public class ControllerServiceTypesEntity extends Entity {
+
+    private Set<DocumentedTypeDTO> controllerServiceTypes;
+
+    /**
+     * The list of controller service types that are being serialized.
+     *
+     * @return
+     */
+    public Set<DocumentedTypeDTO> getControllerSerivceTypes() {
+        return controllerServiceTypes;
+    }
+
+    public void setControllerServiceTypes(Set<DocumentedTypeDTO> controllerServiceTypes) {
+        this.controllerServiceTypes = controllerServiceTypes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java b/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java
new file mode 100644
index 0000000..4b021ef
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/client-dto/src/main/java/org/apache/nifi/web/api/entity/ReportingTaskTypesEntity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.entity;
+
+import java.util.Set;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.nifi.web.api.dto.DocumentedTypeDTO;
+
+/**
+ * A serialized representation of this class can be placed in the entity body of
+ * a response to the API. This particular entity holds a reference to a list of
+ * reporting task types.
+ */
+@XmlRootElement(name = "reportingTaskTypesEntity")
+public class ReportingTaskTypesEntity extends Entity {
+
+    private Set<DocumentedTypeDTO> reportingTaskTypes;
+
+    /**
+     * The list of reporting task types that are being serialized.
+     *
+     * @return
+     */
+    public Set<DocumentedTypeDTO> getReportingTaskTypes() {
+        return reportingTaskTypes;
+    }
+
+    public void setReportingTaskTypes(Set<DocumentedTypeDTO> reportingTaskTypes) {
+        this.reportingTaskTypes = reportingTaskTypes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
index ae6bf28..b0001ec 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
@@ -243,7 +243,21 @@ public interface NiFiServiceFacade {
      * @return The list of available processor types
      */
     Set<DocumentedTypeDTO> getProcessorTypes();
-
+    
+    /**
+     * Returns the list of controller service types.
+     * 
+     * @return The list of available controller types
+     */
+    Set<DocumentedTypeDTO> getControllerServiceTypes();
+    
+    /**
+     * Returns the list of reporting task types.
+     * 
+     * @return The list of available reporting task types
+     */
+    Set<DocumentedTypeDTO> getReportingTaskTypes();
+    
     /**
      * Returns the list of prioritizer types.
      *

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index c8683b0..41660f2 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -16,8 +16,6 @@
  */
 package org.apache.nifi.web;
 
-import org.apache.nifi.web.OptimisticLockingManager;
-import org.apache.nifi.web.ConfigurationSnapshot;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -1640,6 +1638,16 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     }
 
     @Override
+    public Set<DocumentedTypeDTO> getControllerServiceTypes() {
+        return controllerFacade.getControllerServiceTypes();
+    }
+
+    @Override
+    public Set<DocumentedTypeDTO> getReportingTaskTypes() {
+        return controllerFacade.getReportingTaskTypes();
+    }
+
+    @Override
     public ProcessorDTO getProcessor(String groupId, String id) {
         final ProcessorNode processor = processorDAO.getProcessor(groupId, id);
         final ProcessorDTO processorDto = dtoFactory.createProcessorDto(processor);

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
index 3afe0e1..d13e4ce 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
@@ -72,6 +72,8 @@ import org.apache.nifi.web.api.request.ClientIdParameter;
 import org.apache.nifi.web.api.request.IntegerParameter;
 import org.apache.nifi.web.api.request.LongParameter;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.web.api.entity.ControllerServiceTypesEntity;
+import org.apache.nifi.web.api.entity.ReportingTaskTypesEntity;
 import org.codehaus.enunciate.jaxrs.TypeHint;
 import org.springframework.security.access.prepost.PreAuthorize;
 
@@ -713,6 +715,72 @@ public class ControllerResource extends ApplicationResource {
         // generate the response
         return clusterContext(generateOkResponse(entity)).build();
     }
+    
+    /**
+     * Retrieves the types of controller services that this NiFi supports.
+     *
+     * @param clientId Optional client id. If the client id is not specified, a
+     * new one will be generated. This value (whether specified or generated) is
+     * included in the response.
+     * @return A controllerServicesTypesEntity.
+     */
+    @GET
+    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    @Path("/controller-service-types")
+    @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+    @TypeHint(ControllerServiceTypesEntity.class)
+    public Response getControllerServiceTypes(@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) {
+
+        // replicate if cluster manager
+        if (properties.isClusterManager()) {
+            return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse();
+        }
+
+        // create the revision
+        final RevisionDTO revision = new RevisionDTO();
+        revision.setClientId(clientId.getClientId());
+
+        // create response entity
+        final ControllerServiceTypesEntity entity = new ControllerServiceTypesEntity();
+        entity.setRevision(revision);
+        entity.setControllerServiceTypes(serviceFacade.getControllerServiceTypes());
+
+        // generate the response
+        return clusterContext(generateOkResponse(entity)).build();
+    }
+    
+    /**
+     * Retrieves the types of reporting tasks that this NiFi supports.
+     *
+     * @param clientId Optional client id. If the client id is not specified, a
+     * new one will be generated. This value (whether specified or generated) is
+     * included in the response.
+     * @return A controllerServicesTypesEntity.
+     */
+    @GET
+    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    @Path("/reporting-task-types")
+    @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+    @TypeHint(ReportingTaskTypesEntity.class)
+    public Response getReportingTaskTypes(@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) {
+
+        // replicate if cluster manager
+        if (properties.isClusterManager()) {
+            return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse();
+        }
+
+        // create the revision
+        final RevisionDTO revision = new RevisionDTO();
+        revision.setClientId(clientId.getClientId());
+
+        // create response entity
+        final ReportingTaskTypesEntity entity = new ReportingTaskTypesEntity();
+        entity.setRevision(revision);
+        entity.setReportingTaskTypes(serviceFacade.getControllerServiceTypes());
+
+        // generate the response
+        return clusterContext(generateOkResponse(entity)).build();
+    }
 
     /**
      * Retrieves the types of prioritizers that this NiFi supports.

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 9a2dc30..9ef6287 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -1128,6 +1128,56 @@ public final class DtoFactory {
 
         return types;
     }
+    
+    /**
+     * Identifies all baseTypes for the specified type that are assignable to the specified baseType.
+     * 
+     * @param baseType
+     * @param type
+     * @param baseTypes 
+     */
+    private void identifyBaseTypes(final Class baseType, final Class type, final Set<String> baseTypes) {
+        final Class[] interfaces = type.getInterfaces();
+        for (final Class i : interfaces) {
+            if (baseType.isAssignableFrom(i) && !baseType.equals(i)) {
+                baseTypes.add(i.getName());
+            }
+        }
+        
+        if (type.getSuperclass() != null) {
+            identifyBaseTypes(baseType, type.getSuperclass(), baseTypes);
+        }
+    }
+    
+    /**
+     * Gets the DocumentedTypeDTOs from the specified classes for the specified baseClass.
+     *
+     * @param baseClass
+     * @param classes
+     * @return
+     */
+    public Set<DocumentedTypeDTO> fromDocumentedTypes(final Class baseClass, final Set<Class> classes) {
+        final Set<DocumentedTypeDTO> types = new LinkedHashSet<>();
+        final Set<Class> sortedClasses = new TreeSet<>(CLASS_NAME_COMPARATOR);
+        sortedClasses.addAll(classes);
+
+        for (final Class<?> cls : sortedClasses) {
+            final DocumentedChildTypeDTO type = new DocumentedChildTypeDTO();
+            type.setType(cls.getName());
+            type.setDescription(getCapabilityDescription(cls));
+            type.setTags(getTags(cls));
+            
+            // identify the base types
+            final Set<String> baseTypes = new LinkedHashSet<>();
+            identifyBaseTypes(baseClass, cls, baseTypes);
+            type.setBaseType(baseTypes);
+            
+            // add this type
+            types.add(type);
+        }
+
+        return types;
+    }
 
     /**
      * Creates a ProcessorDTO from the specified ProcessorNode.

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index dbc4b3c..a9ad968 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -114,6 +114,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.admin.service.UserService;
 import org.apache.nifi.authorization.DownloadAuthorization;
 import org.apache.nifi.processor.DataUnit;
+import org.apache.nifi.reporting.ReportingTask;
+import org.apache.nifi.web.api.dto.DocumentedChildTypeDTO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.access.AccessDeniedException;
@@ -347,6 +349,24 @@ public class ControllerFacade implements ControllerServiceProvider {
     public Set<DocumentedTypeDTO> getFlowFileComparatorTypes() {
         return dtoFactory.fromDocumentedTypes(ExtensionManager.getExtensions(FlowFilePrioritizer.class));
     }
+    
+    /**
+     * Gets the ControllerService types that this controller supports.
+     * 
+     * @return 
+     */
+    public Set<DocumentedTypeDTO> getControllerServiceTypes() {
+        return dtoFactory.fromDocumentedTypes(ControllerService.class, ExtensionManager.getExtensions(ControllerService.class));
+    }
+    
+    /**
+     * Gets the ReportingTask types that this controller supports.
+     * 
+     * @return 
+     */
+    public Set<DocumentedTypeDTO> getReportingTaskTypes() {
+        return dtoFactory.fromDocumentedTypes(ReportingTask.class, ExtensionManager.getExtensions(ReportingTask.class));
+    }
 
     /**
      * Gets the counters for this controller.
@@ -371,6 +391,8 @@ public class ControllerFacade implements ControllerServiceProvider {
 
         return counter;
     }
+    
+    
 
     /**
      * Return the controller service for the specified identifier.

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/settings-content.jsp
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/settings-content.jsp b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/settings-content.jsp
index d9b2f29..b235bdf 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/settings-content.jsp
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/settings-content.jsp
@@ -18,43 +18,59 @@
 <div id="settings">
     <div id="settings-header-text">NiFi Settings</div>
     <div id="settings-container">
-        <div id="general-settings">
-            <div class="setting">
-                <div class="setting-name">Data flow name</div>
-                <div class="setting-field">
-                    <input type="text" id="data-flow-title-field" name="data-flow-title" class="setting-input"/>
-                    <span id="archive-flow-link" class="link">Back-up flow</span>
-                    <img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="Archives the flow configuration."/>
-                </div>
-            </div>
-            <div class="setting">
-                <div class="setting-name">Data flow comments</div>
-                <div class="setting-field">
-                    <textarea id="data-flow-comments-field" name="data-flow-comments" class="setting-input"></textarea>
+        <div id="settings-tabs-container">
+            <div id="settings-tabs"></div>
+            <div id="new-service-or-task" class="add-icon-bg"></div>
+            <div class="clear"></div>
+        </div>
+        <div id="settings-tab-background"></div>
+        <div id="settings-tabs-content">
+            <div id="general-settings-tab-content" class="configuration-tab">
+                <div id="general-settings">
+                    <div class="setting">
+                        <div class="setting-name">Data flow name</div>
+                        <div class="setting-field">
+                            <input type="text" id="data-flow-title-field" name="data-flow-title" class="setting-input"/>
+                            <span id="archive-flow-link" class="link">Back-up flow</span>
+                            <img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="Archives the flow configuration."/>
+                        </div>
+                    </div>
+                    <div class="setting">
+                        <div class="setting-name">Data flow comments</div>
+                        <div class="setting-field">
+                            <textarea id="data-flow-comments-field" name="data-flow-comments" class="setting-input"></textarea>
+                        </div>
+                    </div>
+                    <div class="setting">
+                        <div class="setting-name">
+                            Maximum timer driven thread count
+                            <img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum number of threads for timer driven processors available to the system."/>
+                        </div>
+                        <div class="setting-field">
+                            <input type="text" id="maximum-timer-driven-thread-count-field" class="setting-input"/>
+                        </div>
+                    </div>
+                    <div class="setting">
+                        <div class="setting-name">
+                            Maximum event driven thread count
+                            <img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum number of threads for event driven processors available to the system."/>
+                        </div>
+                        <div class="setting-field">
+                            <input type="text" id="maximum-event-driven-thread-count-field" class="setting-input"/>
+                        </div>
+                    </div>
+                    <div id="settings-buttons">
+                        <div id="settings-save" class="button">Apply</div>
+                        <div class="clear"></div>
+                    </div>
                 </div>
             </div>
-            <div class="setting">
-                <div class="setting-name">
-                    Maximum timer driven thread count
-                    <img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum number of threads for timer driven processors available to the system."/>
-                </div>
-                <div class="setting-field">
-                    <input type="text" id="maximum-timer-driven-thread-count-field" class="setting-input"/>
-                </div>
+            <div id="controller-services-tab-content" class="configuration-tab">
+                <div id="controller-services-table" class="settings-table"></div>
             </div>
-            <div class="setting">
-                <div class="setting-name">
-                    Maximum event driven thread count
-                    <img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum number of threads for event driven processors available to the system."/>
-                </div>
-                <div class="setting-field">
-                    <input type="text" id="maximum-event-driven-thread-count-field" class="setting-input"/>
-                </div>
+            <div id="reporting-tasks-tab-content" class="configuration-tab">
+                <div id="reporting-tasks-table" class="settings-table"></div>
             </div>
         </div>
-        <div id="settings-buttons">
-            <div id="settings-cancel" class="button">Cancel</div>
-            <div id="settings-save" class="button">Apply</div>
-        </div>
     </div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
index e9d78d4..0622aa9 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/css/settings.css
@@ -21,23 +21,93 @@
     bottom: 0px;
     left: 0px;
     display: none;
+    padding: 20px;
 }
 
 #settings-header-text {
     height: 35px;
-    margin-top: 20px;
-    margin-left: 20px;
     font-size: 16px;
     font-weight: bold;
 }
 
 #settings-container {
-    margin-top: -10px;
+    margin-top: 18px;
 }
 
+#new-service-or-task {
+    float: right;
+    width: 19px;
+    height: 19px;
+    margin-top: 4px;
+    cursor: pointer;
+}
+
+/* settings tabs */
+
+#settings-tabs-container {
+    border-bottom: 2px solid #666;
+}
+
+#settings-tabs {
+    float: left;
+}
+
+.settings-tab {
+    display: block;
+    padding: 0 5px;
+    height: 26px;
+    float: left;
+    color: #666;
+    background-color: #ccc;
+    border-left: 1px solid #b5b5b5;
+    border-top: 1px solid #b5b5b5;
+    border-right: 1px solid #b5b5b5;
+    margin-right: 5px;
+    text-align: center;
+    cursor: pointer;
+    line-height: 26px;
+    font-weight: bold;
+}
+
+.settings-selected-tab {
+    color: #fff;
+    background-color: #666;
+    border-left: 1px solid #666;
+    border-top: 1px solid #666;
+    border-right: 1px solid #666;
+}
+
+#settings-tab-background {
+    height: 200px;
+    margin-top: 1px;
+    background-color: transparent;
+    background: linear-gradient(to bottom, #dddddd, #ffffff);
+    filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr=#dddddd, endColorstr=#ffffff);
+}
+
+#settings div.configuration-tab {
+    display: none;
+}
+
+div.settings-table {
+    position: absolute;
+    top: 115px;
+    left: 25px;
+    bottom: 20px;
+    right: 25px;
+    border: 1px solid #666;
+    overflow: hidden;
+    background-color: #fff;
+}
+
+span.sorted {
+    text-decoration: underline;
+}
+
+/* general */
+
 #general-settings {
-    padding-left: 10px;
-    margin-top: 15px;
+    margin-top: -190px;
     margin-left: 10px;
 }
 
@@ -53,11 +123,11 @@
 }
 
 #settings-buttons {
-    margin-left: 260px;
+    margin-left: 304px;
     margin-top: 10px;
 }
 
-#settings-save, #settings-cancel {
+#settings-save {
     float: left;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
index 5c1cbb8..8742047 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
@@ -512,6 +512,7 @@ nf.Canvas = (function () {
         // listen for browser resize events to reset the graph size
         $(window).on('resize', function () {
             updateGraphSize();
+            nf.Settings.resetTableSize();
         }).on('keydown', function (evt) {
             // if a dialog is open, disable canvas shortcuts
             if ($('.dialog').is(':visible')) {

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/03d422e4/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index 3d573b3..8015be5 100644
--- a/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nar-bundles/framework-bundle/framework/web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -19,11 +19,75 @@ nf.Settings = (function () {
     var config = {
         urls: {
             controllerConfig: '../nifi-api/controller/config',
-            controllerArchive: '../nifi-api/controller/archive'
+            controllerArchive: '../nifi-api/controller/archive',
+            controllerServiceTypes: '../nifi-api/controller/controller-service-types',
+            reportingTaskTypes: '../nifi-api/controller/reporting-task-types'
         }
     };
 
     /**
+     * Initializes the general tab.
+     */
+    var initGeneral = function () {
+        // register the click listener for the archive link
+        $('#archive-flow-link').click(function () {
+            var revision = nf.Client.getRevision();
+
+            $.ajax({
+                type: 'POST',
+                url: config.urls.controllerArchive,
+                data: {
+                    version: revision.version,
+                    clientId: revision.clientId
+                },
+                dataType: 'json'
+            }).done(function (response) {
+                // update the revision
+                nf.Client.setRevision(response.revision);
+
+                // show the result dialog
+                nf.Dialog.showOkDialog({
+                    dialogContent: 'A new flow archive was successfully created.',
+                    overlayBackground: false
+                });
+            }).fail(nf.Common.handleAjaxError);
+        });
+
+        // register the click listener for the save button
+        $('#settings-save').click(function () {
+            var revision = nf.Client.getRevision();
+
+            // marshal the configuration details
+            var configuration = marshalConfiguration();
+            configuration['version'] = revision.version;
+            configuration['clientId'] = revision.clientId;
+
+            // save the new configuration details
+            $.ajax({
+                type: 'PUT',
+                url: config.urls.controllerConfig,
+                data: configuration,
+                dataType: 'json'
+            }).done(function (response) {
+                // update the revision
+                nf.Client.setRevision(response.revision);
+
+                // update the displayed name
+                document.title = response.config.name;
+
+                // set the data flow title and close the shell
+                $('#data-flow-title-container').children('span.link:first-child').text(response.config.name);
+
+                // close the settings dialog
+                nf.Dialog.showOkDialog({
+                    dialogContent: 'Settings successfully applied.',
+                    overlayBackground: false
+                });
+            }).fail(nf.Common.handleAjaxError);
+        });
+    };
+
+    /**
      * Marshals the details to include in the configuration request.
      */
     var marshalConfiguration = function () {
@@ -35,83 +99,125 @@ nf.Settings = (function () {
         configuration['maxEventDrivenThreadCount'] = $('#maximum-event-driven-thread-count-field').val();
         return configuration;
     };
+    
+    
+    
+    /**
+     * Initializes the controller services tab.
+     */
+    var initControllerServies = function () {
+        $.ajax({
+            type: 'GET',
+            url: config.urls.controllerServiceTypes,
+            dataType: 'json'
+        }).done(function(response) {
+            console.log(response);
+        });
+        
+        var moreControllerServiceDetails = function (row, cell, value, columnDef, dataContext) {
+            return '<img src="images/iconDetails.png" title="View Details" class="pointer" style="margin-top: 5px; float: left;" onclick="javascript:nf.Settings.showControllerServiceDetails(\'' + row + '\');"/>';
+        };
+        
+        // define the column model for the controller services table
+        var controllerServicesColumnModel = [
+            {id: 'moreDetails', field: 'moreDetails', name: '&nbsp;', resizable: false, formatter: moreControllerServiceDetails, sortable: true, width: 50, maxWidth: 50},
+            {id: 'id', field: 'id', name: 'Identifier', sortable: true, resizable: true},
+            {id: 'type', field: 'type', name: 'Type', sortable: true, resizable: true}
+        ];
+    };
+    
+    /**
+     * Initializes the reporting tasks tab.
+     */
+    var initReportingTasks = function () {
+        $.ajax({
+            type: 'GET',
+            url: config.urls.reportingTaskTypes,
+            dataType: 'json'
+        }).done(function(response) {
+            console.log(response);
+        });
+        
+        var moreReportingTaskDetails = function (row, cell, value, columnDef, dataContext) {
+            return '<img src="images/iconDetails.png" title="View Details" class="pointer" style="margin-top: 5px; float: left;" onclick="javascript:nf.Settings.showControllerServiceDetails(\'' + row + '\');"/>';
+        };
+        
+        // define the column model for the reporting tasks table
+        var reportingTasksColumnModel = [
+            {id: 'moreDetails', field: 'moreDetails', name: '&nbsp;', resizable: false, formatter: moreReportingTaskDetails, sortable: true, width: 50, maxWidth: 50},
+            {id: 'id', field: 'id', name: 'Identifier', sortable: true, resizable: true},
+            {id: 'type', field: 'type', name: 'Type', sortable: true, resizable: true},
+            
+        ];
+    };
 
     return {
         /**
          * Initializes the status page.
          */
         init: function () {
-
-            // register the click listener for the archive link
-            $('#archive-flow-link').click(function () {
-                var revision = nf.Client.getRevision();
-
-                $.ajax({
-                    type: 'POST',
-                    url: config.urls.controllerArchive,
-                    data: {
-                        version: revision.version,
-                        clientId: revision.clientId
-                    },
-                    dataType: 'json'
-                }).done(function (response) {
-                    // update the revision
-                    nf.Client.setRevision(response.revision);
-
-                    // show the result dialog
-                    nf.Dialog.showOkDialog({
-                        dialogContent: 'A new flow archive was successfully created.',
-                        overlayBackground: false
-                    });
-                }).fail(function (xhr, status, error) {
-                    // close the details panel
-                    $('#settings-cancel').click();
-
-                    // handle the error
-                    nf.Common.handleAjaxError(xhr, status, error);
-                });
+            // initialize the settings tabs
+            $('#settings-tabs').tabbs({
+                tabStyle: 'settings-tab',
+                selectedTabStyle: 'settings-selected-tab',
+                tabs: [{
+                    name: 'General',
+                    tabContentId: 'general-settings-tab-content'
+                }, {
+                    name: 'Controller Services',
+                    tabContentId: 'controller-services-tab-content'
+                }, {
+                    name: 'Reporting Tasks',
+                    tabContentId: 'reporting-tasks-tab-content'
+                }],
+                select: function () {
+                    var tab = $(this).text();
+                    if (tab === 'General') {
+                        $('#new-service-or-task').hide();
+                    } else {
+                        $('#new-service-or-task').show();
+                        
+                        // update the tooltip on the button
+                        $('#new-service-or-task').attr('title', function() {
+                            if (tab === 'Controller Services') {
+                                return 'Create a new controller service';
+                            } else if (tab === 'Reporting Tasks') {
+                                return 'Create a new reporting task';
+                            }
+                        });
+                    }
+                }
             });
-
-            // register the click listener for the save button
-            $('#settings-save').click(function () {
-                var revision = nf.Client.getRevision();
-
-                // marshal the configuration details
-                var configuration = marshalConfiguration();
-                configuration['version'] = revision.version;
-                configuration['clientId'] = revision.clientId;
-
-                // save the new configuration details
-                $.ajax({
-                    type: 'PUT',
-                    url: config.urls.controllerConfig,
-                    data: configuration,
-                    dataType: 'json'
-                }).done(function (response) {
-                    // update the revision
-                    nf.Client.setRevision(response.revision);
-
-                    // update the displayed name
-                    document.title = response.config.name;
-
-                    // set the data flow title and close the shell
-                    $('#data-flow-title-container').children('span.link:first-child').text(response.config.name);
-
-                    // close the settings dialog
-                    $('#shell-close-button').click();
-                }).fail(function (xhr, status, error) {
-                    // close the details panel
-                    $('#settings-cancel').click();
-
-                    // handle the error
-                    nf.Common.handleAjaxError(xhr, status, error);
-                });
+            
+            // create a new controller service or reporting task
+            $('#new-service-or-task').on('click', function() {
+                var selectedTab = $('li.settings-selected-tab').text();
+                if (selectedTab === 'Controller Services') {
+                    
+                } else if (selectedTab === 'Reporting Tasks') {
+                    
+                }
             });
 
-            // install a cancel button listener to close the shell
-            $('#settings-cancel').click(function () {
-                $('#shell-close-button').click();
-            });
+            // initialize each tab
+            initGeneral();
+            initControllerServies();
+            initReportingTasks();
+        },
+        
+        /**
+         * Update the size of the grid based on its container's current size.
+         */
+        resetTableSize: function () {
+            var controllerServicesGrid = $('#controller-services-table').data('gridInstance');
+            if (nf.Common.isDefinedAndNotNull(controllerServicesGrid)) {
+                controllerServicesGrid.resizeCanvas();
+            }
+
+            var reportingTasksGrid = $('#reporting-tasks-table').data('gridInstance');
+            if (nf.Common.isDefinedAndNotNull(reportingTasksGrid)) {
+                reportingTasksGrid.resizeCanvas();
+            }
         },
         
         /**
@@ -138,7 +244,7 @@ nf.Settings = (function () {
                 // show the settings dialog
                 nf.Shell.showContent('#settings').done(function () {
                     // reset button state
-                    $('#settings-save, #settings-cancel').mouseout();
+                    $('#settings-save').mouseout();
                 });
             }).fail(nf.Common.handleAjaxError);
         }