@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ResourceConfigurationUpdate persistResourceConfigurationUpdateInNewTransaction(Subject subject,
int resourceId, Configuration newConfiguration, ConfigurationUpdateStatus newStatus, String newSubject,
boolean isPartofGroupUpdate) throws ResourceNotFoundException, ConfigurationUpdateStillInProgressException {
ResourceConfigurationUpdate current = null;
String errorMessage = null;
// for efficiency, in one query fetch IN_PROGRESS and/or the current update
Query query = entityManager
.createNamedQuery(ResourceConfigurationUpdate.QUERY_FIND_CURRENT_AND_IN_PROGRESS_CONFIGS);
query.setParameter("resourceId", resourceId);
List<?> updates = query.getResultList();
for (Object result : updates) {
current = (ResourceConfigurationUpdate) result;
if (ConfigurationUpdateStatus.INPROGRESS == current.getStatus()) {
// A previous update is still in progress for this Resource. If this update is part of a group
// update, persist it with FAILURE status, so it is still listed as part of the group history.
// Otherwise, throw an exception that can bubble up to the GUI.
if (isPartofGroupUpdate) {
newStatus = ConfigurationUpdateStatus.FAILURE;
errorMessage = "Resource configuration Update was aborted because an update request for the Resource was already in progress.";
} else {
// NOTE: If you change this to another exception, make sure you change getLatestResourceConfigurationUpdate().
throw new ConfigurationUpdateStillInProgressException(
"Resource ["
+ resourceId
+ "] has a resource configuration update request already in progress - please wait for it to finish: "
+ current);
}
}
}
Resource resource = null;
if (null != current) {
// Always persist a group update because each member must have an update. Otherwise, only persist a
// single resource update if it has changed.
if (!isPartofGroupUpdate) {
Configuration currentConfiguration = current.getConfiguration();
Hibernate.initialize(currentConfiguration.getMap());
if (currentConfiguration.equals(newConfiguration)) {
return null;
}
}
resource = current.getResource();
} else {
// make sure the resource exists
resource = resourceManager.getResourceById(subject, resourceId);
}
Configuration zeroedConfiguration = newConfiguration.deepCopyWithoutProxies();
// create our new update request and assign it to our resource - its status will initially be INPROGRESS
ResourceConfigurationUpdate newUpdateRequest = new ResourceConfigurationUpdate(resource, zeroedConfiguration,
newSubject);
newUpdateRequest.setStatus(newStatus);
if (ConfigurationUpdateStatus.FAILURE == newStatus) {
newUpdateRequest.setErrorMessage(errorMessage);
}
entityManager.persist(newUpdateRequest);
// No need to alert on the first configuration update, only on subsequent change