modules/core/dbutils/pom.xml
| 2
modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/OperationScheduleIdSetterUpgradeTask.java
| 60 ++++++++++
modules/core/dbutils/src/main/scripts/dbsetup/operation-schema.xml
| 19 +--
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
| 19 +++
modules/core/domain/src/main/java/org/rhq/core/domain/operation/GroupOperationScheduleEntity.java
| 2
modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationScheduleEntity.java
| 31 ++++-
modules/core/domain/src/main/java/org/rhq/core/domain/operation/ResourceOperationScheduleEntity.java
| 5
modules/core/domain/src/main/java/org/rhq/core/domain/operation/ScheduleJobId.java
| 6 -
modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java
| 9 +
modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/GroupOperationScheduleComposite.java
| 8 -
modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/OperationScheduleComposite.java
| 24 ++--
modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/ResourceOperationScheduleComposite.java
| 8 -
modules/core/domain/src/test/java/org/rhq/core/domain/operation/test/JobIdTest.java
| 7 +
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java
| 23 ++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationJob.java
| 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java
| 50 +++++++-
16 files changed, 220 insertions(+), 55 deletions(-)
New commits:
commit 28b070f78cac12c2c2f58194361133d3cc0b2e2d
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Fri Dec 17 15:52:12 2010 -0500
add ID field to RHQ_OPERATION_SCHEDULE and make it the primary key
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index c6bdebd..2d8d1fc 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.101</db.schema.version>
+ <db.schema.version>2.102</db.schema.version>
</properties>
<dependencies>
diff --git
a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/OperationScheduleIdSetterUpgradeTask.java
b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/OperationScheduleIdSetterUpgradeTask.java
new file mode 100644
index 0000000..58692c9
--- /dev/null
+++
b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/OperationScheduleIdSetterUpgradeTask.java
@@ -0,0 +1,60 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.core.db.upgrade;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.rhq.core.db.DatabaseType;
+
+/**
+ * Sets values on the id column for all rows in RHQ_OPERATION_SCHEDULE. The id's are
set, starting at 10001, in the
+ * order that the rows were created. This is done by parsing the value of the JOB_NAME
column, which includes the
+ * creation time.
+ *
+ * @author Ian Springer
+ */
+public class OperationScheduleIdSetterUpgradeTask implements DatabaseUpgradeTask {
+
+ @Override
+ public void execute(DatabaseType databaseType, Connection connection) throws
SQLException {
+ String selectSQL = "SELECT job_name FROM rhq_operation_schedule;";
+ System.out.println("Executing: " + selectSQL);
+ List<Object[]> results = databaseType.executeSelectSql(connection,
selectSQL);
+ Map<Long, String> sortedJobNames = new TreeMap<Long, String>();
+ for (Object[] result : results) {
+ String jobName = (String)result[0]; // e.g.:
rhq-resource-10001--121207376-1292542028679
+ // last portion is the job's creation time, e.g.: 1292542028679
+ Long ctime = Long.valueOf(jobName.substring(jobName.lastIndexOf('-')
+ 1));
+ sortedJobNames.put(ctime, jobName);
+ }
+ int id = 10001;
+ for (String jobName : sortedJobNames.values()) {
+ String updateSQL = "UPDATE rhq_operation_schedule SET id = " +
(id++) + " WHERE job_name = '" + jobName +
+ "';";
+ System.out.println("Executing: " + updateSQL);
+ databaseType.executeSql(connection, updateSQL);
+ }
+ }
+
+}
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/operation-schema.xml
b/modules/core/dbutils/src/main/scripts/dbsetup/operation-schema.xml
index 2e34094..68b3274 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/operation-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/operation-schema.xml
@@ -71,6 +71,8 @@
code special conditions into the session bean, we'll allow a short-lived NULL
next fire time row.
-->
<table name="RHQ_OPERATION_SCHEDULE">
+ <column name="ID" type="INTEGER" required="true"
default="sequence-only" initial="10001"
primarykey="true"/>
+
<column name="JOB_NAME" type="VARCHAR2"
required="true" size="100"/>
<column name="JOB_GROUP" type="VARCHAR2"
required="true" size="100"/>
<column name="DTYPE" type="VARCHAR2"
required="true" size="8"/>
@@ -83,16 +85,15 @@
<column name="GROUP_ID" type="INTEGER"
required="false" references="RHQ_RESOURCE_GROUP"/>
<!--
- Note that this is the same primary key that Quartz uses for its schedules
(RHQ_qrtz_job_details).
- We do not need to add DTYPE to the key, because we ensure the name/group are
unique
- across resource/group schedules
+ Note, this is the same as the primary key that Quartz uses for its schedules
(RHQ_QRTZ_JOB_DETAILS).
+ We do not need to add DTYPE to the key, because we ensure the name/group are
unique across resource/group
+ schedules
-->
- <constraint name="RHQ_OPERATION_SCHEDULE_KEY">
- <primaryKey>
- <field ref="JOB_NAME"/>
- <field ref="JOB_GROUP"/>
- </primaryKey>
- </constraint>
+ <!-- === business key (JOB_NAME + JOB_GROUP) === -->
+ <index name="RHQ_OPERATION_SCHEDULE_KEY_IDX"
unique="true">
+ <field ref="JOB_NAME"/>
+ <field ref="JOB_GROUP"/>
+ </index>
</table>
</dbsetup>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index d9f63c0..975c778 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -3277,6 +3277,25 @@
</schema-directSQL>
<schema-alterColumn table="RHQ_RESOURCE_TYPE"
column="DELETED" nullable="FALSE" />
</schemaSpec>
+
+ <schemaSpec version="2.102">
+ <!-- Create the ID column nullable. -->
+ <schema-addColumn table="RHQ_OPERATION_SCHEDULE"
column="ID" columnType="INTEGER" />
+ <!-- Set values for ID column on all existing rows. -->
+ <schema-javaTask
className="OperationScheduleIdSetterUpgradeTask" />
+ <!-- Now that all existing rows have IDs, switch the column to
non-nullable. -->
+ <schema-alterColumn table="RHQ_OPERATION_SCHEDULE"
column="ID" nullable="FALSE" />
+ <!-- Finally, make ID the primary key, rather than (JOB_NAME,
JOB_GROUP), and make
+ (JOB_NAME, JOB_GROUP) a unique index instead. -->
+ <schema-directSQL>
+ <statement desc="Changing primary key of
RHQ_OPERATION_SCHEDULE to ID...">
+ ALTER TABLE RHQ_OPERATION_SCHEDULE DROP CONSTRAINT
RHQ_OPERATION_SCHEDULE_KEY;
+ ALTER TABLE RHQ_OPERATION_SCHEDULE ADD PRIMARY KEY (ID);
+ CREATE UNIQUE INDEX RHQ_OPERATION_SCHEDULE_KEY_IDX ON
RHQ_OPERATION_SCHEDULE (JOB_NAME, JOB_GROUP);
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/GroupOperationScheduleEntity.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/GroupOperationScheduleEntity.java
index 39f85d2..3f545bd 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/GroupOperationScheduleEntity.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/GroupOperationScheduleEntity.java
@@ -36,6 +36,7 @@ import org.rhq.core.domain.resource.group.ResourceGroup;
@NamedQueries( { @NamedQuery(name = GroupOperationScheduleEntity.QUERY_FIND_BY_GROUP_ID,
query = "SELECT s "
+ " FROM GroupOperationScheduleEntity s " + " WHERE s.group.id =
:groupId ") })
public class GroupOperationScheduleEntity extends OperationScheduleEntity {
+
public static final String QUERY_FIND_BY_GROUP_ID =
"GroupOperationScheduleEntity.findByGroupId";
private static final long serialVersionUID = 1L;
@@ -68,4 +69,5 @@ public class GroupOperationScheduleEntity extends
OperationScheduleEntity {
str.append("]");
return str.toString();
}
+
}
\ No newline at end of file
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationScheduleEntity.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationScheduleEntity.java
index 7da39d1..6eea462 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationScheduleEntity.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationScheduleEntity.java
@@ -28,12 +28,14 @@ import java.util.Date;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
import javax.persistence.Id;
-import javax.persistence.IdClass;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
@@ -45,10 +47,8 @@ import javax.persistence.Table;
*
* @author John Mazzitelli
*/
-
@DiscriminatorColumn(name = "DTYPE")
@Entity
-(a)IdClass(ScheduleJobId.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NamedQueries( {
@NamedQuery(name = OperationScheduleEntity.QUERY_FIND_BY_JOB_ID, query = ""
//
@@ -58,6 +58,7 @@ import javax.persistence.Table;
+ " AND s.jobGroup = :jobGroup "),
@NamedQuery(name = OperationScheduleEntity.QUERY_GET_SCHEDULE_RESOURCE_ADMIN, query =
"" //
+ "SELECT DISTINCT new
org.rhq.core.domain.operation.composite.ResourceOperationScheduleComposite( "
+ + " ro.id, " //
+ " ro.jobName, " //
+ " ro.jobGroup, " //
+ " '', " //
@@ -69,6 +70,7 @@ import javax.persistence.Table;
+ " WHERE ro.nextFireTime IS NOT NULL "), //
@NamedQuery(name = OperationScheduleEntity.QUERY_GET_SCHEDULE_RESOURCE, query =
"" //
+ "SELECT DISTINCT new
org.rhq.core.domain.operation.composite.ResourceOperationScheduleComposite( "
+ + " ro.id, " //
+ " ro.jobName, " //
+ " ro.jobGroup, " //
+ " '', " //
@@ -84,6 +86,7 @@ import javax.persistence.Table;
+ " AND s = :subject "), //
@NamedQuery(name = OperationScheduleEntity.QUERY_GET_SCHEDULE_GROUP_ADMIN, query =
"" //
+ "SELECT DISTINCT new
org.rhq.core.domain.operation.composite.GroupOperationScheduleComposite( "
+ + " go.id, " //
+ " go.jobName, " //
+ " go.jobGroup, " //
+ " '', " //
@@ -95,6 +98,7 @@ import javax.persistence.Table;
+ " WHERE go.nextFireTime IS NOT NULL "), //
@NamedQuery(name = OperationScheduleEntity.QUERY_GET_SCHEDULE_GROUP, query =
"" //
+ "SELECT DISTINCT new
org.rhq.core.domain.operation.composite.GroupOperationScheduleComposite( "
+ + " go.id, " //
+ " go.jobName, " //
+ " go.jobGroup, " //
+ " '', " //
@@ -108,8 +112,10 @@ import javax.persistence.Table;
+ " JOIN r.subjects s " //
+ " WHERE go.nextFireTime IS NOT NULL " //
+ " AND s = :subject ") })
+@SequenceGenerator(name = "id", sequenceName =
"RHQ_OPERATION_SCHEDULE_ID_SEQ")
@Table(name = "RHQ_OPERATION_SCHEDULE")
public abstract class OperationScheduleEntity implements Serializable {
+
public static final String QUERY_FIND_BY_JOB_ID =
"OperationScheduleEntity.findByJobId";
public static final String QUERY_GET_SCHEDULE_RESOURCE =
"OperationScheduleEntity.getScheduleResource";
public static final String QUERY_GET_SCHEDULE_RESOURCE_ADMIN =
"OperationScheduleEntity.getScheduleResource_admin";
@@ -118,10 +124,15 @@ public abstract class OperationScheduleEntity implements
Serializable {
private static final long serialVersionUID = 1L;
+ @Column(name = "ID", nullable = false)
+ @GeneratedValue(strategy = GenerationType.AUTO, generator = "id")
@Id
+ private int id;
+
+ @Column(name = "JOB_NAME", nullable = false)
private String jobName;
- @Id
+ @Column(name = "JOB_GROUP", nullable = false)
private String jobGroup;
@Column(name = "NEXT_FIRE_TIME", nullable = true)
@@ -136,6 +147,10 @@ public abstract class OperationScheduleEntity implements Serializable
{
this.nextFireTime = (nextFireTime == null) ? null : nextFireTime.getTime();
}
+ public int getId() {
+ return id;
+ }
+
/**
* The single job ID which identifies this specific schedule. It can later be parsed
via
* {@link ScheduleJobId#ScheduleJobId(String)}.
@@ -184,9 +199,10 @@ public abstract class OperationScheduleEntity implements Serializable
{
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
- buf.append("job-name=[" + jobName);
- buf.append("], job-group=[" + jobGroup);
- buf.append("], next-fire-time=[" + ((nextFireTime == null) ?
"never" : new Date(nextFireTime)));
+ buf.append("id=" + id);
+ buf.append(", jobName=" + jobName);
+ buf.append(", jobGroup=" + jobGroup);
+ buf.append(", nextFireTime=" + ((nextFireTime == null) ?
"never" : new Date(nextFireTime)));
return buf.toString();
}
@@ -210,4 +226,5 @@ public abstract class OperationScheduleEntity implements Serializable
{
return this.getJobId().equals(other.getJobId());
}
+
}
\ No newline at end of file
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ResourceOperationScheduleEntity.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ResourceOperationScheduleEntity.java
index b7be10a..46dc63e 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ResourceOperationScheduleEntity.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ResourceOperationScheduleEntity.java
@@ -34,11 +34,10 @@ import javax.persistence.NamedQuery;
import org.rhq.core.domain.resource.Resource;
/**
- * Information on a specific operation schedule on a particular resource.
+ * Information on a specific operation schedule on a particular Resource.
*
* @author John Mazzitelli
*/
-
@DiscriminatorValue("resource")
@Entity
@NamedQueries( {
@@ -47,6 +46,7 @@ import org.rhq.core.domain.resource.Resource;
@NamedQuery(name = ResourceOperationScheduleEntity.QUERY_DELETE_BY_RESOURCES, query =
"DELETE FROM ResourceOperationScheduleEntity s "
+ " WHERE s.resource.id IN ( :resourceIds ) )") })
public class ResourceOperationScheduleEntity extends OperationScheduleEntity {
+
public static final String QUERY_DELETE_BY_RESOURCES =
"ResourceOperationScheduleEntity.QUERY_DELETE_BY_RESOURCES";
public static final String QUERY_FIND_BY_RESOURCE_ID =
"ResourceOperationScheduleEntity.findByResourceId";
@@ -80,4 +80,5 @@ public class ResourceOperationScheduleEntity extends
OperationScheduleEntity {
str.append("]");
return str.toString();
}
+
}
\ No newline at end of file
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ScheduleJobId.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ScheduleJobId.java
index 0d29a76..bc6641b 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ScheduleJobId.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/ScheduleJobId.java
@@ -23,8 +23,10 @@
package org.rhq.core.domain.operation;
/**
- * This class is a mutable version of {@link JobId} and is used as the primary key to
the
- * {@link OperationScheduleEntity} entities.
+ * This class is a mutable version of {@link JobId}, which represents the unique
identifier of the Quartz job
+ * for a scheduled RHQ operation.
+ *
+ * NOTE: It is no longer used as the primary key to the {@link OperationScheduleEntity}
entities.
*
* @author John Mazzitelli
*/
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java
index c638b31..70f6a36 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/bean/OperationSchedule.java
@@ -41,6 +41,7 @@ import org.rhq.core.domain.operation.JobId;
public abstract class OperationSchedule implements Serializable {
private static final long serialVersionUID = 1L;
+ private int id;
private String jobName;
private String jobGroup;
private String operationName;
@@ -53,6 +54,14 @@ public abstract class OperationSchedule implements Serializable {
public OperationSchedule() {
}
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
public String getJobGroup() {
return jobGroup;
}
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/GroupOperationScheduleComposite.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/GroupOperationScheduleComposite.java
index b5fba55..1107b06 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/GroupOperationScheduleComposite.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/GroupOperationScheduleComposite.java
@@ -22,8 +22,6 @@
*/
package org.rhq.core.domain.operation.composite;
-import org.rhq.core.domain.operation.ScheduleJobId;
-
/**
* Provides some information on a compatible group's scheduled operation.
*
@@ -31,15 +29,15 @@ import org.rhq.core.domain.operation.ScheduleJobId;
*/
public class GroupOperationScheduleComposite extends OperationScheduleComposite {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 2L;
private final int groupId;
private final String groupName;
private final String groupResourceTypeName;
- public GroupOperationScheduleComposite(String jobName, String jobGroup, String
operationName,
+ public GroupOperationScheduleComposite(int id, String jobName, String jobGroup,
String operationName,
long operationNextFireTime, int groupId, String groupName, String
groupResourceTypeName) {
- super(new ScheduleJobId(jobName, jobGroup), operationName,
operationNextFireTime);
+ super(id, jobName, jobGroup, operationName, operationNextFireTime);
this.groupId = groupId;
this.groupName = groupName;
this.groupResourceTypeName = groupResourceTypeName;
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/OperationScheduleComposite.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/OperationScheduleComposite.java
index dc99113..f80811a 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/OperationScheduleComposite.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/OperationScheduleComposite.java
@@ -25,31 +25,37 @@ package org.rhq.core.domain.operation.composite;
import java.io.Serializable;
import java.util.Date;
-import org.rhq.core.domain.operation.ScheduleJobId;
+import org.rhq.core.domain.operation.JobId;
public abstract class OperationScheduleComposite implements Serializable {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 2L;
- private ScheduleJobId operationJobId;
+ private int id;
+ private JobId jobId;
private String operationName;
private long operationNextFireTime;
//no args constructor for serialization purposes not to be used.
protected OperationScheduleComposite() {
this.operationNextFireTime = -1;
- this.operationJobId = null;
+ this.id = 0;
this.operationName = "(uninitialized)";
}
- public OperationScheduleComposite(ScheduleJobId operationJobId, String operationName,
long operationNextFireTime) {
- this.operationJobId = operationJobId;
+ public OperationScheduleComposite(int id, String jobName, String jobGroup, String
operationName, long operationNextFireTime) {
+ this.id = id;
+ this.jobId = new JobId(jobName, jobGroup);
this.operationName = operationName;
this.operationNextFireTime = operationNextFireTime;
}
- public ScheduleJobId getOperationJobId() {
- return operationJobId;
+ public int getId() {
+ return id;
+ }
+
+ public JobId getJobId() {
+ return jobId;
}
public String getOperationName() {
@@ -72,7 +78,7 @@ public abstract class OperationScheduleComposite implements Serializable
{
@Override
public String toString() {
StringBuilder str = new StringBuilder();
- str.append("operation-job-id=[" + operationJobId);
+ str.append("operation-job-id=[" + id);
str.append("], operation-name=[" + operationName);
str.append("], operation-next-fire-time=[" + new
Date(operationNextFireTime));
str.append("]");
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/ResourceOperationScheduleComposite.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/ResourceOperationScheduleComposite.java
index a0996a7..7ddd0d1 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/ResourceOperationScheduleComposite.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/composite/ResourceOperationScheduleComposite.java
@@ -22,11 +22,9 @@
*/
package org.rhq.core.domain.operation.composite;
-import org.rhq.core.domain.operation.ScheduleJobId;
-
public class ResourceOperationScheduleComposite extends OperationScheduleComposite {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 2L;
private int resourceId;
private String resourceName;
@@ -40,9 +38,9 @@ public class ResourceOperationScheduleComposite extends
OperationScheduleComposi
this.resourceId = 0;
}
- public ResourceOperationScheduleComposite(String jobName, String jobGroup, String
operationName,
+ public ResourceOperationScheduleComposite(int id, String jobName, String jobGroup,
String operationName,
long operationNextFireTime, int resourceId, String resourceName, String
resourceTypeName) {
- super(new ScheduleJobId(jobName, jobGroup), operationName,
operationNextFireTime);
+ super(id, jobName, jobGroup, operationName, operationNextFireTime);
this.resourceId = resourceId;
this.resourceName = resourceName;
this.resourceTypeName = resourceTypeName;
diff --git
a/modules/core/domain/src/test/java/org/rhq/core/domain/operation/test/JobIdTest.java
b/modules/core/domain/src/test/java/org/rhq/core/domain/operation/test/JobIdTest.java
index 48ff284..8cb8ca7 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/operation/test/JobIdTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/operation/test/JobIdTest.java
@@ -22,13 +22,17 @@
*/
package org.rhq.core.domain.operation.test;
+import org.rhq.core.domain.operation.ScheduleJobId;
import org.testng.annotations.Test;
import org.rhq.core.domain.operation.HistoryJobId;
import org.rhq.core.domain.operation.JobId;
-import org.rhq.core.domain.operation.ScheduleJobId;
+ /**
+ * Test the equals() and hashCode() methods on {@link JobId}, {@link HistoryJobId}, and
{@link ScheduleJobId}.
+ */
@Test
public class JobIdTest {
+
public void testJobIdEquals() {
JobId one;
JobId two;
@@ -170,4 +174,5 @@ public class JobIdTest {
assert !one.equals(two);
assert one.hashCode() != two.hashCode();
}
+
}
\ No newline at end of file
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java
index 65fe51f..06e68e5 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/OperationScheduleDataSource.java
@@ -23,6 +23,7 @@ import java.util.List;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.data.Record;
+import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
@@ -40,6 +41,7 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
public abstract class OperationScheduleDataSource<T extends OperationSchedule>
extends RPCDataSource<T> {
public static abstract class Field {
+ public static final String ID = "id";
public static final String JOB_NAME = "jobName";
public static final String JOB_GROUP = "jobGroup";
public static final String OPERATION_NAME = "operationName";
@@ -63,6 +65,11 @@ public abstract class OperationScheduleDataSource<T extends
OperationSchedule> e
protected List<DataSourceField> addDataSourceFields() {
List<DataSourceField> fields = super.addDataSourceFields();
+ DataSourceIntegerField idField = new DataSourceIntegerField(Field.ID,
"ID");
+ idField.setPrimaryKey(true);
+ idField.setCanEdit(false);
+ fields.add(idField);
+
DataSourceTextField operationDisplayNameField =
createTextField(Field.OPERATION_DISPLAY_NAME, "Operation", null, 100, true);
fields.add(operationDisplayNameField);
@@ -84,14 +91,15 @@ public abstract class OperationScheduleDataSource<T extends
OperationSchedule> e
public T copyValues(Record from) {
T to = createOperationSchedule();
+ to.setId(from.getAttributeAsInt(Field.ID));
to.setJobName(from.getAttribute(Field.JOB_NAME));
to.setJobGroup(from.getAttribute(Field.JOB_GROUP));
to.setJobTrigger((JobTrigger)from.getAttributeAsObject(Field.JOB_TRIGGER));
- to.setDescription(from.getAttribute(Field.DESCRIPTION));
- to.setOperationDisplayName(from.getAttribute(Field.OPERATION_DISPLAY_NAME));
- to.setOperationName(from.getAttribute(Field.OPERATION_NAME));
- to.setParameters((Configuration)from.getAttributeAsObject(Field.PARAMETERS));
to.setSubject((Subject)from.getAttributeAsObject(Field.SUBJECT));
+ to.setParameters((Configuration)from.getAttributeAsObject(Field.PARAMETERS));
+ to.setOperationName(from.getAttribute(Field.OPERATION_NAME));
+ to.setOperationDisplayName(from.getAttribute(Field.OPERATION_DISPLAY_NAME));
+ to.setDescription(from.getAttribute(Field.DESCRIPTION));
return to;
}
@@ -100,14 +108,15 @@ public abstract class OperationScheduleDataSource<T extends
OperationSchedule> e
public ListGridRecord copyValues(T from) {
ListGridRecord to = new ListGridRecord();
+ to.setAttribute(Field.ID, from.getId());
to.setAttribute(Field.JOB_NAME, from.getJobName());
to.setAttribute(Field.JOB_GROUP, from.getJobGroup());
to.setAttribute(Field.JOB_TRIGGER, from.getJobTrigger());
- to.setAttribute(Field.OPERATION_DISPLAY_NAME, from.getOperationDisplayName());
- to.setAttribute(Field.OPERATION_NAME, from.getOperationName());
to.setAttribute(Field.SUBJECT, from.getSubject());
- to.setAttribute(Field.DESCRIPTION, from.getDescription());
to.setAttribute(Field.PARAMETERS, from.getParameters());
+ to.setAttribute(Field.OPERATION_NAME, from.getOperationName());
+ to.setAttribute(Field.OPERATION_DISPLAY_NAME, from.getOperationDisplayName());
+ to.setAttribute(Field.DESCRIPTION, from.getDescription());
return to;
}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationJob.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationJob.java
index f5988e3..db58484 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationJob.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationJob.java
@@ -39,6 +39,8 @@ public abstract class OperationJob implements Job {
public static final String DATAMAP_STRING_OPERATION_DISPLAY_NAME =
"operationDisplayName";
public static final String DATAMAP_INT_PARAMETERS_ID = "parametersId"; //
the configuration ID
public static final String DATAMAP_INT_SUBJECT_ID = "subjectId";
+ // id of the associated OperationScheduleEntity - may be null for jobs created prior
to upgrading to RHQ 4.0
+ public static final String DATAMAP_INT_ENTITY_ID = "entityId";
/**
* For security purposes, we need to provide a subject with a valid login session.
This creates such a subject by
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java
index a1fc704..5d62695 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java
@@ -203,13 +203,16 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
trigger.setJobName(jobDetail.getName());
trigger.setJobGroup(jobDetail.getGroup());
- // we need to create our own schedule tracking entity
+ // We need to create our own schedule tracking entity.
ResourceOperationScheduleEntity schedule;
schedule = new ResourceOperationScheduleEntity(jobDetail.getName(),
jobDetail.getGroup(), trigger
.getStartTime(), resource);
entityManager.persist(schedule);
- // now actually schedule it
+ // Add the id of the entity bean, so we can easily map the Quartz job to the
associated entity bean.
+ jobDataMap.put(ResourceOperationJob.DATAMAP_INT_ENTITY_ID,
String.valueOf(schedule.getId()));
+
+ // Now actually schedule it.
Date next = scheduler.scheduleJob(jobDetail, trigger);
ResourceOperationSchedule newSchedule = getResourceOperationSchedule(subject,
jobDetail);
@@ -283,6 +286,9 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
group);
entityManager.persist(schedule);
+ // Add the id of the entity bean, so we can easily map the Quartz job to the
associated entity bean.
+ jobDataMap.put(ResourceOperationJob.DATAMAP_INT_ENTITY_ID,
String.valueOf(schedule.getId()));
+
// now actually schedule it
Date next = scheduler.scheduleJob(jobDetail, trigger);
GroupOperationSchedule newSchedule = getGroupOperationSchedule(subject,
jobDetail);
@@ -424,6 +430,8 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
public ResourceOperationSchedule getResourceOperationSchedule(Subject whoami,
JobDetail jobDetail) {
JobDataMap jobDataMap = jobDetail.getJobDataMap();
+ String jobName = jobDetail.getName();
+ String jobGroup = jobDetail.getGroup();
String description = jobDetail.getDescription();
String operationName =
jobDataMap.getString(ResourceOperationJob.DATAMAP_STRING_OPERATION_NAME);
String displayName =
jobDataMap.getString(ResourceOperationJob.DATAMAP_STRING_OPERATION_DISPLAY_NAME);
@@ -438,6 +446,8 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
int resourceId =
jobDataMap.getIntFromString(ResourceOperationJob.DATAMAP_INT_RESOURCE_ID);
Resource resource = getResourceIfAuthorized(whoami, resourceId);
+ Integer entityId = getOperationScheduleEntityId(jobDetail);
+
// note that we throw an exception if the subject does not exist!
// this is by design to avoid a malicious user creating a dummy subject in the
database,
// scheduling a very bad operation, and deleting that subject thus removing all
traces
@@ -445,8 +455,9 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
// will need to be deleted and rescheduled.
ResourceOperationSchedule sched = new ResourceOperationSchedule();
- sched.setJobName(jobDetail.getName());
- sched.setJobGroup(jobDetail.getGroup());
+ sched.setId(entityId);
+ sched.setJobName(jobName);
+ sched.setJobGroup(jobGroup);
sched.setResource(resource);
sched.setOperationName(operationName);
sched.setOperationDisplayName(displayName);
@@ -461,6 +472,25 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
return sched;
}
+ private int getOperationScheduleEntityId(JobDetail jobDetail) {
+ JobDataMap jobDataMap = jobDetail.getJobDataMap();
+ Object entityIdObj = jobDataMap.get(ResourceOperationJob.DATAMAP_INT_ENTITY_ID);
+ int entityId;
+ if (entityIdObj != null) {
+ // for jobs created using RHQ 4.0 or later, the map will contain an entityId
entry
+ entityId = Integer.valueOf((String)entityIdObj);
+ } else {
+ // for jobs created prior to upgrading to RHQ 4.0, the map will not contain
an entityId entry,
+ // so we'll need to lookup the entity id from the DB.
+ String jobName = jobDetail.getName();
+ String jobGroup = jobDetail.getGroup();
+ ScheduleJobId jobId = new ScheduleJobId(jobName, jobGroup);
+ OperationScheduleEntity operationScheduleEntity =
findOperationScheduleEntity(jobId);
+ entityId = operationScheduleEntity.getId();
+ }
+ return entityId;
+ }
+
public ResourceOperationSchedule getResourceOperationSchedule(Subject subject, String
jobId)
throws SchedulerException {
JobId jobIdObject = new JobId(jobId);
@@ -1430,7 +1460,7 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
Subject overlord = subjectManager.getOverlord();
for (ResourceOperationScheduleComposite composite : results) {
try {
- ResourceOperationSchedule sched = getResourceOperationSchedule(subject,
composite.getOperationJobId()
+ ResourceOperationSchedule sched = getResourceOperationSchedule(subject,
composite.getJobId()
.toString());
OperationDefinition def = getSupportedResourceOperation(overlord,
composite.getResourceId(), sched
.getOperationName(), false);
@@ -1484,7 +1514,7 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
Subject overlord = subjectManager.getOverlord();
for (GroupOperationScheduleComposite composite : results) {
try {
- GroupOperationSchedule sched = getGroupOperationSchedule(subject,
composite.getOperationJobId()
+ GroupOperationSchedule sched = getGroupOperationSchedule(subject,
composite.getJobId()
.toString());
OperationDefinition def = getSupportedGroupOperation(overlord,
composite.getGroupId(), sched
.getOperationName(), false);
@@ -1765,7 +1795,13 @@ public class OperationManagerBean implements OperationManagerLocal,
OperationMan
*/
private OperationScheduleEntity findOperationScheduleEntity(ScheduleJobId jobId) {
OperationScheduleEntity entity =
entityManager.find(OperationScheduleEntity.class, jobId);
- return entity;
+ Query query =
entityManager.createNamedQuery(OperationScheduleEntity.QUERY_FIND_BY_JOB_ID);
+ String jobName = jobId.getJobName();
+ query.setParameter("jobName", jobName);
+ String jobGroup = jobId.getJobGroup();
+ query.setParameter("jobGroup", jobGroup);
+ OperationScheduleEntity operationScheduleEntity =
(OperationScheduleEntity)query.getSingleResult();
+ return operationScheduleEntity;
}
public GroupOperationSchedule scheduleGroupOperation(Subject subject, int groupId,
int[] executionOrderResourceIds,