You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2015/04/14 23:33:23 UTC

ambari git commit: AMBARI-10484. Expose API endpoint to expose active widget layout for a user.

Repository: ambari
Updated Branches:
  refs/heads/trunk 073cec990 -> 958fd13ec


AMBARI-10484. Expose API endpoint to expose active widget layout for a user.


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

Branch: refs/heads/trunk
Commit: 958fd13ec71ccbb4b2ce86abb5b007c32e90cba8
Parents: 073cec9
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Tue Apr 14 14:33:06 2015 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Tue Apr 14 14:33:15 2015 -0700

----------------------------------------------------------------------
 .../ActiveWidgetLayoutResourceDefinition.java   |  89 +++++++
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../api/resources/UserResourceDefinition.java   |   1 +
 .../api/services/ActiveWidgetLayoutService.java |  80 ++++++
 .../ambari/server/api/services/UserService.java |  10 +
 .../AbstractControllerResourceProvider.java     |   2 +
 .../ActiveWidgetLayoutResourceProvider.java     | 226 ++++++++++++++++
 .../ambari/server/controller/spi/Resource.java  |   2 +
 .../server/orm/entities/ClusterEntity.java      |   6 +
 .../ambari/server/orm/entities/UserEntity.java  |  12 +-
 .../server/upgrade/UpgradeCatalog210.java       |   3 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   1 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   1 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   1 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   1 +
 .../resources/UserResourceDefinitionTest.java   |   2 +-
 .../ActiveWidgetLayoutResourceProviderTest.java | 259 +++++++++++++++++++
 .../server/upgrade/UpgradeCatalog210Test.java   |   8 +
 18 files changed, 705 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ActiveWidgetLayoutResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ActiveWidgetLayoutResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ActiveWidgetLayoutResourceDefinition.java
