Browse Source

AMBARI-5167. Takes 48 seconds on 800 node cluster for HostComponent creation. (Myroslav Papirkovskyy via swagle)

Siddharth Wagle 11 years ago
parent
commit
fae3fa56d4
39 changed files with 807 additions and 256 deletions
  1. 198 0
      ambari-server/src/main/java/com/google/inject/persist/jpa/AmbariJpaPersistModule.java
  2. 37 0
      ambari-server/src/main/java/com/google/inject/persist/jpa/AmbariJpaPersistService.java
  3. 27 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
  4. 4 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
  5. 8 10
      ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java
  6. 160 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/AmbariJpaLocalTxnInterceptor.java
  7. 60 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/AmbariLocalSessionInterceptor.java
  8. 39 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/RequiresSession.java
  9. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintDAO.java
  10. 10 9
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterDAO.java
  11. 4 3
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
  12. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterStateDAO.java
  13. 4 3
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupConfigMappingDAO.java
  14. 22 20
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupDAO.java
  15. 5 5
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupHostMappingDAO.java
  16. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ExecutionCommandDAO.java
  17. 13 12
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java
  18. 13 12
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java
  19. 7 7
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostConfigMappingDAO.java
  20. 4 3
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostDAO.java
  21. 75 74
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
  22. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostStateDAO.java
  23. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KeyValueDAO.java
  24. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MetainfoDAO.java
  25. 9 6
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestDAO.java
  26. 4 3
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestScheduleBatchRequestDAO.java
  27. 4 3
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestScheduleDAO.java
  28. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RoleDAO.java
  29. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RoleSuccessCriteriaDAO.java
  30. 14 13
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
  31. 14 13
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java
  32. 29 28
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/StageDAO.java
  33. 7 6
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
  34. 2 1
      ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
  35. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
  36. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
  37. 2 2
      ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java
  38. 6 0
      ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java
  39. 0 2
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java

+ 198 - 0
ambari-server/src/main/java/com/google/inject/persist/jpa/AmbariJpaPersistModule.java

@@ -0,0 +1,198 @@
+/**
+ * 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 com.google.inject.persist.jpa;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.persist.PersistModule;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+import com.google.inject.persist.finder.DynamicFinder;
+import com.google.inject.persist.finder.Finder;
+import com.google.inject.util.Providers;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.ambari.server.orm.AmbariJpaLocalTxnInterceptor;
+import org.apache.ambari.server.orm.AmbariLocalSessionInterceptor;
+import org.apache.ambari.server.orm.RequiresSession;
+
+import static com.google.inject.matcher.Matchers.annotatedWith;
+import static com.google.inject.matcher.Matchers.any;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Copy of guice persist module for local modifications
+ */
+public class AmbariJpaPersistModule extends PersistModule {
+  private final String jpaUnit;
+
+  public AmbariJpaPersistModule(String jpaUnit) {
+    if (null != jpaUnit && jpaUnit.length() > 0) {
+      this.jpaUnit = jpaUnit;
+    } else {
+      throw new IllegalArgumentException("jpaUnit should not be null");
+    }
+  }
+
+  private Properties properties;
+  private MethodInterceptor transactionInterceptor;
+  private MethodInterceptor sessionInterceptor;
+
+  @Override protected void configurePersistence() {
+    bindConstant().annotatedWith(Jpa.class).to(jpaUnit);
+
+    if (null != properties) {
+      bind(Properties.class).annotatedWith(Jpa.class).toInstance(properties);
+    } else {
+      bind(Properties.class).annotatedWith(Jpa.class)
+          .toProvider(Providers.<Properties>of(null));
+    }
+
+    bind(AmbariJpaPersistService.class).in(Singleton.class);
+
+    bind(PersistService.class).to(AmbariJpaPersistService.class);
+    bind(UnitOfWork.class).to(AmbariJpaPersistService.class);
+    bind(EntityManager.class).toProvider(AmbariJpaPersistService.class);
+    bind(EntityManagerFactory.class)
+        .toProvider(JpaPersistService.EntityManagerFactoryProvider.class);
+
+
+
+    transactionInterceptor = new AmbariJpaLocalTxnInterceptor();
+    requestInjection(transactionInterceptor);
+    sessionInterceptor = new AmbariLocalSessionInterceptor();
+    requestInjection(sessionInterceptor);
+
+
+    // Bind dynamic finders.
+    for (Class<?> finder : dynamicFinders) {
+      bindFinder(finder);
+    }
+
+    bindInterceptor(annotatedWith(RequiresSession.class), any(), sessionInterceptor);
+    bindInterceptor(any(), annotatedWith(RequiresSession.class), sessionInterceptor);
+  }
+
+
+
+  @Override protected MethodInterceptor getTransactionInterceptor() {
+    return transactionInterceptor;
+  }
+
+  /**
+   * Configures the JPA persistence provider with a set of properties.
+   *
+   * @param properties A set of name value pairs that configure a JPA persistence
+   * provider as per the specification.
+   */
+  public AmbariJpaPersistModule properties(Properties properties) {
+    this.properties = properties;
+    return this;
+  }
+
+  private final List<Class<?>> dynamicFinders = Lists.newArrayList();
+
+  /**
+   * Adds an interface to this module to use as a dynamic finder.
+   *
+   * @param iface Any interface type whose methods are all dynamic finders.
+   */
+  public <T> AmbariJpaPersistModule addFinder(Class<T> iface) {
+    dynamicFinders.add(iface);
+    return this;
+  }
+
+  private <T> void bindFinder(Class<T> iface) {
+    if (!isDynamicFinderValid(iface)) {
+      return;
+    }
+
+    InvocationHandler finderInvoker = new InvocationHandler() {
+      @Inject
+      JpaFinderProxy finderProxy;
+
+      public Object invoke(final Object thisObject, final Method method, final Object[] args)
+          throws Throwable {
+
+        // Don't intercept non-finder methods like equals and hashcode.
+        if (!method.isAnnotationPresent(Finder.class)) {
+          // This is not ideal, we are using the invocation handler's equals
+          // and hashcode as a proxy (!) for the proxy's equals and hashcode.
+          return method.invoke(this, args);
+        }
+
+        return finderProxy.invoke(new MethodInvocation() {
+          public Method getMethod() {
+            return method;
+          }
+
+          public Object[] getArguments() {
+            return null == args ? new Object[0] : args;
+          }
+
+          public Object proceed() throws Throwable {
+            return method.invoke(thisObject, args);
+          }
+
+          public Object getThis() {
+            throw new UnsupportedOperationException("Bottomless proxies don't expose a this.");
+          }
+
+          public AccessibleObject getStaticPart() {
+            throw new UnsupportedOperationException();
+          }
+        });
+      }
+    };
+    requestInjection(finderInvoker);
+
+    @SuppressWarnings("unchecked") // Proxy must produce instance of type given.
+        T proxy = (T) Proxy
+        .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { iface },
+            finderInvoker);
+
+    bind(iface).toInstance(proxy);
+  }
+
+  private boolean isDynamicFinderValid(Class<?> iface) {
+    boolean valid = true;
+    if (!iface.isInterface()) {
+      addError(iface + " is not an interface. Dynamic Finders must be interfaces.");
+      valid = false;
+    }
+
+    for (Method method : iface.getMethods()) {
+      DynamicFinder finder = DynamicFinder.from(method);
+      if (null == finder) {
+        addError("Dynamic Finder methods must be annotated with @Finder, but " + iface
+            + "." + method.getName() + " was not");
+        valid = false;
+      }
+    }
+    return valid;
+  }
+}

+ 37 - 0
ambari-server/src/main/java/com/google/inject/persist/jpa/AmbariJpaPersistService.java

