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/06 20:25:46 UTC

[2/2] ambari git commit: AMBARI-10372. Create an API endpoint for widget_layouts.

AMBARI-10372. Create an API endpoint for widget_layouts.


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

Branch: refs/heads/trunk
Commit: 4b3caee767a2dc2dbd0061021ebafff9156bcbd3
Parents: 75c9df8
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Mon Apr 6 11:25:21 2015 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Mon Apr 6 11:25:21 2015 -0700

----------------------------------------------------------------------
 .../resources/ResourceInstanceFactoryImpl.java  |   8 +
 .../WidgetLayoutResourceDefinition.java         |  86 +++++
 .../api/resources/WidgetResourceDefinition.java |  46 +++
 .../server/api/services/ClusterService.java     |  10 +
 .../api/services/WidgetLayoutService.java       | 114 ++++++
 .../services/parsers/JsonRequestBodyParser.java |   3 +-
 .../server/controller/WidgetResponse.java       | 181 ++++++++++
 .../AbstractControllerResourceProvider.java     |   2 +
 .../internal/WidgetLayoutResourceProvider.java  | 343 ++++++++++++++++++
 .../ambari/server/controller/spi/Resource.java  |   4 +
 .../ambari/server/orm/dao/UserWidgetDAO.java    |  99 -----
 .../apache/ambari/server/orm/dao/WidgetDAO.java |  97 +++++
 .../ambari/server/orm/dao/WidgetLayoutDAO.java  |   2 -
 .../server/orm/entities/UserWidgetEntity.java   | 222 ------------
 .../server/orm/entities/WidgetEntity.java       | 231 ++++++++++++
 .../server/orm/entities/WidgetLayoutEntity.java |  48 ++-
 .../entities/WidgetLayoutUserWidgetEntity.java  |  19 +-
 .../server/upgrade/UpgradeCatalog210.java       |   5 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   6 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   6 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   8 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   8 +-
 .../src/main/resources/META-INF/persistence.xml |   2 +-
 .../src/main/resources/properties.json          |  27 ++
 .../parsers/JsonRequestBodyParserTest.java      |   2 +
 .../WidgetLayoutResourceProviderTest.java       | 362 +++++++++++++++++++
 .../server/orm/dao/UserWidgetDAOTest.java       | 116 ------
 .../ambari/server/orm/dao/WidgetDAOTest.java    | 121 +++++++
 .../server/orm/dao/WidgetLayoutDAOTest.java     |  36 +-
 .../server/upgrade/UpgradeCatalog210Test.java   |  10 +-
 30 files changed, 1748 insertions(+), 476 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 7183fa7..07e70ab 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
@@ -362,6 +362,14 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new SimpleResourceDefinition(Resource.Type.Theme, "theme", "themes");
         break;
 