new file mode 100644
index 0000000..d6b4c6b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ActiveWidgetLayoutResourceDefinition.java
@@ -0,0 +1,89 @@
+/**
+ * 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.ambari.server.api.resources;
+
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.util.TreeNode;
+import org.apache.ambari.server.controller.WidgetResponse;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Resource Definition for WidgetLayout types.
+ */
+public class ActiveWidgetLayoutResourceDefinition extends BaseResourceDefinition {
+
+  public ActiveWidgetLayoutResourceDefinition() {
+    super(Resource.Type.ActiveWidgetLayout);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "widget_layouts";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "widget_layout";
+  }
+
+  @Override
+  public List<PostProcessor> getPostProcessors() {
+    List<PostProcessor> listProcessors = super.getPostProcessors();
+    listProcessors.add(new WidgetLayoutHrefProcessor());
+
+    return listProcessors;
+  }
+
+  /**
+   * Base resource processor which generates href's.  This is called by the
+   * {@link org.apache.ambari.server.api.services.ResultPostProcessor} during post processing of a result.
+   */
+  private class WidgetLayoutHrefProcessor extends BaseHrefPostProcessor {
+    @Override
+    public void process(Request request, TreeNode<Resource> resultNode, String href) {
+      TreeNode<Resource> parent = resultNode.getParent();
+
+      for (TreeNode<Resource> node : parent.getChildren()) {
+        if (node.getObject().getPropertiesMap().get("WidgetLayouts") != null) {
+          String layoutId = resultNode.getObject().getPropertyValue("WidgetLayouts/id").toString();
+          String clusterName = resultNode.getObject().getPropertyValue("WidgetLayouts/cluster_name").toString();
+          String newHref = href.substring(0, href.indexOf("/users") + 1) +
+                  "clusters/" + clusterName + "/widget_layouts/" + layoutId;
+          resultNode.setProperty("href", newHref);
+        }
+        if (node.getObject().getPropertiesMap().get("WidgetLayouts") != null &&
+                node.getObject().getPropertiesMap().get("WidgetLayouts").get("WidgetInfo") != null) {
+
+          ArrayList widgetsList = (ArrayList) node.getObject().getPropertiesMap().get("WidgetLayouts").get("WidgetInfo");
+          for (Object widgetObject : widgetsList) {
+            HashMap<String, Object> widgetMap = (HashMap) widgetObject;
+            String widgetId = ((WidgetResponse) widgetMap.get("Widget")).getId().toString();
+            String clusterName = ((WidgetResponse) widgetMap.get("Widget")).getClusterName().toString();
+            String widgetHref = href.substring(0, href.indexOf("/users") + 1) +
+                    "clusters/" + clusterName + "/widgets/" + widgetId;
+            widgetMap.put("href", widgetHref);
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index e3af507..24232ba 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -376,6 +376,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new WidgetLayoutResourceDefinition();
         break;
 
+      case ActiveWidgetLayout:
+        resourceDefinition = new ActiveWidgetLayoutResourceDefinition();
+        break;
+
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java
index 95ce7b5..26c1bd9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java
@@ -45,6 +45,7 @@ public class UserResourceDefinition extends BaseResourceDefinition {
   public Set<SubResourceDefinition> getSubResourceDefinitions() {
     final Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
     subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.UserPrivilege));
+    subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.ActiveWidgetLayout));
     return subResourceDefinitions;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/api/services/ActiveWidgetLayoutService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ActiveWidgetLayoutService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ActiveWidgetLayoutService.java
new file mode 100644
index 0000000..c4403df
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ActiveWidgetLayoutService.java
@@ -0,0 +1,80 @@
+/**
+ * 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.ambari.server.api.services;
+
+import com.sun.jersey.core.util.Base64;
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * WidgetLayout Service
+ */
+public class ActiveWidgetLayoutService extends BaseService {
+
+  private final String userName;
+
+  public ActiveWidgetLayoutService(String userName) {
+    this.userName = userName;
+  }
+
+  /**
+   * Handles URL: /activeWidgetLayouts
+   * Get all instances for a view.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   *
+   * @return instance collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.GET,
+            createResource(null));
+  }
+
+  @PUT
+  @Produces("text/plain")
+  public Response updateServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResource(null));
+  }
+
+  private ResourceInstance createResource(String widgetLayoutId) {
+    Map<Resource.Type,String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.User, userName);
+    return createResource(Resource.Type.ActiveWidgetLayout, mapIds);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/api/services/UserService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UserService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UserService.java
index 00be99c..05ee6b1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UserService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UserService.java
@@ -139,6 +139,16 @@ public class UserService extends BaseService {
   }
 
   /**
+   * Gets the active widget layout service
+   */
+  @Path("{userName}/activeWidgetLayouts")
+  public ActiveWidgetLayoutService getWidgetLayoutService(@Context javax.ws.rs.core.Request request,
+                                                    @PathParam ("userName") String userName) {
+
+    return new ActiveWidgetLayoutService(userName);
+  }
+
+  /**
    * Create a user resource instance.
    *
    * @param userName  user name

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 0cff452..20f15c0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -159,6 +159,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
         return new StackArtifactResourceProvider(managementController);
       case Theme:
         return new ThemeArtifactResourceProvider(managementController);
+      case ActiveWidgetLayout:
+        return new ActiveWidgetLayoutResourceProvider(managementController);
       case WidgetLayout:
         return new WidgetLayoutResourceProvider(managementController);
       case Widget:

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
new file mode 100644
index 0000000..8d35b93
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProvider.java
@@ -0,0 +1,226 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.WidgetResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.WidgetDAO;
+import org.apache.ambari.server.orm.dao.WidgetLayoutDAO;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.orm.entities.WidgetEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resource provider for widget layout resources.
+ */
+@StaticallyInject
+public class ActiveWidgetLayoutResourceProvider extends AbstractControllerResourceProvider {
+
+  // ----- Property ID constants ---------------------------------------------
+
+  public static final String WIDGETLAYOUT_ID_PROPERTY_ID                 = PropertyHelper.getPropertyId("WidgetLayouts", "id");
+  public static final String WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID                 = PropertyHelper.getPropertyId("WidgetLayouts", "cluster_name");
+  public static final String WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID                 = PropertyHelper.getPropertyId("WidgetLayouts", "section_name");
+  public static final String WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID                 = PropertyHelper.getPropertyId("WidgetLayouts", "layout_name");
+  public static final String WIDGETLAYOUT_SCOPE_PROPERTY_ID                  = PropertyHelper.getPropertyId("WidgetLayouts", "scope");
+  public static final String WIDGETLAYOUT_INFO_PROPERTY_ID                   = PropertyHelper.getPropertyId("WidgetLayouts", "WidgetInfo");
+  public static final String WIDGETLAYOUT_USERNAME_PROPERTY_ID                   = PropertyHelper.getPropertyId("WidgetLayouts", "user_name");
+  public static final String WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID                   = PropertyHelper.getPropertyId("WidgetLayouts", "display_name");
+  public static final String WIDGETLAYOUT = "WidgetLayouts";
+  public static final String ID = "id";
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>();
+
+  @SuppressWarnings("serial")
+  public static Set<String> propertyIds = new HashSet<String>();
+
+  @SuppressWarnings("serial")
+  public static Map<Type, String> keyPropertyIds = new HashMap<Type, String>();
+
+  static {
+    pkPropertyIds.add(WIDGETLAYOUT_ID_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_ID_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_INFO_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_SCOPE_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_USERNAME_PROPERTY_ID);
+    propertyIds.add(WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID);
+    keyPropertyIds.put(Type.ActiveWidgetLayout, WIDGETLAYOUT_ID_PROPERTY_ID);
+    keyPropertyIds.put(Type.User, WIDGETLAYOUT_USERNAME_PROPERTY_ID);
+  }
+
+  @Inject
+  private static UserDAO userDAO;
+
+  @Inject
+  private static WidgetDAO widgetDAO;
+
+  @Inject
+  private static WidgetLayoutDAO widgetLayoutDAO;
+
+  @Inject
+  private static Gson gson;
+
+  /**
+   * Create a new resource provider.
+   *
+   */
+  public ActiveWidgetLayoutResourceProvider(AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+
+  @Override
+  public RequestStatus createResources(final Request request)
+      throws SystemException,
+      UnsupportedPropertyException,
+      ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+
+    throw new SystemException("The request is not supported");
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Resource> resources = new HashSet<Resource>();
+    final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    List<WidgetLayoutEntity> layoutEntities = new ArrayList<WidgetLayoutEntity>();
+
+    for (Map<String, Object> propertyMap: propertyMaps) {
+      final String userName = propertyMap.get(WIDGETLAYOUT_USERNAME_PROPERTY_ID).toString();
+        java.lang.reflect.Type type = new TypeToken<Set<Map<String, String>>>(){}.getType();
+        Set<Map<String, String>> activeWidgetLayouts = gson.fromJson(userDAO.findUserByName(userName).getActiveWidgetLayouts(), type);
+        if (activeWidgetLayouts != null) {
+          for (Map<String, String> widgetLayoutId : activeWidgetLayouts) {
+            layoutEntities.add(widgetLayoutDAO.findById(Long.parseLong(widgetLayoutId.get(ID))));
+          }
+        }
+    }
+
+    for (WidgetLayoutEntity layoutEntity : layoutEntities) {
+      Resource resource = new ResourceImpl(Type.ActiveWidgetLayout);
+      resource.setProperty(WIDGETLAYOUT_ID_PROPERTY_ID, layoutEntity.getId());
+      String clusterName = null;
+      try {
+        clusterName = getManagementController().getClusters().getClusterById(layoutEntity.getClusterId()).getClusterName();
+      } catch (AmbariException e) {
+        throw new SystemException(e.getMessage());
+      }
+      resource.setProperty(WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID, clusterName);
+      resource.setProperty(WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID, layoutEntity.getLayoutName());
+      resource.setProperty(WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID, layoutEntity.getSectionName());
+      resource.setProperty(WIDGETLAYOUT_SCOPE_PROPERTY_ID, layoutEntity.getScope());
+      resource.setProperty(WIDGETLAYOUT_USERNAME_PROPERTY_ID, layoutEntity.getUserName());
+      resource.setProperty(WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID, layoutEntity.getDisplayName());
+
+      List<HashMap> widgets = new ArrayList<HashMap>();
+      List<WidgetLayoutUserWidgetEntity> widgetLayoutUserWidgetEntityList = layoutEntity.getListWidgetLayoutUserWidgetEntity();
+      for (WidgetLayoutUserWidgetEntity widgetLayoutUserWidgetEntity : widgetLayoutUserWidgetEntityList) {
+        WidgetEntity widgetEntity = widgetLayoutUserWidgetEntity.getWidget();
+        HashMap<String, Object> widgetInfoMap = new HashMap<String, Object>();
+        widgetInfoMap.put("Widget",WidgetResponse.coerce(widgetEntity));
+        widgets.add(widgetInfoMap);
+      }
+      resource.setProperty(WIDGETLAYOUT_INFO_PROPERTY_ID, widgets);
+
+      resources.add(resource);
+    }
+    return resources;
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+    throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    final Set<Map<String, Object>> propertyMaps = request.getProperties();
+
+    modifyResources(new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        for (Map<String, Object> propertyMap : propertyMaps) {
+          Set<HashMap> widgetLayouts = (Set) propertyMap.get(WIDGETLAYOUT);
+          for (HashMap<String, String> widgetLayout : widgetLayouts) {
+            final Long layoutId;
+            try {
+              layoutId = Long.parseLong(widgetLayout.get(ID));
+            } catch (Exception ex) {
+              throw new AmbariException("WidgetLayout should have numerical id");
+            }
+            final WidgetLayoutEntity entity = widgetLayoutDAO.findById(layoutId);
+            if (entity == null) {
+              throw new AmbariException("There is no widget layout with id " + layoutId);
+            }
+          }
+          UserEntity user = userDAO.findUserByName(propertyMap.get(WIDGETLAYOUT_USERNAME_PROPERTY_ID).toString());
+          user.setActiveWidgetLayouts(gson.toJson(propertyMap.get(WIDGETLAYOUT)));
+          userDAO.merge(user);
+        }
+        return null;
+      }
+    });
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("The request is not supported");
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 035f96f..e2fad62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -141,6 +141,7 @@ public interface Resource {
     Artifact,
     Widget,
     WidgetLayout,
+    ActiveWidgetLayout,
     Theme;
 
     /**
@@ -244,6 +245,7 @@ public interface Resource {
     public static final Type Theme = InternalType.Theme.getType();
     public static final Type Widget = InternalType.Widget.getType();
     public static final Type WidgetLayout = InternalType.WidgetLayout.getType();
+    public static final Type ActiveWidgetLayout = InternalType.ActiveWidgetLayout.getType();
 
     /**
      * The type name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
index d03f542..3577dc4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
@@ -131,6 +131,12 @@ public class ClusterEntity {
   @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
   private Collection<ClusterVersionEntity> clusterVersionEntities;
 
+  @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
+  private Collection<WidgetEntity> widgetEntities;
+
+  @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
+  private Collection<WidgetLayoutEntity> widgetLayoutEntities;
+
   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumns({
       @JoinColumn(name = "resource_id", referencedColumnName = "resource_id", nullable = false)

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
index 85082a9..32dbbf5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
@@ -70,7 +70,8 @@ public class UserEntity {
   })
   private PrincipalEntity principal;
 
-
+  @Column(name = "active_widget_layouts")
+  private String activeWidgetLayouts;
   // ----- UserEntity --------------------------------------------------------
 
   public Integer getUserId() {
@@ -155,8 +156,15 @@ public class UserEntity {
     this.principal = principal;
   }
 
+  public String getActiveWidgetLayouts() {
+    return activeWidgetLayouts;
+  }
+
+  public void setActiveWidgetLayouts(String activeWidgetLayouts) {
+    this.activeWidgetLayouts = activeWidgetLayouts;
+  }
 
-  // ----- Object overrides --------------------------------------------------
+// ----- Object overrides --------------------------------------------------
 
   @Override
   public boolean equals(Object o) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
index 09a8740..884032e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
@@ -342,6 +342,9 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
     dbAccessor.createTable(WIDGET_LAYOUT_USER_WIDGET_TABLE, columns, "widget_layout_id", "widget_id");
     dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, "FK_widget_layout_id", "widget_layout_id", "widget_layout", "id", true, false);
     dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, "FK_widget_id", "widget_id", "widget", "id", true, false);
+
+    //Alter users to store active widget layouts
+    dbAccessor.addColumn("users", new DBColumnInfo("active_widget_layouts", String.class, 1024, null, true));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index fb2a831..c3488f2 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -185,6 +185,7 @@ CREATE TABLE users (
   user_name VARCHAR(255) NOT NULL,
   user_password VARCHAR(255),
   active INTEGER NOT NULL DEFAULT 1,
+  active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   PRIMARY KEY (user_id));
 
 CREATE TABLE groups (

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index ae70ed3..0455e9e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -174,6 +174,7 @@ CREATE TABLE users (
   user_name VARCHAR2(255) NULL,
   user_password VARCHAR2(255) NULL,
   active INTEGER DEFAULT 1 NOT NULL,
+  active_widget_layouts VARCHAR2(1024) DEFAULT NULL,
   PRIMARY KEY (user_id));
 
 CREATE TABLE groups (

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index f1f3055..2c381b2 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -183,6 +183,7 @@ CREATE TABLE users (
   create_time TIMESTAMP DEFAULT NOW(),
   user_password VARCHAR(255),
   active INTEGER NOT NULL DEFAULT 1,
+  active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   PRIMARY KEY (user_id),
   UNIQUE (ldap_user, user_name));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 6c7f813..24762eb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -210,6 +210,7 @@ CREATE TABLE ambari.users (
   create_time TIMESTAMP DEFAULT NOW(),
   user_password VARCHAR(255),
   active INTEGER NOT NULL DEFAULT 1,
+  active_widget_layouts VARCHAR(1024) DEFAULT NULL,
   PRIMARY KEY (user_id),
   UNIQUE (ldap_user, user_name));
 GRANT ALL PRIVILEGES ON TABLE ambari.users TO :username;

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java
index 43368f0..0924393 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java
@@ -43,6 +43,6 @@ public class UserResourceDefinitionTest {
   public void testGetSubResourceDefinitions() throws Exception {
     final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
     Set<SubResourceDefinition> subResourceDefinitions = userResourceDefinition.getSubResourceDefinitions();
-    Assert.assertEquals(1, subResourceDefinitions.size());
+    Assert.assertEquals(2, subResourceDefinitions.size());
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
new file mode 100644
index 0000000..a635784
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActiveWidgetLayoutResourceProviderTest.java
@@ -0,0 +1,259 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.WidgetLayoutDAO;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * ActiveWidgetLayout tests
+ */
+public class ActiveWidgetLayoutResourceProviderTest {
+
+  private WidgetLayoutDAO widgetLayoutDAO = null;
+  private UserDAO userDAO = null;
+  private Injector m_injector;
+
+  @Before
+  public void before() {
+    widgetLayoutDAO = createStrictMock(WidgetLayoutDAO.class);
+    userDAO = createStrictMock(UserDAO.class);
+
+    m_injector = Guice.createInjector(Modules.override(
+        new InMemoryDefaultTestModule()).with(new MockModule()));
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testGetSingleResource() throws Exception {
+    Request request = PropertyHelper.getReadRequest(
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_ID_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_SCOPE_PROPERTY_ID,
+        ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_INFO_PROPERTY_ID);
+
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    UserEntity userEntity = createMock(UserEntity.class);
+    expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    expect(clusters.getClusterById(1L)).andReturn(cluster).atLeastOnce();
+    expect(cluster.getClusterName()).andReturn("c1").anyTimes();
+
+    Predicate predicate = new PredicateBuilder().property(
+            ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID).equals("username").toPredicate();
+
+
+    expect(userDAO.findUserByName("username")).andReturn(userEntity);
+    expect(userEntity.getActiveWidgetLayouts()).andReturn("[{\"id\":\"1\"},{\"id\":\"2\"}]");
+    expect(widgetLayoutDAO.findById(1L)).andReturn(getMockEntities().get(0));
+    expect(widgetLayoutDAO.findById(2L)).andReturn(getMockEntities().get(1));
+
+    replay(amc, clusters, cluster, widgetLayoutDAO, userEntity, userDAO);
+
+    ActiveWidgetLayoutResourceProvider provider = createProvider(amc);
+    Set<Resource> results = provider.getResources(request, predicate);
+
+    assertEquals(2, results.size());
+
+    Resource r = results.iterator().next();
+    Assert.assertEquals("section0", r.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID));
+    Assert.assertEquals("CLUSTER", r.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_SCOPE_PROPERTY_ID));
+    Assert.assertEquals("username", r.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID));
+    Assert.assertEquals("displ_name", r.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID));
+    Assert.assertEquals("layout name0", r.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID));
+
+    Assert.assertEquals("[]", r.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_INFO_PROPERTY_ID).toString());
+
+    verify(amc, clusters, cluster, widgetLayoutDAO, userEntity, userDAO);
+  }
+
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testCreateResources() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+
+    replay(amc);
+
+    ActiveWidgetLayoutResourceProvider provider = createProvider(amc);
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+
+    Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+    try {
+      provider.createResources(request);
+    } catch (Exception e) {
+      //Expected exception
+    }
+
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testUpdateResources() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+
+    expect(widgetLayoutDAO.findById(anyLong())).andReturn(getMockEntities().get(0)).anyTimes();
+    UserEntity userEntity = new UserEntity();
+    expect(userDAO.findUserByName("username")).andReturn(userEntity);
+    expect(userDAO.merge((UserEntity) anyObject())).andReturn(userEntity).anyTimes();
+
+    replay(amc, widgetLayoutDAO, userDAO);
+
+    Predicate predicate = new PredicateBuilder().property(
+            ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID).equals("username").toPredicate();
+    Set<Map<String, String>> widgetLayouts = new HashSet<Map<String, String>>();
+    HashMap<String, String> layout = new HashMap<String, String>();
+    layout.put("id","1");
+    widgetLayouts.add(layout);
+    layout.put("id","2");
+    widgetLayouts.add(layout);
+    HashMap<String, Object> requestProps = new HashMap<String, Object>();
+    requestProps.put(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT, widgetLayouts);
+    requestProps.put(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID, "username");
+
+    Request request = PropertyHelper.getUpdateRequest(requestProps, null);
+
+    ActiveWidgetLayoutResourceProvider provider = createProvider(amc);
+    provider.updateResources(request, predicate);
+
+    Assert.assertTrue(userEntity.getActiveWidgetLayouts().equals("[{\"id\":\"2\"},{\"id\":\"2\"}]"));
+    verify(amc, widgetLayoutDAO, userDAO);
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testDeleteResources() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+
+    replay(amc);
+
+    ActiveWidgetLayoutResourceProvider provider = createProvider(amc);
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+    Predicate predicate = new PredicateBuilder().property(
+            WidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID).equals("username").toPredicate();
+    try {
+      provider.deleteResources(predicate);
+    } catch (Exception e) {
+      //Expected exception
+    }
+  }
+
+  /**
+   * @param amc
+   * @return
+   */
+  private ActiveWidgetLayoutResourceProvider createProvider(AmbariManagementController amc) {
+    return new ActiveWidgetLayoutResourceProvider(amc);
+  }
+
+  /**
+   * @return
+   */
+  private List<WidgetLayoutEntity> getMockEntities() throws Exception {
+    List<WidgetLayoutEntity> widgetLayoutEntities = new ArrayList<WidgetLayoutEntity>();
+    for (int i=1; i<3; i++) {
+      WidgetLayoutEntity widgetLayoutEntity = new WidgetLayoutEntity();
+      widgetLayoutEntity.setId((long) i);
+      widgetLayoutEntity.setClusterId(Long.valueOf(1L));
+      widgetLayoutEntity.setLayoutName("layout name0");
+      widgetLayoutEntity.setSectionName("section0");
+      widgetLayoutEntity.setUserName("username");
+      widgetLayoutEntity.setScope("CLUSTER");
+      widgetLayoutEntity.setDisplayName("displ_name");
+      List<WidgetLayoutUserWidgetEntity> layoutUserWidgetEntityList = new LinkedList<WidgetLayoutUserWidgetEntity>();
+      widgetLayoutEntity.setListWidgetLayoutUserWidgetEntity(layoutUserWidgetEntityList);
+
+      widgetLayoutEntities.add(widgetLayoutEntity);
+    }
+    return widgetLayoutEntities;
+  }
+
+  /**
+  *
+  */
+  private class MockModule implements Module {
+    /**
+    *
+    */
+    @Override
+    public void configure(Binder binder) {
+      binder.bind(WidgetLayoutDAO.class).toInstance(widgetLayoutDAO);
+      binder.bind(UserDAO.class).toInstance(userDAO);
+      binder.bind(Clusters.class).toInstance(
+          EasyMock.createNiceMock(Clusters.class));
+      binder.bind(Cluster.class).toInstance(
+          EasyMock.createNiceMock(Cluster.class));
+      binder.bind(ActionMetadata.class);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/958fd13e/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
index 6ca7dfd..32d6d1e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
@@ -300,6 +300,7 @@ public class UpgradeCatalog210Test {
   class WidgetSectionDDL implements SectionDDL {
 
     HashMap<String, Capture<List<DBColumnInfo>>> captures;
+    Capture<DBColumnInfo> userActiveLayoutsColumnCapture;
 
     public WidgetSectionDDL() {
       captures = new HashMap<String, Capture<List<DBColumnInfo>>>();
@@ -311,6 +312,7 @@ public class UpgradeCatalog210Test {
       captures.put("widget", userWidgetColumnsCapture);
       captures.put("widget_layout", widgetLayoutColumnsCapture);
       captures.put("widget_layout_user_widget", widgetLayoutUserWidgetColumnsCapture);
+      userActiveLayoutsColumnCapture = new Capture<DBColumnInfo>();
     }
 
     /**
@@ -333,6 +335,8 @@ public class UpgradeCatalog210Test {
       // Widget Layout User Widget
       dbAccessor.createTable(eq("widget_layout_user_widget"),
           capture(widgetLayoutUserWidgetColumnsCapture), eq("widget_layout_id"), eq("widget_id"));
+
+      dbAccessor.addColumn(eq("users"), capture(userActiveLayoutsColumnCapture));
     }
 
     /**
@@ -348,6 +352,10 @@ public class UpgradeCatalog210Test {
       assertEquals(12, widgetColumnsCapture.getValue().size());
       assertEquals(7, widgetLayoutColumnsCapture.getValue().size());
       assertEquals(3, widgetLayoutUserWidgetColumnsCapture.getValue().size());
+
+      DBColumnInfo idColumn = userActiveLayoutsColumnCapture.getValue();
+      Assert.assertEquals(String.class, idColumn.getType());
+      Assert.assertEquals("active_widget_layouts", idColumn.getName());
     }
   }