소스 검색

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

Siddharth Wagle 11 년 전
부모
커밋
fae3fa56d4
39개의 변경된 파일807개의 추가작업 그리고 256개의 파일을 삭제
  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;