You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2014/08/25 03:07:16 UTC

git commit: AMBARI-6995 - Views: Ability to access new view instance UI w/o restarting ambari server

Repository: ambari
Updated Branches:
  refs/heads/trunk ebf47965b -> 3c13f40fa


AMBARI-6995 - Views: Ability to access new view instance UI w/o restarting ambari server


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

Branch: refs/heads/trunk
Commit: 3c13f40fa5fe120cd8b59deb8c7781f193c6e35b
Parents: ebf4796
Author: tbeerbower <tb...@hortonworks.com>
Authored: Fri Aug 22 16:03:24 2014 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Sun Aug 24 20:26:43 2014 -0400

----------------------------------------------------------------------
 .../server/controller/AmbariHandlerList.java    | 151 +++++++++++++++++++
 .../ambari/server/controller/AmbariServer.java  |  10 +-
 .../server/controller/ControllerModule.java     |   2 +
 .../server/controller/FailsafeHandlerList.java  |  40 ++++-
 .../internal/ViewInstanceResourceProvider.java  |   6 +-
 .../server/orm/entities/ViewInstanceEntity.java |  20 +++
 .../server/view/ViewInstanceHandlerList.java    |  43 ++++++
 .../apache/ambari/server/view/ViewRegistry.java |  58 +++----
 .../controller/AmbariHandlerListTest.java       | 107 +++++++++++++
 .../ambari/server/view/ViewRegistryTest.java    |   8 +-
 10 files changed, 402 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