+      case Widget:
+        resourceDefinition = new WidgetResourceDefinition();
+        break;
+
+      case WidgetLayout:
+        resourceDefinition = new WidgetLayoutResourceDefinition();
+        break;
+
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetLayoutResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetLayoutResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetLayoutResourceDefinition.java
new file mode 100644
index 0000000..2d2ca1e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetLayoutResourceDefinition.java
@@ -0,0 +1,86 @@
+/**
+ * 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 org.apache.ambari.server.controller.spi.Schema;
+import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Resource Definition for WidgetLayout types.
+ */
+public class WidgetLayoutResourceDefinition extends BaseResourceDefinition {
+
+  public WidgetLayoutResourceDefinition() {
+    super(Resource.Type.WidgetLayout);
+  }
+
+  @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 &&
+                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 widgetHref = href.substring(0, href.indexOf("/widget_layouts") + 1) +
+                    "widgets/" + widgetId;
+            widgetMap.put("href", widgetHref);
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetResourceDefinition.java
new file mode 100644
index 0000000..ee0eaf0
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/WidgetResourceDefinition.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.ambari.server.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Resource Definition for Widget types.
+ */
+public class WidgetResourceDefinition extends BaseResourceDefinition {
+
+  public WidgetResourceDefinition() {
+    super(Resource.Type.Widget);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "widgets";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "widget";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
index a794693..87a4f7f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
@@ -634,6 +634,16 @@ public class ClusterService extends BaseService {
     return new PreUpgradeCheckService(clusterName);
   }
 
+  /**
+   * Gets the widget layout service
+   */
+  @Path("{clusterName}/widget_layouts")
+  public WidgetLayoutService getWidgetLayoutService(@Context javax.ws.rs.core.Request request,
+                                                    @PathParam ("clusterName") String clusterName) {
+
+    return new WidgetLayoutService(clusterName);
+  }
+
   // ----- helper methods ----------------------------------------------------
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetLayoutService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetLayoutService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetLayoutService.java
new file mode 100644
index 0000000..b4985ca
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetLayoutService.java
@@ -0,0 +1,114 @@
+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.*;
+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 WidgetLayoutService extends BaseService {
+  
+  private final String clusterName;
+
+  public  WidgetLayoutService(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  @GET
+  @Path("{widgetLayoutId}")
+  @Produces("text/plain")
+  public Response getService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                             @PathParam("widgetLayoutId") String widgetLayoutId) {
+
+    return handleRequest(headers, body, ui, Request.Type.GET,
+            createResource(getUserName(headers), widgetLayoutId));
+  }
+
+  /**
+   * Handles URL: /widget_layouts
+   * 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(getUserName(headers), null));
+  }
+
+  @POST
+  @Path("{widgetLayoutId}")
+  @Produces("text/plain")
+  public Response createService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("widgetLayoutId") String widgetLayoutId) {
+    return handleRequest(headers, body, ui, Request.Type.POST,
+            createResource(getUserName(headers), widgetLayoutId));
+  }
+
+  @POST
+  @Produces("text/plain")
+  public Response createServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST,
+            createResource(getUserName(headers), null));
+  }
+
+  @PUT
+  @Path("{widgetLayoutId}")
+  @Produces("text/plain")
+  public Response updateService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("widgetLayoutId") String widgetLayoutId) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResource(getUserName(headers), widgetLayoutId));
+  }
+
+  @PUT
+  @Produces("text/plain")
+  public Response updateServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResource(getUserName(headers), null));
+  }
+
+  @DELETE
+  @Path("{widgetLayoutId}")
+  @Produces("text/plain")
+  public Response deleteService(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("widgetLayoutId") String widgetLayoutId) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createResource(getUserName(headers), widgetLayoutId));
+  }
+
+  private ResourceInstance createResource(String userName, String widgetLayoutId) {
+    Map<Resource.Type,String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.User, userName);
+    mapIds.put(Resource.Type.WidgetLayout, widgetLayoutId);
+    mapIds.put(Resource.Type.Cluster, clusterName);
+    return createResource(Resource.Type.WidgetLayout, mapIds);
+  }
+
+  private String getUserName(HttpHeaders headers) {
+    String authorizationString = headers.getRequestHeaders().get("Authorization").get(0);
+    if (authorizationString != null && authorizationString.startsWith("Basic")) {
+      String base64Credentials = authorizationString.substring("Basic".length()).trim();
+      String clearCredentials = new String(Base64.decode(base64Credentials),Charset.forName("UTF-8"));
+      return clearCredentials.split(":", 2)[0];
+    } else {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
index 5e6df6b..75ac0f3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -118,7 +119,7 @@ public class JsonRequestBodyParser implements RequestBodyParser {
       if (child.isArray()) {
         //array
         Iterator<JsonNode>       arrayIter = child.getElements();
-        Set<Map<String, Object>> arraySet  = new HashSet<Map<String, Object>>();
+        Set<Map<String, Object>> arraySet  = new LinkedHashSet<Map<String, Object>>();
         List<String> primitives = new ArrayList<String>();
 
         while (arrayIter.hasNext()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/controller/WidgetResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/WidgetResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/WidgetResponse.java
new file mode 100644
index 0000000..9d8c95d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/WidgetResponse.java
@@ -0,0 +1,181 @@
+/**
+® * 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;
+
+import org.apache.ambari.server.orm.entities.WidgetEntity;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+
+/**
+ * The {@link org.apache.ambari.server.controller.WidgetResponse} encapsulates the definition information
+ * that should be serialized and returned in REST requests for alerts, groups,
+ * and targets.
+ */
+public class WidgetResponse {
+
+  private Long id;
+  private String widgetName;
+  private String widgetType;
+  private String metrics;
+  private Long timeCreated;
+  private String author;
+  private String description;
+  private String displayName;
+  private String scope;
+  private String widgetValues;
+  private String properties;
+  private String clusterName;
+
+  @JsonProperty("id")
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  @JsonProperty("widget_name")
+  public String getWidgetName() {
+    return widgetName;
+  }
+
+  public void setWidgetName(String widgetName) {
+    this.widgetName = widgetName;
+  }
+
+  @JsonProperty("widget_type")
+  public String getWidgetType() {
+    return widgetType;
+  }
+
+  public void setWidgetType(String widgetType) {
+    this.widgetType = widgetType;
+  }
+
+  public String getMetrics() {
+    return metrics;
+  }
+
+  public void setMetrics(String metrics) {
+    this.metrics = metrics;
+  }
+
+  @JsonProperty("time_created")
+  public Long getTimeCreated() {
+    return timeCreated;
+  }
+
+  public void setTimeCreated(Long timeCreated) {
+    this.timeCreated = timeCreated;
+  }
+
+  public String getAuthor() {
+    return author;
+  }
+
+  public void setAuthor(String author) {
+    this.author = author;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  @JsonProperty("display_name")
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  public String getScope() {
+    return scope;
+  }
+
+  public void setScope(String scope) {
+    this.scope = scope;
+  }
+
+  @JsonProperty("values")
+  public String getWidgetValues() {
+    return widgetValues;
+  }
+
+  public void setWidgetValues(String widgetValues) {
+    this.widgetValues = widgetValues;
+  }
+
+  public String getProperties() {
+    return properties;
+  }
+
+  public void setProperties(String properties) {
+    this.properties = properties;
+  }
+
+  @JsonProperty("cluster_name")
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  @Override
+  public String toString() {
+    return widgetName;
+  }
+
+  /**
+   * Gets an {@link org.apache.ambari.server.controller.WidgetResponse} from the supplied entity.
+   *
+   * @param entity
+   *          the entity (not {@code null}).
+   * @return the response.
+   */
+  public static WidgetResponse coerce(WidgetEntity entity) {
+    if (null == entity) {
+      return null;
+    }
+
+    WidgetResponse response = new WidgetResponse();
+    response.setId(entity.getId());
+    response.setWidgetName(entity.getWidgetName());
+    response.setWidgetType(entity.getWidgetType());
+    response.setDescription(entity.getDescription());
+    response.setMetrics(entity.getMetrics());
+    response.setTimeCreated(entity.getTimeCreated());
+    response.setAuthor(entity.getAuthor());
+    response.setDisplayName(entity.getDisplayName());
+    response.setScope(entity.getScope());
+    response.setWidgetValues(entity.getWidgetValues());
+    response.setProperties(entity.getProperties());
+    String clusterName = (entity.getClusterEntity() != null) ? entity.getClusterEntity().getClusterName() : null;
+    response.setClusterName(clusterName);
+
+    return response;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 113087c..2c3f0b0 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
@@ -157,6 +157,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
         return new StackArtifactResourceProvider(managementController);
       case Theme:
         return new ThemeArtifactResourceProvider(managementController);
+      case WidgetLayout:
+        return new WidgetLayoutResourceProvider(managementController);
 
       default:
         throw new IllegalArgumentException("Unknown type " + type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetLayoutResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetLayoutResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetLayoutResourceProvider.java
new file mode 100644
index 0000000..eedde92
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetLayoutResourceProvider.java
@@ -0,0 +1,343 @@
+/**
+ * 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.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.WidgetDAO;
+import org.apache.ambari.server.orm.dao.WidgetLayoutDAO;
+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 WidgetLayoutResourceProvider 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");
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(WIDGETLAYOUT_ID_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  public static Set<String> propertyIds = new HashSet<String>() {
+    {
+      add(WIDGETLAYOUT_ID_PROPERTY_ID);
+      add(WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID);
+      add(WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID);
+      add(WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID);
+      add(WIDGETLAYOUT_INFO_PROPERTY_ID);
+      add(WIDGETLAYOUT_SCOPE_PROPERTY_ID);
+      add(WIDGETLAYOUT_USERNAME_PROPERTY_ID);
+      add(WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  public static Map<Type, String> keyPropertyIds = new HashMap<Type, String>() {
+    {
+      put(Type.WidgetLayout, WIDGETLAYOUT_ID_PROPERTY_ID);
+      put(Type.Cluster, WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID);
+      put(Type.User, WIDGETLAYOUT_USERNAME_PROPERTY_ID);
+    }
+  };
+
+  @Inject
+  private static WidgetDAO widgetDAO;
+
+  @Inject
+  private static WidgetLayoutDAO widgetLayoutDAO;
+
+  /**
+   * Create a new resource provider.
+   *
+   */
+  public WidgetLayoutResourceProvider(
+                                      AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+
+  @Override
+  public RequestStatus createResources(final Request request)
+      throws SystemException,
+      UnsupportedPropertyException,
+      ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+
+    for (final Map<String, Object> properties : request.getProperties()) {
+      Void resources = createResources(new Command<Void>() {
+
+        @Override
+        public Void invoke() throws AmbariException {
+          final String[] requiredProperties = {
+              WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID,
+              WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID,
+              WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID,
+              WIDGETLAYOUT_SCOPE_PROPERTY_ID,
+              WIDGETLAYOUT_INFO_PROPERTY_ID,
+              WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID,
+              WIDGETLAYOUT_USERNAME_PROPERTY_ID
+          };
+          for (String propertyName : requiredProperties) {
+            if (properties.get(propertyName) == null) {
+              throw new AmbariException("Property " + propertyName + " should be provided");
+            }
+          }
+          final WidgetLayoutEntity entity = new WidgetLayoutEntity();
+
+          Set widgetsSet = (LinkedHashSet) properties.get(WIDGETLAYOUT_INFO_PROPERTY_ID);
+
+          String clusterName = properties.get(WIDGETLAYOUT_CLUSTER_NAME_PROPERTY_ID).toString();
+          entity.setLayoutName(properties.get(WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID).toString());
+
+          entity.setClusterId(getManagementController().getClusters().getCluster(clusterName).getClusterId());
+          entity.setSectionName(properties.get(WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID).toString());
+          entity.setScope(properties.get(WIDGETLAYOUT_SCOPE_PROPERTY_ID).toString());
+          entity.setUserName(properties.get(WIDGETLAYOUT_USERNAME_PROPERTY_ID).toString());
+          entity.setDisplayName(properties.get(WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID).toString());
+
+          List<WidgetLayoutUserWidgetEntity> widgetLayoutUserWidgetEntityList = new LinkedList<WidgetLayoutUserWidgetEntity>();
+          int order=0;
+          for (Object widgetObject : widgetsSet) {
+            HashMap<String, Object> widget = (HashMap) widgetObject;
+            long id = Integer.parseInt(widget.get("id").toString());
+            WidgetEntity widgetEntity = widgetDAO.findById(id);
+            if (widgetEntity == null) {
+              throw new AmbariException("Widget with id " + widget.get("id").toString() + " does not exists");
+            }
+            WidgetLayoutUserWidgetEntity widgetLayoutUserWidgetEntity = new WidgetLayoutUserWidgetEntity();
+
+            widgetLayoutUserWidgetEntity.setWidget(widgetEntity);
+            widgetLayoutUserWidgetEntity.setWidgetOrder(order++);
+            widgetLayoutUserWidgetEntity.setWidgetLayout(entity);
+            widgetLayoutUserWidgetEntityList.add(widgetLayoutUserWidgetEntity);
+
+          }
+
+          entity.setListWidgetLayoutUserWidgetEntity(widgetLayoutUserWidgetEntityList);
+          widgetLayoutDAO.create(entity);
+          notifyCreate(Type.WidgetLayout, request);
+
+          return null;
+        }
+      });
+    }
+
+    return getRequestStatus(null);
+  }
+
+  @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<WidgetEntity> widgetEntities = new ArrayList<WidgetEntity>();
+    List<WidgetLayoutEntity> layoutEntities = new ArrayList<WidgetLayoutEntity>();
+
+    for (Map<String, Object> propertyMap: propertyMaps) {
+      final String userName = propertyMap.get(WIDGETLAYOUT_USERNAME_PROPERTY_ID).toString();
+      if (propertyMap.get(WIDGETLAYOUT_ID_PROPERTY_ID) != null) {
+        final Long id;
+        try {
+          id = Long.parseLong(propertyMap.get(WIDGETLAYOUT_ID_PROPERTY_ID).toString());
+        } catch (Exception ex) {
+          throw new SystemException("WidgetLayout should have numerical id");
+        }
+        final WidgetLayoutEntity entity = widgetLayoutDAO.findById(id);
+        if (entity == null) {
+          throw new NoSuchResourceException("WidgetLayout with id " + id + " does not exists");
+        }
+        layoutEntities.add(entity);
+      } else {
+        layoutEntities.addAll(widgetLayoutDAO.findAll());
+      }
+    }
+
+    for (WidgetLayoutEntity layoutEntity : layoutEntities) {
+      Resource resource = new ResourceImpl(Type.WidgetLayout);
+      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) {
+          final Long layoutId;
+          try {
+            layoutId = Long.parseLong(propertyMap.get(WIDGETLAYOUT_ID_PROPERTY_ID).toString());
+          } catch (Exception ex) {
+            throw new AmbariException("WidgetLayout should have numerical id");
+          }
+          final WidgetLayoutEntity entity = widgetLayoutDAO.findById(layoutId);
+          if (entity == null) {
+            throw new ObjectNotFoundException("There is no widget layout with id " + layoutId);
+          }
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID)))) {
+            entity.setLayoutName(propertyMap.get(WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID).toString());
+          }
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID)))) {
+            entity.setSectionName(propertyMap.get(WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID).toString());
+          }
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID)))) {
+            entity.setDisplayName(propertyMap.get(WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID).toString());
+          }
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGETLAYOUT_SCOPE_PROPERTY_ID)))) {
+            entity.setScope(propertyMap.get(WIDGETLAYOUT_SCOPE_PROPERTY_ID).toString());
+          }
+
+          Set widgetsSet = (LinkedHashSet) propertyMap.get(WIDGETLAYOUT_INFO_PROPERTY_ID);
+
+          List<WidgetLayoutUserWidgetEntity> widgetLayoutUserWidgetEntityList = new LinkedList<WidgetLayoutUserWidgetEntity>();
+          int order=0;
+          for (Object widgetObject : widgetsSet) {
+            HashMap<String, Object> widget = (HashMap) widgetObject;
+            long id = Integer.parseInt(widget.get("id").toString());
+            WidgetEntity widgetEntity = widgetDAO.findById(id);
+            if (widgetEntity == null) {
+              throw new AmbariException("Widget with id " + widget.get("id").toString() + " does not exists");
+            }
+            WidgetLayoutUserWidgetEntity widgetLayoutUserWidgetEntity = new WidgetLayoutUserWidgetEntity();
+
+            widgetLayoutUserWidgetEntity.setWidget(widgetEntity);
+            widgetLayoutUserWidgetEntity.setWidgetOrder(order++);
+            widgetLayoutUserWidgetEntity.setWidgetLayout(entity);
+            widgetLayoutUserWidgetEntityList.add(widgetLayoutUserWidgetEntity);
+
+          }
+
+          entity.setListWidgetLayoutUserWidgetEntity(widgetLayoutUserWidgetEntityList);
+
+          widgetLayoutDAO.merge(entity);
+        }
+        return null;
+      }
+    });
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    final List<WidgetLayoutEntity> entitiesToBeRemoved = new ArrayList<WidgetLayoutEntity>();
+    for (Map<String, Object> propertyMap : propertyMaps) {
+      final Long id;
+      try {
+        id = Long.parseLong(propertyMap.get(WIDGETLAYOUT_ID_PROPERTY_ID).toString());
+      } catch (Exception ex) {
+        throw new SystemException("WidgetLayout should have numerical id");
+      }
+
+      final WidgetLayoutEntity entity = widgetLayoutDAO.findById(id);
+      if (entity == null) {
+        throw new NoSuchResourceException("There is no widget layout with id " + id);
+      }
+
+      entitiesToBeRemoved.add(entity);
+    }
+
+    for (WidgetLayoutEntity entity: entitiesToBeRemoved) {
+      widgetLayoutDAO.remove(entity);
+    }
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 6e5db3a..e928e8e 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
@@ -138,6 +138,8 @@ public interface Resource {
     Stage,
     StackArtifact,
     Artifact,
+    Widget,
+    WidgetLayout,
     Theme;
 
     /**
@@ -238,6 +240,8 @@ public interface Resource {
     public static final Type StackArtifact = InternalType.StackArtifact.getType();
     public static final Type Artifact = InternalType.Artifact.getType();
     public static final Type Theme = InternalType.Theme.getType();
+    public static final Type Widget = InternalType.Widget.getType();
+    public static final Type WidgetLayout = InternalType.WidgetLayout.getType();
 
     /**
      * The type name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
deleted file mode 100644
index 834da26..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * 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.orm.dao;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.persist.Transactional;
-import org.apache.ambari.server.orm.RequiresSession;
-import org.apache.ambari.server.orm.entities.UserWidgetEntity;
-import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
-
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.TypedQuery;
-import java.util.List;
-
-@Singleton
-public class UserWidgetDAO {
-  @Inject
-  Provider<EntityManager> entityManagerProvider;
-
-  /**
-   * DAO utilities for dealing mostly with {@link TypedQuery} results.
-   */
-  @Inject
-  private DaoUtils daoUtils;
-
-  @RequiresSession
-  public UserWidgetEntity findById(Long id) {
-    return entityManagerProvider.get().find(UserWidgetEntity.class, id);
-  }
-
-  @RequiresSession
-  public List<UserWidgetEntity> findByCluster(long clusterId) {
-    TypedQuery<UserWidgetEntity> query = entityManagerProvider.get()
-            .createNamedQuery("UserWidgetEntity.findByCluster", UserWidgetEntity.class);
-    query.setParameter("clusterId", clusterId);
-
-    return daoUtils.selectList(query);
-  }
-
-  @RequiresSession
-  public List<UserWidgetEntity> findBySectionName(String sectionName) {
-    TypedQuery<UserWidgetEntity> query = entityManagerProvider.get()
-            .createNamedQuery("UserWidgetEntity.findBySectionName", UserWidgetEntity.class);
-    query.setParameter("sectionName", sectionName);
-
-    return daoUtils.selectList(query);
-  }
-
-  @RequiresSession
-  public List<UserWidgetEntity> findAll() {
-    TypedQuery<UserWidgetEntity> query = entityManagerProvider.get()
-            .createNamedQuery("UserWidgetEntity.findAll", UserWidgetEntity.class);
-
-    return daoUtils.selectList(query);
-  }
-
-  @Transactional
-  public void create(UserWidgetEntity userWidgetEntity) {
-    entityManagerProvider.get().persist(userWidgetEntity);
-  }
-
-  @Transactional
-  public UserWidgetEntity merge(UserWidgetEntity userWidgetEntity) {
-    return entityManagerProvider.get().merge(userWidgetEntity);
-  }
-
-  @Transactional
-  public void remove(UserWidgetEntity userWidgetEntity) {
-    entityManagerProvider.get().remove(merge(userWidgetEntity));
-  }
-
-  @Transactional
-  public void removeByPK(Long id) {
-    entityManagerProvider.get().remove(findById(id));
-  }
-
-  @Transactional
-  public void refresh(UserWidgetEntity userWidgetEntity) {
-    entityManagerProvider.get().refresh(userWidgetEntity);
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetDAO.java
new file mode 100644
index 0000000..c85e255
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetDAO.java
@@ -0,0 +1,97 @@
+/**
+ * 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.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.WidgetEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+@Singleton
+public class WidgetDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * DAO utilities for dealing mostly with {@link TypedQuery} results.
+   */
+  @Inject
+  private DaoUtils daoUtils;
+
+  @RequiresSession
+  public WidgetEntity findById(Long id) {
+    return entityManagerProvider.get().find(WidgetEntity.class, id);
+  }
+
+  @RequiresSession
+  public List<WidgetEntity> findByCluster(long clusterId) {
+    TypedQuery<WidgetEntity> query = entityManagerProvider.get()
+            .createNamedQuery("WidgetEntity.findByCluster", WidgetEntity.class);
+    query.setParameter("clusterId", clusterId);
+
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<WidgetEntity> findBySectionName(String sectionName) {
+    TypedQuery<WidgetEntity> query = entityManagerProvider.get()
+            .createNamedQuery("WidgetEntity.findBySectionName", WidgetEntity.class);
+    query.setParameter("sectionName", sectionName);
+
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<WidgetEntity> findAll() {
+    TypedQuery<WidgetEntity> query = entityManagerProvider.get()
+            .createNamedQuery("WidgetEntity.findAll", WidgetEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  @Transactional
+  public void create(WidgetEntity widgetEntity) {
+    entityManagerProvider.get().persist(widgetEntity);
+  }
+
+  @Transactional
+  public WidgetEntity merge(WidgetEntity widgetEntity) {
+    return entityManagerProvider.get().merge(widgetEntity);
+  }
+
+  @Transactional
+  public void remove(WidgetEntity widgetEntity) {
+    entityManagerProvider.get().remove(merge(widgetEntity));
+  }
+
+  @Transactional
+  public void removeByPK(Long id) {
+    entityManagerProvider.get().remove(findById(id));
+  }
+
+  @Transactional
+  public void refresh(WidgetEntity widgetEntity) {
+    entityManagerProvider.get().refresh(widgetEntity);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
index 55e7513..1d05acc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
@@ -22,11 +22,9 @@ import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.orm.RequiresSession;
-import org.apache.ambari.server.orm.entities.UserWidgetEntity;
 import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
 
 import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 import java.util.List;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
deleted file mode 100644
index ec84181..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- * 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.orm.entities;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import java.util.List;
-
-@Entity
-@Table(name = "user_widget")
-@NamedQueries({
-    @NamedQuery(name = "UserWidgetEntity.findAll", query = "SELECT userWidget FROM UserWidgetEntity userWidget"),
-    @NamedQuery(name = "UserWidgetEntity.findByCluster", query = "SELECT userWidget FROM UserWidgetEntity userWidget WHERE userWidget.clusterId = :clusterId"),
-    @NamedQuery(name = "UserWidgetEntity.findBySectionName", query =
-                "SELECT userWidget FROM UserWidgetEntity userWidget " +
-                "INNER JOIN userWidget.listWidgetLayoutUserWidgetEntity widgetLayoutUserWidget " +
-                "INNER JOIN widgetLayoutUserWidget.widgetLayout  widgetLayout " +
-                "WHERE widgetLayout.sectionName = :sectionName")
-        })
-public class UserWidgetEntity {
-
-  @Id
-  @GeneratedValue(strategy = GenerationType.IDENTITY)
-  @Column(name = "id", nullable = false, updatable = false)
-  private Long id;
-
-  @Column(name = "user_widget_name", nullable = false, length = 255)
-  private String userWidgetName;
-
-  @Column(name = "user_widget_type", nullable = false, length = 255)
-  private String userWidgetType;
-
-  @Column(name = "metrics", length = 32672)
-  private String metrics;
-
-  @Column(name = "time_created", nullable = false, length = 255)
-  private Long timeCreated = System.currentTimeMillis();
-
-  @Column(name = "author", length = 255)
-  private String author;
-
-  @Column(name = "description", length = 255)
-  private String description;
-
-  @Column(name = "display_name", nullable = false,  length = 255)
-  private String displayName;
-
-  @Column(name = "scope", length = 255)
-  private String scope;
-
-  @Column(name = "widget_values", length = 255)
-  private String widgetValues;
-
-  @Column(name = "properties", length = 255)
-  private String properties;
-
-  @Column(name = "cluster_id", nullable = false)
-  private Long clusterId;
-
-  @ManyToOne
-  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false, updatable = false, insertable = false)
-  private ClusterEntity clusterEntity;
-
-  @OneToMany(cascade = CascadeType.ALL, mappedBy = "userWidget")
-  private List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity;
-
-  public Long getId() {
-    return id;
-  }
-
-  public void setId(Long id) {
-    this.id = id;
-  }
-
-  public String getUserWidgetName() {
-    return userWidgetName;
-  }
-
-  public void setUserWidgetName(String userWidgetName) {
-    this.userWidgetName = userWidgetName;
-  }
-
-  public String getUserWidgetType() {
-    return userWidgetType;
-  }
-
-  public void setUserWidgetType(String userWidgetType) {
-    this.userWidgetType = userWidgetType;
-  }
-
-  public String getMetrics() {
-    return metrics;
-  }
-
-  public void setMetrics(String metrics) {
-    this.metrics = metrics;
-  }
-
-  public Long getTimeCreated() {
-    return timeCreated;
-  }
-
-  public void setTimeCreated(Long timeCreated) {
-    this.timeCreated = timeCreated;
-  }
-
-  public String getAuthor() {
-    return author;
-  }
-
-  public void setAuthor(String author) {
-    this.author = author;
-  }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public void setDescription(String description) {
-    this.description = description;
-  }
-
-  public String getDisplayName() {
-    return displayName;
-  }
-
-  public void setDisplayName(String displayName) {
-    this.displayName = displayName;
-  }
-
-  public String getScope() {
-    return scope;
-  }
-
-  public void setScope(String scope) {
-    this.scope = scope;
-  }
-
-  public String getWidgetValues() {
-    return widgetValues;
-  }
-
-  public void setWidgetValues(String widgetValues) {
-    this.widgetValues = widgetValues;
-  }
-
-  public String getProperties() {
-    return properties;
-  }
-
-  public void setProperties(String properties) {
-    this.properties = properties;
-  }
-
-  public ClusterEntity getClusterEntity() {
-    return clusterEntity;
-  }
-
-  public void setClusterEntity(ClusterEntity clusterEntity) {
-    this.clusterEntity = clusterEntity;
-  }
-
-  public Long getClusterId() {
-    return clusterId;
-  }
-
-  public void setClusterId(Long clusterId) {
-    this.clusterId = clusterId;
-  }
-
-  public List<WidgetLayoutUserWidgetEntity> getListWidgetLayoutUserWidgetEntity() {
-    return listWidgetLayoutUserWidgetEntity;
-  }
-
-  public void setListWidgetLayoutUserWidgetEntity(List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity) {
-    this.listWidgetLayoutUserWidgetEntity = listWidgetLayoutUserWidgetEntity;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-
-    UserWidgetEntity that = (UserWidgetEntity) o;
-
-    if (id != that.id) return false;
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = null != id ? id.hashCode() : 0;
-    return result;
-  }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
new file mode 100644
index 0000000..4fd6fbf
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
@@ -0,0 +1,231 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import java.util.List;
+
+@Entity
+@Table(name = "user_widget")
+@TableGenerator(name = "widget_id_generator",
+        table = "ambari_sequences",
+        pkColumnName = "sequence_name",
+        valueColumnName = "sequence_value",
+        pkColumnValue = "widget_id_seq",
+        initialValue = 0,
+        allocationSize = 1
+)
+@NamedQueries({
+    @NamedQuery(name = "WidgetEntity.findAll", query = "SELECT widget FROM WidgetEntity widget"),
+    @NamedQuery(name = "WidgetEntity.findByCluster", query = "SELECT widget FROM WidgetEntity widget WHERE widget.clusterId = :clusterId"),
+    @NamedQuery(name = "WidgetEntity.findBySectionName", query =
+                "SELECT widget FROM WidgetEntity widget " +
+                "INNER JOIN widget.listWidgetLayoutUserWidgetEntity widgetLayoutUserWidget " +
+                "INNER JOIN widgetLayoutUserWidget.widgetLayout  widgetLayout " +
+                "WHERE widgetLayout.sectionName = :sectionName")
+        })
+public class WidgetEntity {
+
+  @Id
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "widget_id_generator")
+  @Column(name = "id", nullable = false, updatable = false)
+  private Long id;
+
+  @Column(name = "user_widget_name", nullable = false, length = 255)
+  private String widgetName;
+
+  @Column(name = "user_widget_type", nullable = false, length = 255)
+  private String widgetType;
+
+  @Column(name = "metrics", length = 32672)
+  private String metrics;
+
+  @Column(name = "time_created", nullable = false, length = 255)
+  private Long timeCreated = System.currentTimeMillis();
+
+  @Column(name = "author", length = 255)
+  private String author;
+
+  @Column(name = "description", length = 255)
+  private String description;
+
+  @Column(name = "display_name", nullable = false,  length = 255)
+  private String displayName;
+
+  @Column(name = "scope", length = 255)
+  private String scope;
+
+  @Column(name = "widget_values", length = 255)
+  private String widgetValues;
+
+  @Column(name = "properties", length = 255)
+  private String properties;
+
+  @Column(name = "cluster_id", nullable = false)
+  private Long clusterId;
+
+  @ManyToOne
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false, updatable = false, insertable = false)
+  private ClusterEntity clusterEntity;
+
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "widget")
+  private List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity;
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getWidgetName() {
+    return widgetName;
+  }
+
+  public void setWidgetName(String widgetName) {
+    this.widgetName = widgetName;
+  }
+
+  public String getWidgetType() {
+    return widgetType;
+  }
+
+  public void setWidgetType(String widgetType) {
+    this.widgetType = widgetType;
+  }
+
+  public String getMetrics() {
+    return metrics;
+  }
+
+  public void setMetrics(String metrics) {
+    this.metrics = metrics;
+  }
+
+  public Long getTimeCreated() {
+    return timeCreated;
+  }
+
+  public void setTimeCreated(Long timeCreated) {
+    this.timeCreated = timeCreated;
+  }
+
+  public String getAuthor() {
+    return author;
+  }
+
+  public void setAuthor(String author) {
+    this.author = author;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  public String getScope() {
+    return scope;
+  }
+
+  public void setScope(String scope) {
+    this.scope = scope;
+  }
+
+  public String getWidgetValues() {
+    return widgetValues;
+  }
+
+  public void setWidgetValues(String widgetValues) {
+    this.widgetValues = widgetValues;
+  }
+
+  public String getProperties() {
+    return properties;
+  }
+
+  public void setProperties(String properties) {
+    this.properties = properties;
+  }
+
+  public ClusterEntity getClusterEntity() {
+    return clusterEntity;
+  }
+
+  public void setClusterEntity(ClusterEntity clusterEntity) {
+    this.clusterEntity = clusterEntity;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public List<WidgetLayoutUserWidgetEntity> getListWidgetLayoutUserWidgetEntity() {
+    return listWidgetLayoutUserWidgetEntity;
+  }
+
+  public void setListWidgetLayoutUserWidgetEntity(List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity) {
+    this.listWidgetLayoutUserWidgetEntity = listWidgetLayoutUserWidgetEntity;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    WidgetEntity that = (WidgetEntity) o;
+
+    if (id != that.id) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = null != id ? id.hashCode() : 0;
+    return result;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
index dfce4f4..820e3e0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
@@ -28,11 +28,21 @@ import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
 import javax.persistence.Table;
+import javax.persistence.TableGenerator;
 import java.util.List;
 
 @Entity
 @Table(name = "widget_layout")
+@TableGenerator(name = "widget_layout_id_generator",
+        table = "ambari_sequences",
+        pkColumnName = "sequence_name",
+        valueColumnName = "sequence_value",
+        pkColumnValue = "widget_layout_id_seq",
+        initialValue = 0,
+        allocationSize = 1
+)
 @NamedQueries({
     @NamedQuery(name = "WidgetLayoutEntity.findAll", query = "SELECT widgetLayout FROM WidgetLayoutEntity widgetLayout"),
     @NamedQuery(name = "WidgetLayoutEntity.findByCluster", query = "SELECT widgetLayout FROM WidgetLayoutEntity widgetLayout WHERE widgetLayout.clusterId = :clusterId"),
@@ -41,7 +51,7 @@ import java.util.List;
 public class WidgetLayoutEntity {
 
   @Id
-  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "widget_layout_id_generator")
   @Column(name = "id", nullable = false, updatable = false)
   private Long id;
 
@@ -54,11 +64,21 @@ public class WidgetLayoutEntity {
   @Column(name = "cluster_id", nullable = false)
   private Long clusterId;
 
+  @Column(name = "user_name", nullable = false)
+  private String userName;
+
+  @Column(name = "scope", nullable = false)
+  private String scope;
+
+  @Column(name = "display_name", nullable = false)
+  private String displayName;
+
   @ManyToOne
   @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false, updatable = false, insertable = false)
   private ClusterEntity clusterEntity;
 
-  @OneToMany(cascade = CascadeType.ALL, mappedBy = "widgetLayout")
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "widgetLayout", orphanRemoval = true)
+  @OrderBy("widgetOrder")
   private List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity;
 
   public Long getId() {
@@ -85,6 +105,30 @@ public class WidgetLayoutEntity {
     this.sectionName = sectionName;
   }
 
+  public String getUserName() {
+    return userName;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public String getScope() {
+    return scope;
+  }
+
+  public void setScope(String scope) {
+    this.scope = scope;
+  }
+
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
   public Long getClusterId() {
     return clusterId;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
index 5de9f89..df00eb3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
@@ -17,7 +17,6 @@
  */
 package org.apache.ambari.server.orm.entities;
 
-import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
@@ -40,13 +39,13 @@ public class WidgetLayoutUserWidgetEntity {
   @Column(name = "user_widget_id", nullable = false, updatable = false, insertable = false)
   private Long userWidgetId;
 
-  @ManyToOne(cascade = { CascadeType.ALL })
+  @ManyToOne
   @JoinColumn(name = "widget_layout_id", referencedColumnName = "id")
   private WidgetLayoutEntity widgetLayout;
 
-  @ManyToOne(cascade = { CascadeType.ALL })
+  @ManyToOne
   @JoinColumn(name = "user_widget_id", referencedColumnName = "id")
-  private UserWidgetEntity userWidget;
+  private WidgetEntity widget;
 
   @Column(name = "widget_order")
   private Integer widgetOrder;
@@ -75,12 +74,12 @@ public class WidgetLayoutUserWidgetEntity {
     this.widgetLayout = widgetLayout;
   }
 
-  public UserWidgetEntity getUserWidget() {
-    return userWidget;
+  public WidgetEntity getWidget() {
+    return widget;
   }
 
-  public void setUserWidget(UserWidgetEntity userWidget) {
-    this.userWidget = userWidget;
+  public void setWidget(WidgetEntity widget) {
+    this.widget = widget;
   }
 
   public Integer getWidgetOrder() {
@@ -99,7 +98,7 @@ public class WidgetLayoutUserWidgetEntity {
     WidgetLayoutUserWidgetEntity that = (WidgetLayoutUserWidgetEntity) o;
 
     if (widgetLayout.getId() != that.widgetLayout.getId()) return false;
-    if (userWidget.getId() != that.userWidget.getId()) return false;
+    if (widget.getId() != that.widget.getId()) return false;
 
     return true;
   }
@@ -107,7 +106,7 @@ public class WidgetLayoutUserWidgetEntity {
   @Override
   public int hashCode() {
     int result = null != widgetLayout ? widgetLayout.hashCode() : 0;
-    result = 31 * result + (userWidget != null ? userWidget.hashCode() : 0);
+    result = 31 * result + (widget != null ? widget.hashCode() : 0);
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 d1a0bbe..854a897 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
@@ -321,8 +321,11 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
     columns.add(new DBColumnInfo("layout_name", String.class,  255,   null, false));
     columns.add(new DBColumnInfo("section_name", String.class,  255,   null, false));
     columns.add(new DBColumnInfo("cluster_id", Long.class,  255,   null, false));
+    columns.add(new DBColumnInfo("scope", String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("user_name", String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("display_name", String.class,  255,   null, false));
+
     dbAccessor.createTable(WIDGET_LAYOUT_TABLE, columns, "id");
-    dbAccessor.executeQuery("ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, section_name)");
 
     columns = new ArrayList<DBColumnInfo>();
     columns.add(new DBColumnInfo("widget_layout_id", Long.class,    null,  null, false));

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 3bfe959..36f4208 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -554,6 +554,9 @@ CREATE TABLE ambari.widget_layout (
   id BIGINT NOT NULL,
   layout_name VARCHAR(255) NOT NULL,
   section_name VARCHAR(255) NOT NULL,
+  scope VARCHAR(255) NOT NULL,
+  user_name VARCHAR(255) NOT NULL,
+  display_name VARCHAR(255) NOT NULL,
   cluster_id BIGINT NOT NULL,
   PRIMARY KEY(id)
 );
@@ -584,7 +587,6 @@ ALTER TABLE serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
-ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, section_name);
 
 -- altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
@@ -865,6 +867,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_id_
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_group_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_item_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('stack_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_layout_id_seq', 0);
 
 insert into adminresourcetype (resource_type_id, resource_type_name)
   select 1, 'AMBARI'

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 807306f..204f1bf 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -542,6 +542,9 @@ CREATE TABLE ambari.widget_layout (
   id NUMBER(19) NOT NULL,
   layout_name VARCHAR2(255) NOT NULL,
   section_name VARCHAR2(255) NOT NULL,
+  scope VARCHAR2(255) NOT NULL,
+  user_name VARCHAR2(255) NOT NULL,
+  display_name VARCHAR2(255) NOT NULL,
   cluster_id NUMBER(19) NOT NULL,
   PRIMARY KEY(id)
 );
@@ -572,7 +575,6 @@ ALTER TABLE serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
-ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, section_name);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
@@ -856,6 +858,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_id_
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_group_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_item_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('stack_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_layout_id_seq', 0);
 
 INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', '${ambariVersion}');
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 f728bdf..a772c5c 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -547,6 +547,9 @@ CREATE TABLE widget_layout (
   id BIGINT NOT NULL,
   layout_name VARCHAR(255) NOT NULL,
   section_name VARCHAR(255) NOT NULL,
+  scope VARCHAR(255) NOT NULL,
+  user_name VARCHAR(255) NOT NULL,
+  display_name VARCHAR(255) NOT NULL,
   cluster_id BIGINT NOT NULL,
   PRIMARY KEY(id)
 );
@@ -574,7 +577,6 @@ ALTER TABLE serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
-ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, section_name);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
@@ -889,6 +891,10 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   union all
   select 'upgrade_group_id_seq', 0
   union all
+  select 'widget_id_seq', 0
+  union all
+  select 'widget_layout_id_seq', 0
+  union all
   select 'upgrade_item_id_seq', 0
   union all
   select 'stack_id_seq', 0;  

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/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 034639d..89a4f9a 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
@@ -623,6 +623,9 @@ CREATE TABLE ambari.widget_layout (
   id BIGINT NOT NULL,
   layout_name VARCHAR(255) NOT NULL,
   section_name VARCHAR(255) NOT NULL,
+  scope VARCHAR(255) NOT NULL,
+  user_name VARCHAR(255) NOT NULL,
+  display_name VARCHAR(255) NOT NULL,
   cluster_id BIGINT NOT NULL,
   PRIMARY KEY(id)
 );
@@ -646,7 +649,6 @@ ALTER TABLE ambari.serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (c
 ALTER TABLE ambari.adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE ambari.repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
 ALTER TABLE ambari.repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
-ALTER TABLE ambari.widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, section_name);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE ambari.members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES ambari.groups (group_id);
@@ -979,6 +981,10 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value)
   union all
   select 'upgrade_group_id_seq', 0 
   union all
+  select 'widget_id_seq', 0
+  union all
+  select 'widget_layout_id_seq', 0
+  union all
   select 'upgrade_item_id_seq', 0
   union all
   select 'stack_id_seq', 0;

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 3146aff..b864c59 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -72,7 +72,7 @@
     <class>org.apache.ambari.server.orm.entities.UpgradeGroupEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeItemEntity</class>
     <class>org.apache.ambari.server.orm.entities.UserEntity</class>
-    <class>org.apache.ambari.server.orm.entities.UserWidgetEntity</class>
+    <class>org.apache.ambari.server.orm.entities.WidgetEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntityEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewInstanceDataEntity</class>

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index 300d77e..540d58b 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -421,6 +421,33 @@
         "HostRoles/host_name",
         "_"
     ],
+    "Widget":[
+      "Widgets/id",
+      "Widgets/cluster_name",
+      "Widgets/widget_name",
+      "Widgets/display_name",
+      "Widgets/widget_type",
+      "Widgets/time_created",
+      "Widgets/author",
+      "Widgets/description",
+      "Widgets/scope",
+      "Widgets/metrics",
+      "Widgets/values",
+      "Widgets/properties",
+      "_"
+    ],
+    "WidgetLayout":[
+      "WidgetLayouts/id",
+      "WidgetLayouts/section_name",
+      "WidgetLayouts/cluster_name",
+      "WidgetLayouts/layout_name",
+      "WidgetLayouts/display_name",
+      "WidgetLayouts/scope",
+      "WidgetLayouts/user_name",
+      "WidgetLayouts/WidgetsInfo",
+      "User/user_name",
+      "_"
+    ],
     "StackLevelConfiguration":[
         "StackLevelConfigurations/stack_name",
         "StackLevelConfigurations/stack_version",

http://git-wip-us.apache.org/repos/asf/ambari/blob/4b3caee7/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java
index f89b1b3..c529301 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java
@@ -399,6 +399,8 @@ public class JsonRequestBodyParserTest {
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(1, setProps2.size());
     assertEquals(setProperties, setProps2);
+    assertEquals("java.util.LinkedHashSet",
+            body.getNamedPropertySets().iterator().next().getProperties().get("services").getClass().getName());
   }
 
   @Test