You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2016/09/16 13:57:54 UTC
[21/27] ambari git commit: AMBARI-18404 - Upgrade Summary Endpoint
Throws NPEs Due To JPA Cached Entities With Missing IDs (jonathanhurley)
AMBARI-18404 - Upgrade Summary Endpoint Throws NPEs Due To JPA Cached Entities With Missing IDs (jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/da560570
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/da560570
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/da560570
Branch: refs/heads/branch-dev-patch-upgrade
Commit: da5605706555d3aecca7a67fb399d9c501972ad4
Parents: 1efc99c
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Thu Sep 15 12:12:06 2016 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Thu Sep 15 23:57:36 2016 -0400
----------------------------------------------------------------------
.../actionmanager/ActionDBAccessorImpl.java | 14 +++++-----
.../server/actionmanager/HostRoleCommand.java | 16 +++++++++++
.../orm/entities/HostRoleCommandEntity.java | 19 +++++++++++++
.../ambari/server/topology/HostRequest.java | 25 ++++++++---------
.../actionmanager/TestActionDBAccessorImpl.java | 29 ++++++++++++++++++++
5 files changed, 82 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/da560570/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
index b7e7f2d..c31ca7e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
@@ -344,7 +344,6 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
StageEntity stageEntity = stage.constructNewPersistenceEntity();
stageEntities.add(stageEntity);
stageEntity.setClusterId(clusterId);
- //TODO refactor to reduce merges
stageEntity.setRequest(requestEntity);
stageDAO.create(stageEntity);
@@ -353,9 +352,6 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
for (HostRoleCommand hostRoleCommand : orderedHostRoleCommands) {
HostRoleCommandEntity hostRoleCommandEntity = hostRoleCommand.constructNewPersistenceEntity();
hostRoleCommandEntity.setStage(stageEntity);
-
- HostEntity hostEntity = null;
-
hostRoleCommandDAO.create(hostRoleCommandEntity);
assert hostRoleCommandEntity.getTaskId() != null;
@@ -365,6 +361,7 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
String output = "output-" + hostRoleCommandEntity.getTaskId() + ".txt";
String error = "errors-" + hostRoleCommandEntity.getTaskId() + ".txt";
+ HostEntity hostEntity = null;
if (null != hostRoleCommandEntity.getHostId()) {
hostEntity = hostDAO.findById(hostRoleCommandEntity.getHostId());
if (hostEntity == null) {
@@ -372,6 +369,7 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
LOG.error(msg);
throw new AmbariException(msg);
}
+
hostRoleCommandEntity.setHostEntity(hostEntity);
try {
@@ -401,9 +399,10 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
hostRoleCommandEntity.setExecutionCommand(executionCommandEntity);
executionCommandDAO.create(hostRoleCommandEntity.getExecutionCommand());
- hostRoleCommandDAO.merge(hostRoleCommandEntity);
+ hostRoleCommandEntity = hostRoleCommandDAO.merge(hostRoleCommandEntity);
+
if (null != hostEntity) {
- hostDAO.merge(hostEntity);
+ hostEntity = hostDAO.merge(hostEntity);
}
}
@@ -411,8 +410,9 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
roleSuccessCriteriaDAO.create(roleSuccessCriteriaEntity);
}
- stageDAO.create(stageEntity);
+ stageEntity = stageDAO.merge(stageEntity);
}
+
requestEntity.setStages(stageEntities);
requestDAO.merge(requestEntity);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/da560570/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
index ff2ce92..85c8e9f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/HostRoleCommand.java
@@ -209,6 +209,22 @@ public class HostRoleCommand {
hostRoleCommandEntity.setEvent(event.getEventJson());
+ // set IDs if the wrapping object has them - they are most likely
+ // non-updatable in JPA since they are retrieved from a relationship,
+ // however the JPA cache may choose to not refresh the entity so they would
+ // end up being null if not set before persisting the command entity
+ if (requestId >= 0) {
+ hostRoleCommandEntity.setRequestId(requestId);
+ }
+
+ if (stageId >= 0) {
+ hostRoleCommandEntity.setStageId(stageId);
+ }
+
+ if (taskId >= 0) {
+ hostRoleCommandEntity.setTaskId(taskId);
+ }
+
return hostRoleCommandEntity;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/da560570/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
index 6288091..74271b9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostRoleCommandEntity.java
@@ -511,8 +511,27 @@ public class HostRoleCommandEntity {
return stage;
}
+ /**
+ * Sets the associated {@link StageEntity} for this command. If the
+ * {@link StageEntity} has been persisted, then this will also set the
+ * commands stage and request ID fields.
+ *
+ * @param stage
+ */
public void setStage(StageEntity stage) {
this.stage = stage;
+
+ // ensure that the IDs are also set since they may not be retrieved from JPA
+ // when this entity is cached
+ if (null != stage) {
+ if (null == stageId) {
+ stageId = stage.getStageId();
+ }
+
+ if (null == requestId) {
+ requestId = stage.getRequestId();
+ }
+ }
}
public HostEntity getHostEntity() {
http://git-wip-us.apache.org/repos/asf/ambari/blob/da560570/ambari-server/src/main/java/org/apache/ambari/server/topology/HostRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostRequest.java
index c3b44b8..6a65b48 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostRequest.java
@@ -18,6 +18,17 @@
package org.apache.ambari.server.topology;
+import static org.apache.ambari.server.controller.internal.ProvisionAction.INSTALL_AND_START;
+import static org.apache.ambari.server.controller.internal.ProvisionAction.INSTALL_ONLY;
+import static org.apache.ambari.server.controller.internal.ProvisionAction.START_ONLY;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
import org.apache.ambari.server.actionmanager.HostRoleCommand;
import org.apache.ambari.server.api.predicate.InvalidQueryException;
import org.apache.ambari.server.api.predicate.PredicateCompiler;
@@ -37,17 +48,6 @@ import org.apache.ambari.server.state.host.HostImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.ambari.server.controller.internal.ProvisionAction.INSTALL_AND_START;
-import static org.apache.ambari.server.controller.internal.ProvisionAction.INSTALL_ONLY;
-import static org.apache.ambari.server.controller.internal.ProvisionAction.START_ONLY;
-
/**
* Represents a set of requests to a single host such as install, start, etc.
*/
@@ -355,9 +355,6 @@ public class HostRequest implements Comparable<HostRequest> {
for (HostRoleCommand task : logicalTasks.values()) {
HostRoleCommandEntity entity = task.constructNewPersistenceEntity();
// the above method doesn't set all of the fields for some unknown reason
- entity.setRequestId(task.getRequestId());
- entity.setStageId(task.getStageId());
- entity.setTaskId(task.getTaskId());
entity.setOutputLog(task.getOutputLog());
entity.setErrorLog(task.errorLog);
http://git-wip-us.apache.org/repos/asf/ambari/blob/da560570/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
index 0813dff..bf9d0db 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
+import javax.persistence.NamedQuery;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.Role;
@@ -611,6 +612,34 @@ public class TestActionDBAccessorImpl {
}
+ /**
+ * Tests that entities created int he {@link ActionDBAccessor} can be
+ * retrieved with their IDs intact. EclipseLink seems to execute the
+ * {@link NamedQuery} but then use its cached entities to fill in the data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testEntitiesCreatedWithIDs() throws Exception {
+ List<Stage> stages = new ArrayList<Stage>();
+ Stage stage = createStubStage(hostName, requestId, stageId);
+
+ stages.add(stage);
+
+ Request request = new Request(stages, clusters);
+
+ // persist entities
+ db.persistActions(request);
+
+ // query entities immediately to ensure IDs are populated
+ List<HostRoleCommandEntity> commandEntities = hostRoleCommandDAO.findByRequest(requestId);
+ Assert.assertEquals(2, commandEntities.size());
+
+ for (HostRoleCommandEntity entity : commandEntities) {
+ Assert.assertEquals(Long.valueOf(requestId), entity.getRequestId());
+ Assert.assertEquals(Long.valueOf(stageId), entity.getStageId());
+ }
+ }
private static class TestActionDBAccessorModule extends AbstractModule {
@Override