new file mode 100644
index 0000000..2dc3f47
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
@@ -0,0 +1,151 @@
+/**
+ * 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.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.view.ViewContextImpl;
+import org.apache.ambari.server.view.ViewInstanceHandlerList;
+import org.apache.ambari.server.view.ViewRegistry;
+import org.apache.ambari.view.SystemException;
+import org.apache.ambari.view.ViewContext;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An Ambari specific extension of the FailsafeHandlerList that allows for the addition
+ * of view instances as handlers.
+ */
+@Singleton
+public class AmbariHandlerList extends FailsafeHandlerList implements ViewInstanceHandlerList {
+
+  /**
+   * The view registry.
+   */
+  @Inject
+  ViewRegistry viewRegistry;
+
+  /**
+   * The Handler factory.
+   */
+  private final HandlerFactory handlerFactory;
+
+  /**
+   * Mapping of view instance entities to handlers.
+   */
+  private final Map<ViewInstanceEntity, Handler> handlerMap = new HashMap<ViewInstanceEntity, Handler>();
+
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Construct an AmbariHandlerList.
+   */
+  public AmbariHandlerList() {
+    super(true);
+    this.handlerFactory = new HandlerFactory() {
+      @Override
+      public Handler create(ViewInstanceEntity viewInstanceDefinition, String webApp, String contextPath) {
+
+        WebAppContext context = new WebAppContext(webApp, contextPath);
+
+        context.setClassLoader(viewInstanceDefinition.getViewEntity().getClassLoader());
+        context.setAttribute(ViewContext.CONTEXT_ATTRIBUTE, new ViewContextImpl(viewInstanceDefinition, viewRegistry));
+
+        return context;
+      }
+    };
+  }
+
+  /**
+   * Construct an AmbariHandlerList with the given handler factory.
+   *
+   * @param handlerFactory  the handler factory.
+   */
+  protected AmbariHandlerList(HandlerFactory handlerFactory) {
+    super(true);
+    this.handlerFactory = handlerFactory;
+  }
+
+
+  // ----- ViewInstanceHandler -----------------------------------------------
+
+  @Override
+  public void addViewInstance(ViewInstanceEntity viewInstanceDefinition) throws SystemException {
+    Handler handler = getHandler(viewInstanceDefinition);
+    handlerMap.put(viewInstanceDefinition, handler);
+    addFailsafeHandler(handler);
+    // if this is running then start the handler being added...
+    if(!isStopped() && !isStopping()) {
+      try {
+        handler.start();
+      } catch (Exception e) {
+        throw new SystemException("Caught exception adding a view instance.", e);
+      }
+    }
+  }
+
+  @Override
+  public void removeViewInstance(ViewInstanceEntity viewInstanceDefinition) {
+    Handler handler = handlerMap.get(viewInstanceDefinition);
+    if (handler != null) {
+      removeHandler(handler);
+    }
+  }
+
+
+  // ----- helper methods ----------------------------------------------------
+
+  /**
+   * Get a Handler for the given view instance.
+   *
+   * @param viewInstanceDefinition  the view instance definition
+   *
+   * @return a handler
+   *
+   * @throws org.apache.ambari.view.SystemException if an handler can not be obtained for the given view instance
+   */
+  private Handler getHandler(ViewInstanceEntity viewInstanceDefinition)
+      throws SystemException {
+    ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
+    return handlerFactory.create(viewInstanceDefinition, viewDefinition.getArchive(), viewInstanceDefinition.getContextPath());
+  }
+
+
+  // ----- inner interface : HandlerFactory ----------------------------------
+
+  /**
+   * Factory for creating Handler instances.
+   */
+  protected interface HandlerFactory {
+    /**
+     * Create a Handler.
+     *
+     * @param webApp       the web app archive
+     * @param contextPath  the context path
+     *
+     * @return a new Handler instance
+     */
+    public Handler create(ViewInstanceEntity viewInstanceDefinition, String webApp, String contextPath);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 07de5cb..955bf0a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -150,6 +150,12 @@ public class AmbariServer {
   @Inject
   ViewRegistry viewRegistry;
 
+  /**
+   * The handler list for deployed web apps.
+   */
+  @Inject
+  AmbariHandlerList handlerList;
+
   public String getServerOsType() {
     return configs.getServerOsType();
   }
@@ -301,11 +307,9 @@ public class AmbariServer {
       root.addServlet(sh, "/api/v1/*");
       sh.setInitOrder(2);
 
-      FailsafeHandlerList handlerList = new FailsafeHandlerList();
-
       try {
         for (ViewInstanceEntity entity : viewRegistry.readViewArchives(configs)){
-          handlerList.addFailsafeHandler(viewRegistry.getWebAppContext(entity));
+          handlerList.addViewInstance(entity);
         }
       } catch (SystemException e) {
         LOG.error("Caught exception deploying views.", e);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 2513382..fa785c8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -76,6 +76,7 @@ import org.apache.ambari.server.state.scheduler.RequestExecution;
 import org.apache.ambari.server.state.scheduler.RequestExecutionFactory;
 import org.apache.ambari.server.state.scheduler.RequestExecutionImpl;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostImpl;
+import org.apache.ambari.server.view.ViewInstanceHandlerList;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.StandardPasswordEncoder;
 
@@ -201,6 +202,7 @@ public class ControllerModule extends AbstractModule {
     bind(ServerActionManager.class).to(ServerActionManagerImpl.class);
     bind(ExecutionScheduler.class).to(ExecutionSchedulerImpl.class);
     bind(DBAccessor.class).to(DBAccessorImpl.class);
+    bind(ViewInstanceHandlerList.class).to(AmbariHandlerList.class);
 
     requestStaticInjection(ExecutionCommandWrapper.class);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/controller/FailsafeHandlerList.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/FailsafeHandlerList.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/FailsafeHandlerList.java
index 48ec626..fa1e6b1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/FailsafeHandlerList.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/FailsafeHandlerList.java
@@ -50,16 +50,40 @@ public class FailsafeHandlerList extends HandlerCollection {
    */
   private final List<Handler> failsafeHandlers = new ArrayList<Handler>();
 
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Construct a FailsafeHandlerList.
+   */
+  public FailsafeHandlerList() {
+  }
+
+  /**
+   * Construct a FailsafeHandlerList.
+   *
+   * @param mutableWhenRunning allow for changes while running
+   */
+  public FailsafeHandlerList(boolean mutableWhenRunning) {
+    super(mutableWhenRunning);
+  }
+
+
+  // ----- FailsafeHandlerList -----------------------------------------------
+
   /**
    * Adds handler to collection and marks it as fail-safe.
    *
-   * @param handler failsafe handler
+   * @param handler fail-safe handler
    */
   public void addFailsafeHandler(Handler handler) {
     addHandler(handler);
     failsafeHandlers.add(handler);
   }
 
+
+  // ----- HandlerCollection -------------------------------------------------
+
   @Override
   public void removeHandler(Handler handler) {
     super.removeHandler(handler);
@@ -74,11 +98,16 @@ public class FailsafeHandlerList extends HandlerCollection {
   public void handle(String target, Request baseRequest,
       HttpServletRequest request, HttpServletResponse response)
       throws IOException, ServletException {
+
     final Handler[] handlers = getHandlers();
 
     if (handlers != null && isStarted()) {
+
+      List<Handler> nonFailsafeHandlers = new ArrayList<Handler>();
+
       for (int i = 0; i < handlers.length; i++) {
         final Handler handler = handlers[i];
+        // Do all of the fail-safe handlers first...
         if (failsafeHandlers.contains(handler)) {
           try {
             final FailsafeServletResponse responseWrapper = new FailsafeServletResponse(response);
@@ -92,12 +121,19 @@ public class FailsafeHandlerList extends HandlerCollection {
             continue;
           }
         } else {
-          handler.handle(target, baseRequest, request, response);
+          nonFailsafeHandlers.add(handler);
         }
         if (baseRequest.isHandled()) {
           return;
         }
       }
+
+      for (Handler handler : nonFailsafeHandlers) {
+        handler.handle(target, baseRequest, request, response);
+        if (baseRequest.isHandled()) {
+          return;
+        }
+      }
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
index 75b0879..ae02f0a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
@@ -331,7 +331,11 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
     return new Command<Void>() {
       @Override
       public Void invoke() throws AmbariException {
-        ViewRegistry.getInstance().installViewInstance(toEntity(properties));
+        try {
+          ViewRegistry.getInstance().installViewInstance(toEntity(properties));
+        } catch (org.apache.ambari.view.SystemException e) {
+          throw new AmbariException("Caught exception trying to create view instance.", e);
+        }
         return null;
       }
     };

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
index 643bac2..8fa700e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
@@ -748,4 +748,24 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
   protected void setSecurityHelper(SecurityHelper securityHelper) {
     this.securityHelper = securityHelper;
   }
+
+
+  // ----- Object overrides --------------------------------------------------
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ViewInstanceEntity that = (ViewInstanceEntity) o;
+
+    return name.equals(that.name) && viewName.equals(that.viewName);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = viewName.hashCode();
+    result = 31 * result + name.hashCode();
+    return result;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/view/ViewInstanceHandlerList.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewInstanceHandlerList.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewInstanceHandlerList.java
new file mode 100644
index 0000000..8d2b52a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewInstanceHandlerList.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.view;
+
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.view.SystemException;
+
+/**
+ * List of handlers for deployed view instances.
+ */
+public interface ViewInstanceHandlerList {
+
+  /**
+   * Add a handler for the given view instance.
+   *
+   * @param viewInstanceDefinition  the view instance
+   *
+   * @throws SystemException if a handler the view instance can not be added
+   */
+  public void addViewInstance(ViewInstanceEntity viewInstanceDefinition) throws SystemException;
+
+  /**
+   * Remove the handler for the given view instance.
+   *
+   * @param viewInstanceDefinition  the view instance
+   */
+  public void removeViewInstance(ViewInstanceEntity viewInstanceDefinition);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index 56a3168..7542876 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -93,7 +93,6 @@ import org.apache.ambari.view.ViewResourceHandler;
 import org.apache.ambari.view.events.Event;
 import org.apache.ambari.view.events.Listener;
 import org.apache.commons.lang.StringUtils;
-import org.eclipse.jetty.webapp.WebAppContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.GrantedAuthority;
@@ -208,6 +207,12 @@ public class ViewRegistry {
   @Inject
   Configuration configuration;
 
+  /**
+   * The handler list.
+   */
+  @Inject
+  ViewInstanceHandlerList handlerList;
+
 
   // ----- ViewRegistry ------------------------------------------------------
 
@@ -468,9 +473,10 @@ public class ViewRegistry {
    * @throws IllegalStateException     if the given instance is not in a valid state
    * @throws IllegalArgumentException  if the view associated with the given instance
    *                                   does not exist
+   * @throws SystemException           if the instance can not be installed
    */
   public void installViewInstance(ViewInstanceEntity instanceEntity)
-      throws IllegalStateException, IllegalArgumentException {
+      throws IllegalStateException, IllegalArgumentException, SystemException {
     ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());
 
     if (viewEntity != null) {
@@ -511,6 +517,9 @@ public class ViewRegistry {
         }
         // update the registry
         addInstanceDefinition(viewEntity, instanceEntity);
+
+        // add the web app context
+        handlerList.addViewInstance(instanceEntity);
       }
     } else {
       String message = "Attempt to install an instance for an unknown view " +
@@ -539,21 +548,6 @@ public class ViewRegistry {
   }
 
   /**
-   * Remove the data entry keyed by the given key from the given instance entity.
-   *
-   * @param instanceEntity  the instance entity
-   * @param key             the data key
-   */
-  public void removeInstanceData(ViewInstanceEntity instanceEntity, String key) {
-    ViewInstanceDataEntity dataEntity = instanceEntity.getInstanceData(key);
-    if (dataEntity != null) {
-      instanceDAO.removeData(dataEntity);
-    }
-    instanceEntity.removeInstanceData(key);
-    instanceDAO.merge(instanceEntity);
-  }
-
-  /**
    * Uninstall a view instance for the view with the given view name.
    *
    * @param instanceEntity  the view instance entity
@@ -578,32 +572,26 @@ public class ViewRegistry {
         instanceDAO.remove(instanceEntity);
         viewEntity.removeInstanceDefinition(instanceName);
         removeInstanceDefinition(viewEntity, instanceName);
+
+        // remove the web app context
+        handlerList.removeViewInstance(instanceEntity);
       }
     }
   }
 
   /**
-   * Get a WebAppContext for the given view instance.
-   *
-   * @param viewInstanceDefinition  the view instance definition
-   *
-   * @return a web app context
+   * Remove the data entry keyed by the given key from the given instance entity.
    *
-   * @throws SystemException if an application context can not be obtained for the given view instance
+   * @param instanceEntity  the instance entity
+   * @param key             the data key
    */
-  public WebAppContext getWebAppContext(ViewInstanceEntity viewInstanceDefinition)
-      throws SystemException{
-    try {
-      ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
-
-      WebAppContext context = new WebAppContext(viewDefinition.getArchive(), viewInstanceDefinition.getContextPath());
-      context.setClassLoader(viewDefinition.getClassLoader());
-      context.setAttribute(ViewContext.CONTEXT_ATTRIBUTE, new ViewContextImpl(viewInstanceDefinition, this));
-      return context;
-    } catch (Exception e) {
-      throw new SystemException("Can't get application context for view " +
-          viewInstanceDefinition.getViewEntity().getCommonName() + ".", e);
+  public void removeInstanceData(ViewInstanceEntity instanceEntity, String key) {
+    ViewInstanceDataEntity dataEntity = instanceEntity.getInstanceData(key);
+    if (dataEntity != null) {
+      instanceDAO.removeData(dataEntity);
     }
+    instanceEntity.removeInstanceData(key);
+    instanceDAO.merge(instanceEntity);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java
new file mode 100644
index 0000000..7171e88
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java
@@ -0,0 +1,107 @@
+/**
+ * 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.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntityTest;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * AmbariHandlerList tests.
+ */
+public class AmbariHandlerListTest {
+  @Test
+  public void testAddViewInstance() throws Exception {
+
+    ViewInstanceEntity viewInstanceEntity = ViewInstanceEntityTest.getViewInstanceEntity();
+
+    final Handler handler = createNiceMock(Handler.class);
+    Server server = createNiceMock(Server.class);
+
+    expect(handler.getServer()).andReturn(server);
+    handler.setServer(null);
+
+    replay(handler, server);
+
+    AmbariHandlerList.HandlerFactory handlerFactory = new AmbariHandlerList.HandlerFactory() {
+      @Override
+      public Handler create(ViewInstanceEntity viewInstanceDefinition, String webApp, String contextPath) {
+        return handler;
+      }
+    };
+
+    AmbariHandlerList handlerList = new AmbariHandlerList(handlerFactory);
+
+    handlerList.addViewInstance(viewInstanceEntity);
+
+    ArrayList<Handler> handlers = new ArrayList<Handler>(Arrays.asList(handlerList.getHandlers()));
+
+    Assert.assertTrue(handlers.contains(handler));
+
+    verify(handler, server);
+  }
+
+  @Test
+  public void testRemoveViewInstance() throws Exception {
+    ViewInstanceEntity viewInstanceEntity = ViewInstanceEntityTest.getViewInstanceEntity();
+
+    final Handler handler = createNiceMock(Handler.class);
+    Server server = createNiceMock(Server.class);
+
+    expect(handler.getServer()).andReturn(server);
+    handler.setServer(null);
+
+    replay(handler, server);
+
+    AmbariHandlerList.HandlerFactory handlerFactory = new AmbariHandlerList.HandlerFactory() {
+      @Override
+      public Handler create(ViewInstanceEntity viewInstanceDefinition, String webApp, String contextPath) {
+        return handler;
+      }
+    };
+
+    AmbariHandlerList handlerList = new AmbariHandlerList(handlerFactory);
+
+    handlerList.addViewInstance(viewInstanceEntity);
+
+    ArrayList<Handler> handlers = new ArrayList<Handler>(Arrays.asList(handlerList.getHandlers()));
+
+    Assert.assertTrue(handlers.contains(handler));
+
+    handlerList.removeViewInstance(viewInstanceEntity);
+
+    handlers = new ArrayList<Handler>(Arrays.asList(handlerList.getHandlers()));
+
+    Assert.assertFalse(handlers.contains(handler));
+
+    verify(handler, server);
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3c13f40f/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
index ed3a6a9..55dca84 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
@@ -158,6 +158,7 @@ public class ViewRegistryTest {
   private static final ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
   private static final SecurityHelper securityHelper = createNiceMock(SecurityHelper.class);
   private static final Configuration configuration = createNiceMock(Configuration.class);
+  private static final ViewInstanceHandlerList handlerList = createNiceMock(ViewInstanceHandlerList.class);
 
   @Test
   public void testReadViewArchives() throws Exception {
@@ -521,7 +522,9 @@ public class ViewRegistryTest {
     expect(viewInstanceDAO.merge(viewInstanceEntity)).andReturn(null);
     expect(viewInstanceDAO.findByName("MY_VIEW{1.0.0}", viewInstanceEntity.getInstanceName())).andReturn(viewInstanceEntity);
 
-    replay(viewDAO, viewInstanceDAO, securityHelper);
+    handlerList.addViewInstance(viewInstanceEntity);
+
+    replay(viewDAO, viewInstanceDAO, securityHelper, handlerList);
 
     registry.addDefinition(viewEntity);
     registry.installViewInstance(viewInstanceEntity);
@@ -532,7 +535,7 @@ public class ViewRegistryTest {
 
     Assert.assertEquals(viewInstanceEntity, viewInstanceDefinitions.iterator().next());
 
-    verify(viewDAO, viewInstanceDAO, securityHelper);
+    verify(viewDAO, viewInstanceDAO, securityHelper, handlerList);
   }
 
   @Test
@@ -856,6 +859,7 @@ public class ViewRegistryTest {
     instance.resourceTypeDAO = resourceTypeDAO;
     instance.securityHelper = securityHelper;
     instance.configuration = configuration;
+    instance.handlerList = handlerList;
 
     return instance;
   }