@@ -0,0 +1,37 @@
+/**
+ * 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 com.google.inject.persist.jpa;
+
+
+import com.google.inject.Inject;
+import com.google.inject.internal.util.$Nullable;
+
+import java.util.Properties;
+
+/**
+ * Override non-public class limitations as we need non-interface method
+ */
+public class AmbariJpaPersistService extends JpaPersistService {
+
+  @Inject
+  public AmbariJpaPersistService(@Jpa String persistenceUnitName, @$Nullable @Jpa Properties persistenceProperties) {
+    super(persistenceUnitName, persistenceProperties);
+  }
+
+
+}

+ 27 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -498,6 +498,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
 
     // now doing actual work
+    persistServiceComponentHosts(requests);
+  }
+
+  @Transactional
+  void persistServiceComponentHosts(Set<ServiceComponentHostRequest> requests) throws AmbariException {
     for (ServiceComponentHostRequest request : requests) {
       Cluster cluster = clusters.getCluster(request.getClusterName());
       Service s = cluster.getService(request.getServiceName());
@@ -526,6 +531,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
   }
 
+
   @Override
   public synchronized void createConfiguration(
       ConfigurationRequest request) throws AmbariException {
@@ -645,15 +651,20 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   private Set<ServiceComponentHostResponse> getHostComponents(
       ServiceComponentHostRequest request) throws AmbariException {
+    LOG.debug("Processing request {}", request);
+
     if (request.getClusterName() == null
         || request.getClusterName().isEmpty()) {
-      throw new IllegalArgumentException("Invalid arguments, cluster name should not be null");
+      IllegalArgumentException e = new IllegalArgumentException("Invalid arguments, cluster name should not be null");
+      LOG.debug("Cluster not specified in request", e);
+      throw e;
     }
 
     final Cluster cluster;
     try {
       cluster = clusters.getCluster(request.getClusterName());
     } catch (ClusterNotFoundException e) {
+      LOG.error("Cluster not found ", e);
       throw new ParentObjectNotFoundException("Parent Cluster resource doesn't exist", e);
     }
 
@@ -661,10 +672,12 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       try {
         if (!clusters.getClustersForHost(request.getHostname()).contains(cluster)) {
           // case where host exists but not associated with given cluster
+          LOG.error("Host doesn't belong to cluster");
           throw new ParentObjectNotFoundException("Parent Host resource doesn't exist",
               new HostNotFoundException(request.getClusterName(), request.getHostname()));
         }
       } catch (HostNotFoundException e) {
+        LOG.error("Host not found", e);
         // creating new HostNotFoundException to add cluster name
         throw new ParentObjectNotFoundException("Parent Host resource doesn't exist",
             new HostNotFoundException(request.getClusterName(), request.getHostname()));
@@ -686,6 +699,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         }
         if (serviceName == null
             || serviceName.isEmpty()) {
+          LOG.error("Unable to find service for component {}", request.getComponentName());
           throw new ServiceComponentHostNotFoundException(
               cluster.getClusterName(), null, request.getComponentName(), request.getHostname());
         }
@@ -748,8 +762,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           try {
             if (serviceComponentHostMap == null
                 || !serviceComponentHostMap.containsKey(request.getHostname())) {
-              throw new ServiceComponentHostNotFoundException(cluster.getClusterName(),
+              ServiceComponentHostNotFoundException e = new ServiceComponentHostNotFoundException(cluster.getClusterName(),
                 s.getName(), sc.getName(), request.getHostname());
+              throw e;
             }
 
             ServiceComponentHost sch = serviceComponentHostMap.get(request.getHostname());
@@ -779,9 +794,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
             response.add(r);
           } catch (ServiceComponentHostNotFoundException e) {
             if (request.getServiceName() != null && request.getComponentName() != null) {
+              LOG.error("ServiceComponentHost not found ", e);
               throw new ServiceComponentHostNotFoundException(cluster.getClusterName(),
                   request.getServiceName(), request.getComponentName(), request.getHostname());
             } else {
+              LOG.debug("Ignoring not specified host_component ", e);
               // ignore this since host_component was not specified
               // this is an artifact of how we get host_components and can happen
               // in case where we get all host_components for a host
@@ -2178,6 +2195,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   @Override
   public Set<ServiceComponentHostResponse> getHostComponents(
       Set<ServiceComponentHostRequest> requests) throws AmbariException {
+    LOG.debug("Processing requests: {}", requests);
     Set<ServiceComponentHostResponse> response =
         new HashSet<ServiceComponentHostResponse>();
     for (ServiceComponentHostRequest request : requests) {
@@ -2188,6 +2206,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           // only throw exception if 1 request.
           // there will be > 1 request in case of OR predicate
           throw e;
+        } else {
+          LOG.debug("Ignoring not found exception due to other requests", e);
         }
       } catch (ServiceNotFoundException e) {
         if (requests.size() == 1) {
@@ -2196,6 +2216,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           // In 'OR' case, a host_component may be included in predicate
           // that has no corresponding service
           throw e;
+        } else {
+          LOG.debug("Ignoring not found exception due to other requests", e);
         }
       } catch (ServiceComponentNotFoundException e) {
         if (requests.size() == 1) {
@@ -2204,6 +2226,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           // In 'OR' case, a host_component may be included in predicate
           // that has no corresponding component
           throw e;
+        } else {
+          LOG.debug("Ignoring not found exception due to other requests", e);
         }
       } catch (ParentObjectNotFoundException e) {
         // If there is only one request, always throw exception.
@@ -2217,6 +2241,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
             if (r.getHostname() == null) {
               // host_name provided in query since all requests don't have host_name set
               throwException = false;
+              LOG.debug("HostNotFoundException ignored", e);
               break;
             }
           }

+ 4 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java

@@ -24,7 +24,8 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.name.Names;
-import com.google.inject.persist.jpa.JpaPersistModule;
+import com.google.inject.persist.PersistModule;
+import com.google.inject.persist.jpa.AmbariJpaPersistModule;
 import org.apache.ambari.server.actionmanager.ActionDBAccessor;
 import org.apache.ambari.server.actionmanager.ActionDBAccessorImpl;
 import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
@@ -153,9 +154,9 @@ public class ControllerModule extends AbstractModule {
     requestStaticInjection(ExecutionCommandWrapper.class);
   }
 
-  private JpaPersistModule buildJpaPersistModule() {
+  private PersistModule buildJpaPersistModule() {
     PersistenceType persistenceType = configuration.getPersistenceType();
-    JpaPersistModule jpaPersistModule = new JpaPersistModule(Configuration.JDBC_UNIT_NAME);
+    AmbariJpaPersistModule jpaPersistModule = new AmbariJpaPersistModule(Configuration.JDBC_UNIT_NAME);
 
     Properties properties = new Properties();
 

+ 8 - 10
ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java

@@ -159,16 +159,14 @@ public class ServiceComponentHostRequest {
 
   public String toString() {
     StringBuilder sb = new StringBuilder();
-    sb.append("{"
-        + " clusterName=" + clusterName
-        + ", serviceName=" + serviceName
-        + ", componentName=" + componentName
-        + ", hostname=" + hostname
-        + ", desiredState=" + desiredState
-        + ", desiredStackId=" + desiredStackId
-        + ", staleConfig=" + staleConfig
-        + ", adminState=" + adminState
-        + "}");
+    sb.append("{" + " clusterName=").append(clusterName)
+      .append(", serviceName=").append(serviceName)
+      .append(", componentName=").append(componentName)
+      .append(", hostname=").append(hostname)
+      .append(", desiredState=").append(desiredState)
+      .append(", desiredStackId=").append(desiredStackId)
+      .append(", staleConfig=").append(staleConfig)
+      .append(", adminState=").append(adminState).append("}");
     return sb.toString();
   }
 

+ 160 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/AmbariJpaLocalTxnInterceptor.java

@@ -0,0 +1,160 @@
+/*
+ * 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;
+
+import com.google.inject.Inject;
+import com.google.inject.persist.Transactional;
+import com.google.inject.persist.UnitOfWork;
+import com.google.inject.persist.jpa.AmbariJpaPersistService;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import java.lang.reflect.Method;
+
+public class AmbariJpaLocalTxnInterceptor implements MethodInterceptor {
+
+  @Inject
+  private final AmbariJpaPersistService emProvider = null;
+
+  @Inject
+  private final UnitOfWork unitOfWork = null;
+
+  @Transactional
+  private static class Internal {}
+
+  // Tracks if the unit of work was begun implicitly by this transaction.
+  private final ThreadLocal<Boolean> didWeStartWork = new ThreadLocal<Boolean>();
+
+  public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+
+    // Should we start a unit of work?
+    if (!emProvider.isWorking()) {
+      emProvider.begin();
+      didWeStartWork.set(true);
+    }
+
+    Transactional transactional = readTransactionMetadata(methodInvocation);
+    EntityManager em = this.emProvider.get();
+
+    // Allow 'joining' of transactions if there is an enclosing @Transactional method.
+    if (em.getTransaction().isActive()) {
+      return methodInvocation.proceed();
+    }
+
+    final EntityTransaction txn = em.getTransaction();
+    txn.begin();
+
+    Object result;
+    try {
+      result = methodInvocation.proceed();
+
+    } catch (Exception e) {
+      //commit transaction only if rollback didnt occur
+      if (rollbackIfNecessary(transactional, e, txn)) {
+        txn.commit();
+      }
+
+      //propagate whatever exception is thrown anyway
+      throw e;
+    } finally {
+      // Close the em if necessary (guarded so this code doesn't run unless catch fired).
+      if (null != didWeStartWork.get() && !txn.isActive()) {
+        didWeStartWork.remove();
+        unitOfWork.end();
+      }
+    }
+
+    //everything was normal so commit the txn (do not move into try block above as it
+    //  interferes with the advised method's throwing semantics)
+    try {
+      txn.commit();
+    } finally {
+      //close the em if necessary
+      if (null != didWeStartWork.get() ) {
+        didWeStartWork.remove();
+        unitOfWork.end();
+      }
+    }
+
+    //or return result
+    return result;
+  }
+
+  // TODO Cache this method's results.
+  private Transactional readTransactionMetadata(MethodInvocation methodInvocation) {
+    Transactional transactional;
+    Method method = methodInvocation.getMethod();
+    Class<?> targetClass = methodInvocation.getThis().getClass();
+
+    transactional = method.getAnnotation(Transactional.class);
+    if (null == transactional) {
+      // If none on method, try the class.
+      transactional = targetClass.getAnnotation(Transactional.class);
+    }
+    if (null == transactional) {
+      // If there is no transactional annotation present, use the default
+      transactional = Internal.class.getAnnotation(Transactional.class);
+    }
+
+    return transactional;
+  }
+
+  /**
+   * Returns True if rollback DID NOT HAPPEN (i.e. if commit should continue).
+   *
+   * @param transactional The metadata annotaiton of the method
+   * @param e The exception to test for rollback
+   * @param txn A JPA Transaction to issue rollbacks on
+   */
+  private boolean rollbackIfNecessary(Transactional transactional, Exception e,
+                                      EntityTransaction txn) {
+    boolean commit = true;
+
+    //check rollback clauses
+    for (Class<? extends Exception> rollBackOn : transactional.rollbackOn()) {
+
+      //if one matched, try to perform a rollback
+      if (rollBackOn.isInstance(e)) {
+        commit = false;
+
+        //check ignore clauses (supercedes rollback clause)
+        for (Class<? extends Exception> exceptOn : transactional.ignore()) {
+          //An exception to the rollback clause was found, DON'T rollback
+          // (i.e. commit and throw anyway)
+          if (exceptOn.isInstance(e)) {
+            commit = true;
+            break;
+          }
+        }
+
+        //rollback only if nothing matched the ignore check
+        if (!commit) {
+          txn.rollback();
+        }
+        //otherwise continue to commit
+
+        break;
+      }
+    }
+
+    return commit;
+  }
+}

+ 60 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/AmbariLocalSessionInterceptor.java

@@ -0,0 +1,60 @@
+/**
+ * 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;
+
+
+import com.google.inject.Inject;
+import com.google.inject.persist.jpa.AmbariJpaPersistService;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * AOP interceptor to provide session borders
+ */
+public class AmbariLocalSessionInterceptor implements MethodInterceptor {
+
+  @Inject
+  private final AmbariJpaPersistService emProvider = null;
+
+  private final ThreadLocal<Boolean> didWeStartWork = new ThreadLocal<Boolean>();
+
+  @Override
+  public Object invoke(MethodInvocation invocation) throws Throwable {
+    if (!emProvider.isWorking()) {
+      emProvider.begin();
+      didWeStartWork.set(true);
+
+      try {
+        return invocation.proceed();
+      } finally {
+        if (null != didWeStartWork.get()) {
+          didWeStartWork.remove();
+          emProvider.end();
+        }
+      }
+
+    } else {
+      //if session was in progress just proceed without additional checks
+      return invocation.proceed();
+    }
+
+
+
+
+  }
+}

+ 39 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/RequiresSession.java

@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Any method or class marked with annotation treated as requiring Jpa session.
+ * Marking method with {@code @RequiresSession} will start session before method call and close after.
+ * If session already in progress it will be ignored.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface RequiresSession {
+
+}

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintDAO.java

@@ -23,6 +23,7 @@ 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.BlueprintEntity;
 
 import javax.persistence.EntityManager;
@@ -49,6 +50,7 @@ public class BlueprintDAO {
    *
    * @return  a matching blueprint or null
    */
+  @RequiresSession
   public BlueprintEntity findByName(String blueprint_name) {
     return entityManagerProvider.get().find(BlueprintEntity.class, blueprint_name);
   }
@@ -58,6 +60,7 @@ public class BlueprintDAO {
    *
    * @return all blueprints or an empty List
    */
+  @RequiresSession
   public List<BlueprintEntity> findAll() {
     TypedQuery<BlueprintEntity> query = entityManagerProvider.get().
         createNamedQuery("allBlueprints", BlueprintEntity.class);

+ 10 - 9
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterDAO.java

@@ -25,6 +25,7 @@ import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 
 import com.google.inject.Singleton;
+import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntityPK;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
@@ -44,12 +45,12 @@ public class ClusterDAO {
    * @param id ID of Cluster
    * @return Found entity or NULL
    */
-  @Transactional
+  @RequiresSession
   public ClusterEntity findById(long id) {
     return entityManagerProvider.get().find(ClusterEntity.class, id);
   }
 
-  @Transactional
+  @RequiresSession
   public ClusterEntity findByName(String clusterName) {
     TypedQuery<ClusterEntity> query = entityManagerProvider.get().createNamedQuery("clusterByName", ClusterEntity.class);
     query.setParameter("clusterName", clusterName);
@@ -60,7 +61,7 @@ public class ClusterDAO {
     }
   }
 
-  @Transactional
+  @RequiresSession
   public List<ClusterEntity> findAll() {
     TypedQuery<ClusterEntity> query = entityManagerProvider.get().createNamedQuery("allClusters", ClusterEntity.class);
     try {
@@ -70,6 +71,12 @@ public class ClusterDAO {
     return null;
   }
 
+  @RequiresSession
+  public ClusterConfigEntity findConfig(ClusterConfigEntityPK configEntityPK) {
+    return entityManagerProvider.get().find(ClusterConfigEntity.class,
+      configEntityPK);
+  }
+
   /**
    * Create Cluster entity in Database
    * @param clusterEntity entity to create
@@ -87,12 +94,6 @@ public class ClusterDAO {
     entityManagerProvider.get().persist(entity);
   }
 
-  @Transactional
-  public ClusterConfigEntity findConfig(ClusterConfigEntityPK configEntityPK) {
-    return entityManagerProvider.get().find(ClusterConfigEntity.class,
-      configEntityPK);
-  }
-
   /**
    * Retrieve entity data from DB
    * @param clusterEntity entity to refresh

+ 4 - 3
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java

@@ -22,6 +22,7 @@ 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.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
 
@@ -37,12 +38,12 @@ public class ClusterServiceDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public ClusterServiceEntity findByPK(ClusterServiceEntityPK clusterServiceEntityPK) {
     return entityManagerProvider.get().find(ClusterServiceEntity.class, clusterServiceEntityPK);
   }
 
-  @Transactional
+  @RequiresSession
   public ClusterServiceEntity findByClusterAndServiceNames(String  clusterName, String serviceName) {
     TypedQuery<ClusterServiceEntity> query = entityManagerProvider.get()
             .createNamedQuery("clusterServiceByClusterAndServiceNames", ClusterServiceEntity.class);
@@ -56,7 +57,7 @@ public class ClusterServiceDAO {
     }
   }
 
-  @Transactional
+  @RequiresSession
   public List<ClusterServiceEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ClusterServiceEntity.class);
   }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterStateDAO.java

@@ -22,6 +22,7 @@ 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.ClusterStateEntity;
 
 import javax.persistence.EntityManager;
@@ -34,12 +35,12 @@ public class ClusterStateDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public ClusterStateEntity findByPK(long clusterId) {
     return entityManagerProvider.get().find(ClusterStateEntity.class, clusterId);
   }
 
-  @Transactional
+  @RequiresSession
   public List<ClusterStateEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ClusterStateEntity.class);
   }

+ 4 - 3
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupConfigMappingDAO.java

@@ -21,6 +21,7 @@ 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.ConfigGroupConfigMappingEntity;
 import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntityPK;
 import javax.persistence.EntityManager;
@@ -35,14 +36,14 @@ public class ConfigGroupConfigMappingDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public ConfigGroupConfigMappingEntity findByPK
     (ConfigGroupConfigMappingEntityPK configGroupConfigMappingEntityPK) {
     return entityManagerProvider.get().find(ConfigGroupConfigMappingEntity.class,
       configGroupConfigMappingEntityPK);
   }
 
-  @Transactional
+  @RequiresSession
   public List<ConfigGroupConfigMappingEntity> findByGroup(Long groupId) {
     TypedQuery<ConfigGroupConfigMappingEntity> query = entityManagerProvider
       .get().createNamedQuery("configsByGroup", ConfigGroupConfigMappingEntity.class);
@@ -55,7 +56,7 @@ public class ConfigGroupConfigMappingDAO {
     return null;
   }
 
-  @Transactional
+  @RequiresSession
   public List<ConfigGroupConfigMappingEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ConfigGroupConfigMappingEntity.class);
   }

+ 22 - 20
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupDAO.java

@@ -21,6 +21,7 @@ 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.ConfigGroupEntity;
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
@@ -28,6 +29,7 @@ import javax.persistence.TypedQuery;
 import java.util.List;
 
 @Singleton
+@RequiresSession
 public class ConfigGroupDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
@@ -39,7 +41,7 @@ public class ConfigGroupDAO {
    * @param groupName
    * @return ConfigGroupEntity
    */
-  @Transactional
+  @RequiresSession
   public ConfigGroupEntity findByName(String groupName) {
     TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
       .createNamedQuery("configGroupByName", ConfigGroupEntity.class);
@@ -56,12 +58,12 @@ public class ConfigGroupDAO {
    * @param id
    * @return
    */
-  @Transactional
+  @RequiresSession
   public ConfigGroupEntity findById(Long id) {
     return entityManagerProvider.get().find(ConfigGroupEntity.class, id);
   }
 
-  @Transactional
+  @RequiresSession
   public List<ConfigGroupEntity> findAll() {
     TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
       .createNamedQuery("allConfigGroups", ConfigGroupEntity.class);
@@ -72,6 +74,23 @@ public class ConfigGroupDAO {
     return null;
   }
 
+  /**
+   * Find config groups by service name and so on
+   * @param tag
+   * @return
+   */
+  @RequiresSession
+  public List<ConfigGroupEntity> findAllByTag(String tag) {
+    TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
+      .createNamedQuery("configGroupsByTag", ConfigGroupEntity.class);
+    query.setParameter("tagName", tag);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
   @Transactional
   public void create(ConfigGroupEntity configGroupEntity) {
     entityManagerProvider.get().persist(configGroupEntity);
@@ -99,21 +118,4 @@ public class ConfigGroupDAO {
 
   // DAO methods on associated objects
 
-  /**
-   * Find config groups by service name and so on
-   * @param tag
-   * @return
-   */
-  @Transactional
-  public List<ConfigGroupEntity> findAllByTag(String tag) {
-    TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
-      .createNamedQuery("configGroupsByTag", ConfigGroupEntity.class);
-    query.setParameter("tagName", tag);
-    try {
-      return query.getResultList();
-    } catch (NoResultException ignored) {
-    }
-    return null;
-  }
-
 }

+ 5 - 5
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupHostMappingDAO.java

@@ -22,6 +22,7 @@ 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.cache.ConfigGroupHostMapping;
 import org.apache.ambari.server.orm.cache.ConfigGroupHostMappingImpl;
 import org.apache.ambari.server.orm.entities.ConfigGroupEntity;
@@ -45,7 +46,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -112,7 +112,7 @@ public class ConfigGroupHostMappingDAO {
    * @param configGroupHostMappingEntityPK
    * @return
    */
-  @Transactional
+  @RequiresSession
   public ConfigGroupHostMappingEntity findByPK(final ConfigGroupHostMappingEntityPK
         configGroupHostMappingEntityPK) {
     
@@ -120,7 +120,7 @@ public class ConfigGroupHostMappingDAO {
       .find(ConfigGroupHostMappingEntity.class, configGroupHostMappingEntityPK);
   }
 
-  @Transactional
+  @RequiresSession
   public Set<ConfigGroupHostMapping> findByHost(String hostname) {
     
     populateCache();
@@ -134,7 +134,7 @@ public class ConfigGroupHostMappingDAO {
     
   }
 
-  @Transactional
+  @RequiresSession
   public Set<ConfigGroupHostMapping> findByGroup(final Long groupId) {
     
     populateCache();
@@ -161,7 +161,7 @@ public class ConfigGroupHostMappingDAO {
     
   }
 
-  @Transactional
+  @RequiresSession
   public List<ConfigGroupHostMappingEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ConfigGroupHostMappingEntity.class);
   }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ExecutionCommandDAO.java

@@ -22,6 +22,7 @@ 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.ExecutionCommandEntity;
 
 import javax.persistence.EntityManager;
@@ -35,12 +36,12 @@ public class ExecutionCommandDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public ExecutionCommandEntity findByPK(long taskId) {
     return entityManagerProvider.get().find(ExecutionCommandEntity.class, taskId);
   }
 
-  @Transactional
+  @RequiresSession
   public List<ExecutionCommandEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ExecutionCommandEntity.class);
   }

+ 13 - 12
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentDesiredStateDAO.java

@@ -22,6 +22,7 @@ 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.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntityPK;
 
@@ -35,11 +36,22 @@ public class HostComponentDesiredStateDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
 
-  @Transactional
+  @RequiresSession
   public HostComponentDesiredStateEntity findByPK(HostComponentDesiredStateEntityPK primaryKey) {
     return entityManagerProvider.get().find(HostComponentDesiredStateEntity.class, primaryKey);
   }
 
+  @RequiresSession
+  public List<HostComponentDesiredStateEntity> findAll() {
+    TypedQuery<HostComponentDesiredStateEntity> query = entityManagerProvider.get()
+      .createQuery("SELECT hcd from HostComponentDesiredStateEntity hcd", HostComponentDesiredStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
   @Transactional
   public void refresh(HostComponentDesiredStateEntity hostComponentDesiredStateEntity) {
     entityManagerProvider.get().refresh(hostComponentDesiredStateEntity);
@@ -64,15 +76,4 @@ public class HostComponentDesiredStateDAO {
   public void removeByPK(HostComponentDesiredStateEntityPK primaryKey) {
     remove(findByPK(primaryKey));
   }
-
-  @Transactional
-  public List<HostComponentDesiredStateEntity> findAll() {
-    TypedQuery<HostComponentDesiredStateEntity> query = entityManagerProvider.get()
-      .createQuery("SELECT hcd from HostComponentDesiredStateEntity hcd", HostComponentDesiredStateEntity.class);
-    try {
-      return query.getResultList();
-    } catch (NoResultException ignored) {
-    }
-    return null;
-  }
 }

+ 13 - 12
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java

@@ -22,6 +22,7 @@ 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.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntityPK;
 
@@ -35,11 +36,22 @@ public class HostComponentStateDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
 
-  @Transactional
+  @RequiresSession
   public HostComponentStateEntity findByPK(HostComponentStateEntityPK primaryKey) {
     return entityManagerProvider.get().find(HostComponentStateEntity.class, primaryKey);
   }
 
+  @RequiresSession
+  public List<HostComponentStateEntity> findAll() {
+    TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get()
+      .createQuery("SELECT hsc from HostComponentStateEntity hsc", HostComponentStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
   @Transactional
   public void refresh(HostComponentStateEntity hostComponentStateEntity) {
     entityManagerProvider.get().refresh(hostComponentStateEntity);
@@ -64,15 +76,4 @@ public class HostComponentStateDAO {
   public void removeByPK(HostComponentStateEntityPK primaryKey) {
     remove(findByPK(primaryKey));
   }
-
-  @Transactional
-  public List<HostComponentStateEntity> findAll() {
-    TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get()
-      .createQuery("SELECT hsc from HostComponentStateEntity hsc", HostComponentStateEntity.class);
-    try {
-      return query.getResultList();
-    } catch (NoResultException ignored) {
-    }
-    return null;
-  }
 }

+ 7 - 7
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostConfigMappingDAO.java

@@ -18,7 +18,6 @@
 package org.apache.ambari.server.orm.dao;
 
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -27,6 +26,7 @@ import javax.persistence.TypedQuery;
 
 import com.google.inject.Singleton;
 
+import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.cache.HostConfigMapping;
 import org.apache.ambari.server.orm.cache.HostConfigMappingImpl;
 import org.apache.ambari.server.orm.entities.HostConfigMappingEntity;
@@ -134,7 +134,7 @@ public class HostConfigMappingDAO {
     return hostConfigMapping;
   }
 
-  @Transactional
+  @RequiresSession
   public Set<HostConfigMapping> findByType(final long clusterId, String hostName, final String type) {
     
     populateCache();
@@ -157,7 +157,7 @@ public class HostConfigMappingDAO {
     return set;
   }
 
-  @Transactional
+  @RequiresSession
   public HostConfigMapping findSelectedByType(final long clusterId,
       String hostName, final String type) {
     
@@ -184,7 +184,7 @@ public class HostConfigMappingDAO {
     
   }
 
-  @Transactional
+  @RequiresSession
   public Set<HostConfigMapping> findSelected(final long clusterId, String hostName) {
     
     populateCache();
@@ -207,7 +207,7 @@ public class HostConfigMappingDAO {
     return set;
   }
 
-  @Transactional
+  @RequiresSession
   public Set<HostConfigMapping> findSelectedByHosts(long clusterId, Collection<String> hostNames) {
     
     populateCache();
@@ -244,7 +244,7 @@ public class HostConfigMappingDAO {
   }
 
 
-  @Transactional
+  @RequiresSession
   public Map<String, List<HostConfigMapping>> findSelectedHostsByTypes(final long clusterId,
                                                                              Collection<String> types) {
     
@@ -282,7 +282,7 @@ public class HostConfigMappingDAO {
     return mappingsByType;
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostConfigMappingEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), HostConfigMappingEntity.class);
   }

+ 4 - 3
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostDAO.java

@@ -22,6 +22,7 @@ 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.HostEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
 
@@ -37,12 +38,12 @@ public class HostDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
 
-  @Transactional
+  @RequiresSession
   public HostEntity findByName(String hostName) {
     return entityManagerProvider.get().find(HostEntity.class, hostName);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostEntity> findAll() {
     TypedQuery<HostEntity> query = entityManagerProvider.get().createQuery("SELECT host FROM HostEntity host", HostEntity.class);
     try {
@@ -52,7 +53,7 @@ public class HostDAO {
     }
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostEntity> findByStage(StageEntity stageEntity) {
     TypedQuery<HostEntity> query = entityManagerProvider.get().createQuery(
         "SELECT host FROM HostEntity host " +

+ 75 - 74
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java

@@ -23,6 +23,7 @@ import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
@@ -48,12 +49,12 @@ public class HostRoleCommandDAO {
   private static Logger LOG = LoggerFactory.getLogger(HostRoleCommandDAO.class);
   private static final int REQUESTS_RESULT_LIMIT = 10;
 
-  @Transactional
+  @RequiresSession
   public HostRoleCommandEntity findByPK(long taskId) {
     return entityManagerProvider.get().find(HostRoleCommandEntity.class, taskId);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostRoleCommandEntity> findByPKs(Collection<Long> taskIds) {
     if (taskIds == null || taskIds.isEmpty()) {
       return Collections.emptyList();
@@ -65,7 +66,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, taskIds);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostRoleCommandEntity> findByRequestIds(Collection<Long> requestIds) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery(
         "SELECT task FROM HostRoleCommandEntity task " +
@@ -74,7 +75,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, requestIds);
   }
 
-  @Transactional
+  @RequiresSession
   public List<Long> findTaskIdsByRequestIds(Collection<Long> requestIds) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery(
         "SELECT task.taskId FROM HostRoleCommandEntity task " +
@@ -83,7 +84,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, requestIds);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostRoleCommandEntity> findByRequestAndTaskIds(Collection<Long> requestIds, Collection<Long> taskIds) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery(
         "SELECT DISTINCT task FROM HostRoleCommandEntity task " +
@@ -93,7 +94,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, requestIds, taskIds);
   }
 
-  @Transactional
+  @RequiresSession
   public List<Long> findTaskIdsByRequestAndTaskIds(Collection<Long> requestIds, Collection<Long> taskIds) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery(
         "SELECT DISTINCT task.taskId FROM HostRoleCommandEntity task " +
@@ -103,7 +104,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, requestIds, taskIds);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostRoleCommandEntity> findSortedCommandsByStageAndHost(StageEntity stageEntity, HostEntity hostEntity) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT hostRoleCommand " +
         "FROM HostRoleCommandEntity hostRoleCommand " +
@@ -112,7 +113,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, stageEntity, hostEntity);
   }
 
-  @Transactional
+  @RequiresSession
   public Map<String, List<HostRoleCommandEntity>> findSortedCommandsByStage(StageEntity stageEntity) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT hostRoleCommand " +
         "FROM HostRoleCommandEntity hostRoleCommand " +
@@ -133,7 +134,7 @@ public class HostRoleCommandDAO {
     return hostCommands;
   }
 
-  @Transactional
+  @RequiresSession
   public List<Long> findTaskIdsByStage(long requestId, long stageId) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT hostRoleCommand.taskId " +
         "FROM HostRoleCommandEntity hostRoleCommand " +
@@ -144,7 +145,7 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, requestId, stageId);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostRoleCommandEntity> findByHostRole(String hostName, long requestId, long stageId, String role) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
         "FROM HostRoleCommandEntity command " +
@@ -155,7 +156,28 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query, hostName, requestId, stageId, role);
   }
 
-  @Transactional
+  @RequiresSession
+  public List<HostRoleCommandEntity> findByRequest(long requestId) {
+    TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
+      "FROM HostRoleCommandEntity command " +
+      "WHERE command.requestId=?1 ORDER BY command.taskId", HostRoleCommandEntity.class);
+    return daoUtils.selectList(query, requestId);
+  }
+
+  @RequiresSession
+  public List<Long> findTaskIdsByRequest(long requestId) {
+    TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT command.taskId " +
+      "FROM HostRoleCommandEntity command " +
+      "WHERE command.requestId=?1 ORDER BY command.taskId", Long.class);
+    return daoUtils.selectList(query, requestId);
+  }
+
+  @RequiresSession
+  public List<HostRoleCommandEntity> findAll() {
+    return daoUtils.selectAll(entityManagerProvider.get(), HostRoleCommandEntity.class);
+  }
+
+  @RequiresSession
   public List<Long> getRequests() {
     String queryStr = "SELECT DISTINCT command.requestId " +
         "FROM HostRoleCommandEntity command ORDER BY command.requestId DESC";
@@ -165,6 +187,48 @@ public class HostRoleCommandDAO {
     return daoUtils.selectList(query);
   }
 
+  @RequiresSession
+  public List<Long> getRequestsByTaskStatus(
+    Collection<HostRoleStatus> statuses, boolean match, boolean checkAllTasks) {
+    List<Long> results = null;
+    StringBuilder queryStr = new StringBuilder();
+
+    queryStr.append("SELECT DISTINCT command.requestId ").append(
+      "FROM HostRoleCommandEntity command ");
+    if (statuses != null && !statuses.isEmpty()) {
+      queryStr.append("WHERE ");
+
+      if (checkAllTasks) {
+        queryStr.append("command.requestId ");
+        if (!match) {
+          queryStr.append("NOT ");
+        }
+        queryStr.append("IN (").append("SELECT c.requestId ")
+          .append("FROM HostRoleCommandEntity c ")
+          .append("WHERE c.requestId = command.requestId ")
+          .append("AND c.status IN ?1) ");
+      } else {
+        queryStr.append("command.status ");
+        if (!match) {
+          queryStr.append("NOT ");
+        }
+        queryStr.append("IN ?1 ");
+      }
+    }
+
+    queryStr.append("ORDER BY command.requestId DESC");
+    TypedQuery<Long> query = entityManagerProvider.get().createQuery(queryStr.toString(),
+      Long.class);
+    query.setMaxResults(REQUESTS_RESULT_LIMIT);
+
+    if (statuses != null && !statuses.isEmpty()) {
+      results = daoUtils.selectList(query, statuses);
+    } else {
+      results = daoUtils.selectList(query);
+    }
+    return results;
+  }
+
   @Transactional
   /**
    * NB: You cannot rely on return value if batch write is enabled
@@ -184,27 +248,6 @@ public class HostRoleCommandDAO {
     return commandEntities.size();
   }
 
-  @Transactional
-  public List<HostRoleCommandEntity> findByRequest(long requestId) {
-    TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
-        "FROM HostRoleCommandEntity command " +
-        "WHERE command.requestId=?1 ORDER BY command.taskId", HostRoleCommandEntity.class);
-    return daoUtils.selectList(query, requestId);
-  }
-  
-  @Transactional
-  public List<Long> findTaskIdsByRequest(long requestId) {
-    TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT command.taskId " +
-        "FROM HostRoleCommandEntity command " +
-        "WHERE command.requestId=?1 ORDER BY command.taskId", Long.class);
-    return daoUtils.selectList(query, requestId);
-  }
-
-  @Transactional
-  public List<HostRoleCommandEntity> findAll() {
-    return daoUtils.selectAll(entityManagerProvider.get(), HostRoleCommandEntity.class);
-  }
-
   @Transactional
   public void create(HostRoleCommandEntity stageEntity) {
     entityManagerProvider.get().persist(stageEntity);
@@ -235,46 +278,4 @@ public class HostRoleCommandDAO {
     remove(findByPK(taskId));
   }
 
-  @Transactional
-  public List<Long> getRequestsByTaskStatus(
-      Collection<HostRoleStatus> statuses, boolean match, boolean checkAllTasks) {
-    List<Long> results = null;
-    StringBuilder queryStr = new StringBuilder();
-
-    queryStr.append("SELECT DISTINCT command.requestId ").append(
-        "FROM HostRoleCommandEntity command ");
-    if (statuses != null && !statuses.isEmpty()) {
-      queryStr.append("WHERE ");
-
-      if (checkAllTasks) {
-        queryStr.append("command.requestId ");
-        if (!match) {
-          queryStr.append("NOT ");
-        }
-        queryStr.append("IN (").append("SELECT c.requestId ")
-            .append("FROM HostRoleCommandEntity c ")
-            .append("WHERE c.requestId = command.requestId ")
-            .append("AND c.status IN ?1) ");
-      } else {
-        queryStr.append("command.status ");
-        if (!match) {
-          queryStr.append("NOT ");
-        }
-        queryStr.append("IN ?1 ");
-      }
-    }
-
-    queryStr.append("ORDER BY command.requestId DESC");
-    TypedQuery<Long> query = entityManagerProvider.get().createQuery(queryStr.toString(),
-        Long.class);
-    query.setMaxResults(REQUESTS_RESULT_LIMIT);
-
-    if (statuses != null && !statuses.isEmpty()) {
-      results = daoUtils.selectList(query, statuses);
-    } else {
-      results = daoUtils.selectList(query);
-    }
-    return results;
-  }
-
 }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostStateDAO.java

@@ -22,6 +22,7 @@ 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.HostStateEntity;
 
 import javax.persistence.EntityManager;
@@ -34,12 +35,12 @@ public class HostStateDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public HostStateEntity findByHostName(String hostName) {
     return entityManagerProvider.get().find(HostStateEntity.class, hostName);
   }
 
-  @Transactional
+  @RequiresSession
   public List<HostStateEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), HostStateEntity.class);
   }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KeyValueDAO.java

@@ -22,6 +22,7 @@ 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.KeyValueEntity;
 
 import javax.persistence.EntityManager;
@@ -36,12 +37,12 @@ public class KeyValueDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public KeyValueEntity findByKey(String key) {
     return entityManagerProvider.get().find(KeyValueEntity.class, key);
   }
 
-  @Transactional
+  @RequiresSession
   public Collection<KeyValueEntity> findAll() {
     TypedQuery<KeyValueEntity> query =
         entityManagerProvider.get().createQuery("SELECT keyValue FROM KeyValueEntity keyValue", KeyValueEntity.class);

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MetainfoDAO.java

@@ -22,6 +22,7 @@ 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.MetainfoEntity;
 
 import javax.persistence.EntityManager;
@@ -36,12 +37,12 @@ public class MetainfoDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public MetainfoEntity findByKey(String key) {
     return entityManagerProvider.get().find(MetainfoEntity.class, key);
   }
 
-  @Transactional
+  @RequiresSession
   public Collection<MetainfoEntity> findAll() {
     TypedQuery<MetainfoEntity> query =
         entityManagerProvider.get().createQuery("SELECT metainfo FROM MetainfoEntity metainfo", MetainfoEntity.class);

+ 9 - 6
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestDAO.java

@@ -20,8 +20,10 @@ 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.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.orm.entities.RequestResourceFilterEntity;
 
@@ -30,35 +32,36 @@ import javax.persistence.TypedQuery;
 import java.util.Collection;
 import java.util.List;
 
+@Singleton
 public class RequestDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public RequestEntity findByPK(Long requestId) {
     return entityManagerProvider.get().find(RequestEntity.class, requestId);
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestEntity> findByPks(Collection<Long> requestIds) {
     TypedQuery<RequestEntity> query = entityManagerProvider.get().createQuery("SELECT request FROM RequestEntity request " +
         "WHERE request.requestId IN ?1", RequestEntity.class);
     return daoUtils.selectList(query, requestIds);
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), RequestEntity.class);
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestResourceFilterEntity> findAllResourceFilters() {
     return daoUtils.selectAll(entityManagerProvider.get(), RequestResourceFilterEntity.class);
   }
 
-  @Transactional
+  @RequiresSession
   public boolean isAllTasksCompleted(long requestId) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery(
         "SELECT task.taskId FROM HostRoleCommandEntity task WHERE task.requestId = ?1 AND " +
@@ -70,7 +73,7 @@ public class RequestDAO {
     return daoUtils.selectList(query, requestId, HostRoleStatus.getCompletedStates()).isEmpty();
   }
 
-  @Transactional
+  @RequiresSession
   public Long getLastStageId(long requestId) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT max(stage.stageId) " +
       "FROM StageEntity stage WHERE stage.requestId=?1", Long.class);

+ 4 - 3
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestScheduleBatchRequestDAO.java

@@ -21,6 +21,7 @@ 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.RequestScheduleBatchRequestEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntityPK;
 import javax.persistence.EntityManager;
@@ -35,7 +36,7 @@ public class RequestScheduleBatchRequestDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public RequestScheduleBatchRequestEntity findByPk
     (RequestScheduleBatchRequestEntityPK batchRequestEntity) {
 
@@ -43,7 +44,7 @@ public class RequestScheduleBatchRequestDAO {
       .find(RequestScheduleBatchRequestEntity.class, batchRequestEntity);
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestScheduleBatchRequestEntity> findByScheduleId(Long scheduleId) {
     TypedQuery<RequestScheduleBatchRequestEntity> query = entityManagerProvider
       .get().createNamedQuery("findByScheduleId",
@@ -57,7 +58,7 @@ public class RequestScheduleBatchRequestDAO {
     return null;
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestScheduleBatchRequestEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), RequestScheduleBatchRequestEntity.class);
   }

+ 4 - 3
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestScheduleDAO.java

@@ -21,6 +21,7 @@ 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.RequestScheduleEntity;
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
@@ -32,12 +33,12 @@ public class RequestScheduleDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
 
-  @Transactional
+  @RequiresSession
   public RequestScheduleEntity findById(Long id) {
     return entityManagerProvider.get().find(RequestScheduleEntity.class, id);
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestScheduleEntity> findByStatus(String status) {
     TypedQuery<RequestScheduleEntity> query = entityManagerProvider.get()
       .createNamedQuery("reqScheduleByStatus", RequestScheduleEntity.class);
@@ -49,7 +50,7 @@ public class RequestScheduleDAO {
     }
   }
 
-  @Transactional
+  @RequiresSession
   public List<RequestScheduleEntity> findAll() {
     TypedQuery<RequestScheduleEntity> query = entityManagerProvider.get()
       .createNamedQuery("allReqSchedules", RequestScheduleEntity.class);

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RoleDAO.java

@@ -21,6 +21,7 @@ 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.RoleEntity;
 
 import javax.persistence.EntityManager;
@@ -34,12 +35,12 @@ public class RoleDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public RoleEntity findByName(String roleName) {
     return entityManagerProvider.get().find(RoleEntity.class, roleName.toLowerCase());
   }
 
-  @Transactional
+  @RequiresSession
   public List<RoleEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), RoleEntity.class);
   }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RoleSuccessCriteriaDAO.java

@@ -22,6 +22,7 @@ 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.RoleSuccessCriteriaEntity;
 import org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntityPK;
 
@@ -36,13 +37,13 @@ public class RoleSuccessCriteriaDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public RoleSuccessCriteriaEntity findByPK(RoleSuccessCriteriaEntityPK roleSuccessCriteriaEntityPK) {
     entityManagerProvider.get().clear();
     return entityManagerProvider.get().find(RoleSuccessCriteriaEntity.class, roleSuccessCriteriaEntityPK);
   }
 
-  @Transactional
+  @RequiresSession
   public List<RoleSuccessCriteriaEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), RoleSuccessCriteriaEntity.class);
   }

+ 14 - 13
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java

@@ -22,6 +22,7 @@ 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.ServiceComponentDesiredStateEntityPK;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 
@@ -35,11 +36,23 @@ public class ServiceComponentDesiredStateDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
 
-  @Transactional
+  @RequiresSession
   public ServiceComponentDesiredStateEntity findByPK(ServiceComponentDesiredStateEntityPK primaryKey) {
     return entityManagerProvider.get().find(ServiceComponentDesiredStateEntity.class, primaryKey);
   }
 
+  @RequiresSession
+  public List<ServiceComponentDesiredStateEntity> findAll() {
+    TypedQuery<ServiceComponentDesiredStateEntity> query =
+      entityManagerProvider.get().
+        createQuery("SELECT scd from ServiceComponentDesiredStateEntity scd", ServiceComponentDesiredStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
   @Transactional
   public void refresh(ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity) {
     entityManagerProvider.get().refresh(serviceComponentDesiredStateEntity);
@@ -64,16 +77,4 @@ public class ServiceComponentDesiredStateDAO {
   public void removeByPK(ServiceComponentDesiredStateEntityPK primaryKey) {
     remove(findByPK(primaryKey));
   }
-
-  @Transactional
-  public List<ServiceComponentDesiredStateEntity> findAll() {
-    TypedQuery<ServiceComponentDesiredStateEntity> query =
-      entityManagerProvider.get().
-        createQuery("SELECT scd from ServiceComponentDesiredStateEntity scd", ServiceComponentDesiredStateEntity.class);
-    try {
-      return query.getResultList();
-    } catch (NoResultException ignored) {
-    }
-    return null;
-  }
 }

+ 14 - 13
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceDesiredStateDAO.java

@@ -22,6 +22,7 @@ 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.ServiceDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntityPK;
 
@@ -35,11 +36,23 @@ public class ServiceDesiredStateDAO {
   @Inject
   Provider<EntityManager> entityManagerProvider;
 
-  @Transactional
+  @RequiresSession
   public ServiceDesiredStateEntity findByPK(ServiceDesiredStateEntityPK primaryKey) {
     return entityManagerProvider.get().find(ServiceDesiredStateEntity.class, primaryKey);
   }
 
+  @RequiresSession
+  public List<ServiceDesiredStateEntity> findAll() {
+    TypedQuery<ServiceDesiredStateEntity> query =
+      entityManagerProvider.get().
+        createQuery("SELECT sd from ServiceDesiredStateEntity sd", ServiceDesiredStateEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
   @Transactional
   public void refresh(ServiceDesiredStateEntity serviceDesiredStateEntity) {
     entityManagerProvider.get().refresh(serviceDesiredStateEntity);
@@ -64,16 +77,4 @@ public class ServiceDesiredStateDAO {
   public void removeByPK(ServiceDesiredStateEntityPK primaryKey) {
     remove(findByPK(primaryKey));
   }
-
-  @Transactional
-  public List<ServiceDesiredStateEntity> findAll() {
-    TypedQuery<ServiceDesiredStateEntity> query =
-      entityManagerProvider.get().
-        createQuery("SELECT sd from ServiceDesiredStateEntity sd", ServiceDesiredStateEntity.class);
-    try {
-      return query.getResultList();
-    } catch (NoResultException ignored) {
-    }
-    return null;
-  }
 }

+ 29 - 28
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/StageDAO.java

@@ -23,6 +23,7 @@ import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.orm.entities.StageEntityPK;
 import org.apache.ambari.server.utils.StageUtils;
@@ -41,17 +42,17 @@ public class StageDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public StageEntity findByPK(StageEntityPK stageEntityPK) {
     return entityManagerProvider.get().find(StageEntity.class, stageEntityPK);
   }
 
-  @Transactional
+  @RequiresSession
   public List<StageEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), StageEntity.class);
   }
 
-  @Transactional
+  @RequiresSession
   public long getLastRequestId() {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT max(stage.requestId) FROM StageEntity stage", Long.class);
     Long result = daoUtils.selectSingle(query);
@@ -62,7 +63,7 @@ public class StageDAO {
     }
   }
 
-  @Transactional
+  @RequiresSession
   public StageEntity findByActionId(String actionId) {
     long[] ids = StageUtils.getRequestStage(actionId);
     StageEntityPK pk = new StageEntityPK();
@@ -71,7 +72,7 @@ public class StageDAO {
     return findByPK(pk);
   }
 
-  @Transactional
+  @RequiresSession
   public List<StageEntity> findByRequestId(long requestId) {
     TypedQuery<StageEntity> query = entityManagerProvider.get().createQuery("SELECT stage " +
         "FROM StageEntity stage " +
@@ -80,7 +81,7 @@ public class StageDAO {
     return daoUtils.selectList(query, requestId);
   }
 
-  @Transactional
+  @RequiresSession
   public List<StageEntity> findByCommandStatuses(Collection<HostRoleStatus> statuses) {
     TypedQuery<StageEntity> query = entityManagerProvider.get().createQuery("SELECT stage " +
           "FROM StageEntity stage WHERE stage.stageId IN (SELECT hrce.stageId FROM " +
@@ -89,27 +90,7 @@ public class StageDAO {
     return daoUtils.selectList(query, statuses);
   }
 
-  @Transactional
-  public void create(StageEntity stageEntity) {
-    entityManagerProvider.get().persist(stageEntity);
-  }
-
-  @Transactional
-  public StageEntity merge(StageEntity stageEntity) {
-    return entityManagerProvider.get().merge(stageEntity);
-  }
-
-  @Transactional
-  public void remove(StageEntity stageEntity) {
-    entityManagerProvider.get().remove(merge(stageEntity));
-  }
-
-  @Transactional
-  public void removeByPK(StageEntityPK stageEntityPK) {
-    remove(findByPK(stageEntityPK));
-  }
-
-  @Transactional
+  @RequiresSession
   public Map<Long, String> findRequestContext(List<Long> requestIds) {
     Map<Long, String> resultMap = new HashMap<Long, String>();
     if (requestIds != null && !requestIds.isEmpty()) {
@@ -127,7 +108,7 @@ public class StageDAO {
     return resultMap;
   }
 
-  @Transactional
+  @RequiresSession
   public String findRequestContext(long requestId) {
     TypedQuery<String> query = entityManagerProvider.get().createQuery(
       "SELECT stage.requestContext " + "FROM StageEntity stage " +
@@ -138,4 +119,24 @@ public class StageDAO {
     else
       return ""; // Since it is defined as empty string in the StageEntity
   }
+
+  @Transactional
+  public void create(StageEntity stageEntity) {
+    entityManagerProvider.get().persist(stageEntity);
+  }
+
+  @Transactional
+  public StageEntity merge(StageEntity stageEntity) {
+    return entityManagerProvider.get().merge(stageEntity);
+  }
+
+  @Transactional
+  public void remove(StageEntity stageEntity) {
+    entityManagerProvider.get().remove(merge(stageEntity));
+  }
+
+  @Transactional
+  public void removeByPK(StageEntityPK stageEntityPK) {
+    remove(findByPK(stageEntityPK));
+  }
 }

+ 7 - 6
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java

@@ -21,6 +21,7 @@ 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.UserEntity;
 
 import javax.persistence.EntityManager;
@@ -37,25 +38,25 @@ public class UserDAO {
   @Inject
   DaoUtils daoUtils;
 
-  @Transactional
+  @RequiresSession
   public UserEntity findByPK(Integer userPK) {
     return entityManagerProvider.get().find(UserEntity.class, userPK);
   }
 
-  @Transactional
+  @RequiresSession
   public List<UserEntity> findAll() {
     TypedQuery<UserEntity> query = entityManagerProvider.get().createQuery("SELECT user FROM UserEntity user", UserEntity.class);
     return daoUtils.selectList(query);
   }
 
-  @Transactional
+  @RequiresSession
   public List<UserEntity> findAllLocalUsersByRole(RoleEntity roleEntity) {
     TypedQuery<UserEntity> query = entityManagerProvider.get().createQuery("SELECT role.userEntities FROM RoleEntity role WHERE role = :roleEntity", UserEntity.class);
     query.setParameter("roleEntity", roleEntity);
     return query.getResultList();
   }
-  
-  @Transactional
+
+  @RequiresSession
   public UserEntity findLocalUserByName(String userName) {
     TypedQuery<UserEntity> query = entityManagerProvider.get().createNamedQuery("localUserByName", UserEntity.class);
     query.setParameter("username", userName.toLowerCase());
@@ -66,7 +67,7 @@ public class UserDAO {
     }
   }
 
-  @Transactional
+  @RequiresSession
   public UserEntity findLdapUserByName(String userName) {
     TypedQuery<UserEntity> query = entityManagerProvider.get().createNamedQuery("ldapUserByName", UserEntity.class);
     query.setParameter("username", userName.toLowerCase());

+ 2 - 1
ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java

@@ -39,6 +39,7 @@ import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntityPK;
 import org.apache.ambari.server.state.cluster.ClusterImpl;
+import org.apache.mina.util.CopyOnWriteMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -209,7 +210,7 @@ public class ServiceComponentImpl implements ServiceComponent {
     try {
       readWriteLock.readLock().lock();
       try {
-        return Collections.unmodifiableMap(hostComponents);
+        return new HashMap<String, ServiceComponentHost>(hostComponents);
       } finally {
         readWriteLock.readLock().unlock();
       }

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java

@@ -176,7 +176,7 @@ public class ServiceImpl implements Service {
     try {
       readWriteLock.readLock().lock();
       try {
-        return Collections.unmodifiableMap(components);
+        return new HashMap<String, ServiceComponent>(components);
       } finally {
         readWriteLock.readLock().unlock();
       }

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java

@@ -843,7 +843,7 @@ public class ClusterImpl implements Cluster {
     try {
       readLock.lock();
       try {
-        return Collections.unmodifiableMap(services);
+        return new HashMap<String, Service>(services);
       } finally {
         readLock.unlock();
       }

+ 2 - 2
ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java

@@ -27,7 +27,7 @@ import javax.ws.rs.core.MediaType;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
-import com.google.inject.persist.jpa.JpaPersistModule;
+import com.google.inject.persist.jpa.AmbariJpaPersistModule;
 
 import junit.framework.Assert;
 
@@ -265,7 +265,7 @@ public class AgentResourceTest extends JerseyTest {
     }
 
     private void installDependencies() {
-      install(new JpaPersistModule("ambari-javadb"));
+      install(new AmbariJpaPersistModule("ambari-javadb"));
       install(new FactoryModuleBuilder().implement(
           Cluster.class, ClusterImpl.class).build(ClusterFactory.class));
       install(new FactoryModuleBuilder().implement(

+ 6 - 0
ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java

@@ -21,6 +21,7 @@ package org.apache.ambari.server.orm;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
+import com.google.inject.persist.jpa.AmbariJpaPersistService;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.actionmanager.Stage;
@@ -243,12 +244,15 @@ public class TestOrmImpl extends Assert {
   @Test
   public void testConcurrentModification() throws InterruptedException {
     final ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+    final AmbariJpaPersistService ambariJpaPersistService = injector.getInstance(AmbariJpaPersistService.class);
     ClusterEntity clusterEntity = new ClusterEntity();
     clusterEntity.setClusterName("cluster1");
     clusterDAO.create(clusterEntity);
+//    assertFalse(ambariJpaPersistService.isWorking());
 
     clusterEntity = clusterDAO.findById(clusterEntity.getClusterId());
     assertEquals("cluster1", clusterEntity.getClusterName());
+//    assertFalse(ambariJpaPersistService.isWorking());
 
     Thread thread = new Thread(){
       @Override
@@ -256,6 +260,7 @@ public class TestOrmImpl extends Assert {
         ClusterEntity clusterEntity1 = clusterDAO.findByName("cluster1");
         clusterEntity1.setClusterName("anotherName");
         clusterDAO.merge(clusterEntity1);
+//        assertFalse(ambariJpaPersistService.isWorking());
       }
     };
 
@@ -263,6 +268,7 @@ public class TestOrmImpl extends Assert {
     thread.join();
 
     clusterEntity = clusterDAO.findById(clusterEntity.getClusterId());
+//    assertFalse(ambariJpaPersistService.isWorking());
     assertEquals("anotherName", clusterEntity.getClusterName());
 
     thread = new Thread(){

+ 0 - 2
ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java

@@ -20,9 +20,7 @@ package org.apache.ambari.server.security.authorization;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
-import com.google.inject.persist.jpa.JpaPersistModule;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
-import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.entities.UserEntity;