use of com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException in project midpoint by Evolveum.
the class SqaleUtils method handlePostgresException.
/**
* Throws more specific exception or returns and then original exception should be rethrown.
*/
public static void handlePostgresException(Exception exception) throws ObjectAlreadyExistsException {
PSQLException psqlException = ExceptionUtil.findCause(exception, PSQLException.class);
String state = psqlException.getSQLState();
String message = psqlException.getMessage();
if (PSQLState.UNIQUE_VIOLATION.getState().equals(state)) {
if (message.contains("m_object_oid_pkey")) {
String oid = StringUtils.substringBetween(message, "(oid)=(", ")");
throw new ObjectAlreadyExistsException(oid != null ? "Provided OID " + oid + " already exists" : message, exception);
} else if (message.contains("namenorm_key")) {
String name = StringUtils.substringBetween(message, "(namenorm)=(", ")");
throw new ObjectAlreadyExistsException(name != null ? "Object with conflicting normalized name '" + name + "' already exists" : message, exception);
} else {
throw new ObjectAlreadyExistsException("Conflicting object already exists, constraint violation message: " + psqlException.getMessage(), exception);
}
}
}
use of com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException in project midpoint by Evolveum.
the class SimpleMockActivityRun method runLocally.
@Override
@NotNull
protected ActivityRunResult runLocally(OperationResult result) throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException {
String message = activity.getWorkDefinition().getMessage();
Operation operation = activityState.getLiveItemProcessingStatistics().recordOperationStart(new IterativeOperationStartInfo(new IterationItemInformation(message, null, null, null)));
// to avoid wall clock time of 0 (failing throughput-assuming tests)
MiscUtil.sleepCatchingInterruptedException(10);
LOGGER.info("Message: {}", message);
getRecorder().recordExecution(message);
CommonMockActivityHelper helper = getActivityHandler().getMockHelper();
helper.increaseExecutionCount(activityState, result);
try {
helper.failIfNeeded(this, activity.getWorkDefinition().getInitialFailures());
QualifiedItemProcessingOutcomeType qualifiedOutcome = new QualifiedItemProcessingOutcomeType(getPrismContext()).outcome(ItemProcessingOutcomeType.SUCCESS);
operation.done(qualifiedOutcome, null);
incrementProgress(qualifiedOutcome);
} catch (Exception e) {
QualifiedItemProcessingOutcomeType qualifiedOutcome = new QualifiedItemProcessingOutcomeType(getPrismContext()).outcome(ItemProcessingOutcomeType.FAILURE);
operation.done(qualifiedOutcome, e);
incrementProgress(qualifiedOutcome);
throw e;
}
return standardRunResult();
}
use of com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException in project midpoint by Evolveum.
the class ObjectUpdater method modifyObjectAttempt.
/**
* @param externalSession If non-null, this session is used to execute the operation. Note that usual commit/rollback is
* issued even if external session is present. We assume we are the last element of the processing in the session.
*/
public <T extends ObjectType> ModifyObjectResult<T> modifyObjectAttempt(Class<T> type, String oid, Collection<? extends ItemDelta<?, ?>> originalModifications, ModificationPrecondition<T> precondition, RepoModifyOptions originalModifyOptions, int attempt, OperationResult result, SqlRepositoryServiceImpl sqlRepositoryService, boolean noFetchExtensionValueInsertionForbidden, Session externalSession) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SerializationRelatedException, PreconditionViolationException {
RepoModifyOptions modifyOptions = adjustExtensionValuesHandling(originalModifyOptions, noFetchExtensionValueInsertionForbidden);
AttemptContext attemptContext = new AttemptContext();
// clone - because some certification and lookup table related methods manipulate this collection and even their constituent deltas
// TODO clone elements only if necessary
Collection<? extends ItemDelta<?, ?>> modifications = CloneUtil.cloneCollectionMembers(originalModifications);
// modifications = new ArrayList<>(modifications);
LOGGER.debug("Modifying object '{}' with oid '{}' (attempt {}) (adjusted options: {})", type.getSimpleName(), oid, attempt, modifyOptions);
LOGGER_PERFORMANCE.debug("> modify object {}, oid={} (attempt {}), modifications={}", type.getSimpleName(), oid, attempt, modifications);
LOGGER.trace("Modifications:\n{}", DebugUtil.debugDumpLazily(modifications));
LOGGER.trace("noFetchExtensionValueInsertionForbidden: {}", noFetchExtensionValueInsertionForbidden);
Session session = externalSession;
OrgClosureManager.Context closureContext = null;
try {
if (session == null) {
session = baseHelper.beginTransaction();
}
closureContext = closureManager.onBeginTransactionModify(session, type, oid, modifications);
Collection<? extends ItemDelta<?, ?>> lookupTableModifications = lookupTableHelper.filterLookupTableModifications(type, modifications);
Collection<? extends ItemDelta<?, ?>> campaignCaseModifications = caseHelper.filterCampaignCaseModifications(type, modifications);
ModifyObjectResult<T> rv;
boolean reindex = RepoModifyOptions.isForceReindex(modifyOptions);
if (!modifications.isEmpty() || reindex) {
// JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big.
// Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo
// association. However, this leads to a strange problem when merging in-memory RFocus object with the database state:
// If in-memory RFocus object has no photo associated (because of lazy loading), then the associated RFocusPhoto is deleted.
//
// To prevent this behavior, we've set orphanRemoval to false. Fortunately, the remove operation on RFocus
// seems to be still cascaded to RFocusPhoto. What we have to implement ourselves, however, is removal of RFocusPhoto
// _without_ removing of RFocus. In order to know whether the photo has to be removed, we have to retrieve
// its value, apply the delta (e.g. if the delta is a DELETE VALUE X, we have to know whether X matches current
// value of the photo), and if the resulting value is empty, we have to manually delete the RFocusPhoto instance.
//
// So the first step is to retrieve the current value of photo - we obviously do this only if the modifications
// deal with the jpegPhoto property.
//
// TODO handling of "externally stored" items (focus.jpegPhoto, task.result, lookupTable.row, ...)
// is a kind of ugly magic. It needs to be reviewed and fixed.
GetOperationOptionsBuilder optionsBuilder = schemaService.getOperationOptionsBuilder();
boolean containsFocusPhotoModification = FocusType.class.isAssignableFrom(type) && containsPhotoModification(modifications);
if (containsFocusPhotoModification) {
LOGGER.trace("Setting 'retrieve' option on jpegPhoto for object fetching because containsFocusPhotoModification=true");
optionsBuilder = optionsBuilder.item(FocusType.F_JPEG_PHOTO).retrieve();
}
if (reindex) {
LOGGER.trace("Setting 'raw' option for object fetching because reindex is being applied");
optionsBuilder = optionsBuilder.root().raw();
if (TaskType.class.isAssignableFrom(type) || ShadowType.class.isAssignableFrom(type)) {
// Certification campaigns and lookup tables treat their externally stored items (cases, rows)
// in a different way that collides with the use of "retrieve" option. TODO resolve this!
LOGGER.trace("Setting 'retrieve' option for object fetching because reindex is being applied");
optionsBuilder = optionsBuilder.root().retrieve();
} else {
LOGGER.trace("Setting 'retrieve' option for c:extension for object fetching because reindex is being applied");
// index-only items can be also here
optionsBuilder = optionsBuilder.item(ObjectType.F_EXTENSION).retrieve();
}
}
// get object
PrismObject<T> prismObject = objectRetriever.getObjectInternal(session, type, oid, optionsBuilder.build(), true);
if (precondition != null && !precondition.holds(prismObject)) {
throw new PreconditionViolationException("Modification precondition does not hold for " + prismObject);
}
sqlRepositoryService.invokeConflictWatchers(w -> w.beforeModifyObject(prismObject));
// apply diff
LOGGER.trace("OBJECT before:\n{}", prismObject.debugDumpLazily());
PrismObject<T> originalObject = prismObject.clone();
boolean shouldPhotoBeRemoved;
if (reindex) {
// old implementation start
ItemDeltaCollectionsUtil.applyTo(modifications, prismObject);
LOGGER.trace("OBJECT after:\n{}", prismObject.debugDumpLazily());
// Continuing the photo treatment: should we remove the (now obsolete) focus photo?
// We have to test prismObject at this place, because updateFullObject (below) removes photo property from the prismObject.
shouldPhotoBeRemoved = containsFocusPhotoModification && ((FocusType) prismObject.asObjectable()).getJpegPhoto() == null;
// merge and update object
LOGGER.trace("Translating JAXB to data type.");
ObjectTypeUtil.normalizeAllRelations(prismObject, relationRegistry);
PrismIdentifierGenerator idGenerator = new PrismIdentifierGenerator(PrismIdentifierGenerator.Operation.MODIFY);
RObject rObject = createDataObjectFromJAXB(prismObject, idGenerator);
rObject.setVersion(rObject.getVersion() + 1);
updateFullObject(rObject, prismObject);
LOGGER.trace("Starting merge.");
session.merge(rObject);
// old implementation end
} else {
// new implementation start
RObject rObject = objectDeltaUpdater.modifyObject(type, oid, modifications, prismObject, modifyOptions, session, attemptContext);
LOGGER.trace("OBJECT after:\n{}", prismObject.debugDumpLazily());
// Continuing the photo treatment: should we remove the (now obsolete) focus photo?
// We have to test prismObject at this place, because updateFullObject (below) removes photo property from the prismObject.
shouldPhotoBeRemoved = containsFocusPhotoModification && ((FocusType) prismObject.asObjectable()).getJpegPhoto() == null;
updateFullObject(rObject, prismObject);
LOGGER.trace("Starting save.");
session.save(rObject);
LOGGER.trace("Save finished.");
// new implementation end
}
if (closureManager.isEnabled()) {
closureManager.updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext);
}
// we have to remove the photo manually.
if (shouldPhotoBeRemoved) {
Query<?> query = session.createQuery("delete RFocusPhoto where ownerOid = :oid");
query.setParameter("oid", prismObject.getOid());
query.executeUpdate();
LOGGER.trace("Focus photo for {} was deleted", prismObject.getOid());
}
rv = new ModifyObjectResult<>(originalObject, prismObject, originalModifications);
} else {
rv = new ModifyObjectResult<>(originalModifications);
}
if (LookupTableType.class.isAssignableFrom(type)) {
lookupTableHelper.updateLookupTableData(session, oid, lookupTableModifications);
}
if (AccessCertificationCampaignType.class.isAssignableFrom(type)) {
caseHelper.updateCampaignCases(session, oid, campaignCaseModifications, modifyOptions);
}
LOGGER.trace("Before commit...");
session.getTransaction().commit();
LOGGER.trace("Committed! (at attempt {})", attempt);
return rv;
} catch (ObjectNotFoundException | SchemaException ex) {
baseHelper.rollbackTransaction(session, ex, result, true);
throw ex;
} catch (PersistenceException ex) {
ConstraintViolationException constEx = ExceptionUtil.findCause(ex, ConstraintViolationException.class);
if (constEx != null) {
handleConstraintViolationExceptionSpecialCases(constEx, session, attemptContext, result);
baseHelper.rollbackTransaction(session, constEx, result, true);
LOGGER.debug("Constraint violation occurred (will be rethrown as ObjectAlreadyExistsException).", constEx);
// todo improve (we support only 5 DB, so we should probably do some hacking in here)
throw new ObjectAlreadyExistsException(constEx);
} else {
baseHelper.handleGeneralException(ex, session, result);
throw new AssertionError("Shouldn't get here");
}
} catch (DtoTranslationException | RuntimeException ex) {
baseHelper.handleGeneralException(ex, session, result);
throw new AssertionError("Shouldn't get here");
} finally {
cleanupClosureAndSessionAndResult(closureContext, session, result);
LOGGER.trace("Session cleaned up.");
}
}
use of com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException in project midpoint by Evolveum.
the class StalledTasksWatcher method checkStalledTasks.
public void checkStalledTasks(OperationResult parentResult) {
OperationResult result = parentResult.createSubresult(DOT_CLASS + "checkStalledTasks");
Map<String, RunningTaskQuartzImpl> runningTasks = localNodeState.getLocallyRunningTaskInstances();
LOGGER.trace("checkStalledTasks: running tasks = {}", runningTasks);
for (RunningTaskQuartzImpl task : runningTasks.values()) {
if (task.isExcludedFromStalenessChecking()) {
LOGGER.trace("Task {} is excluded from staleness checking", task);
continue;
}
long currentTimestamp = System.currentTimeMillis();
long lastStartedTimestamp = task.getLastRunStartTimestamp() != null ? task.getLastRunStartTimestamp() : 0L;
Long heartbeatProgressInfo = task.getHandler().heartbeat(task);
long realProgress;
if (heartbeatProgressInfo != null) {
realProgress = heartbeatProgressInfo;
} else {
try {
realProgress = taskRetriever.getTaskPlain(task.getOid(), result).getLegacyProgress();
} catch (ObjectNotFoundException e) {
LoggingUtils.logException(LOGGER, "Task {} cannot be checked for staleness because it is gone", e, task);
continue;
} catch (SchemaException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Task {} cannot be checked for staleness because " + "of schema exception", e, task);
continue;
}
}
ProgressInformation lastProgressEntry = lastProgressMap.get(task.getTaskIdentifier());
LOGGER.trace("checkStalledTasks: considering ({}, {}, {}), last information = {}", task, lastStartedTimestamp, realProgress, lastProgressEntry);
// check and/or update the last progress information
if (hasEntryChanged(lastProgressEntry, lastStartedTimestamp, realProgress)) {
lastProgressMap.put(task.getTaskIdentifier(), new ProgressInformation(currentTimestamp, realProgress, lastStartedTimestamp));
} else {
if (isEntryStalled(currentTimestamp, lastProgressEntry)) {
if (currentTimestamp - lastProgressEntry.lastNotificationIssuedTimestamp > configuration.getStalledTasksRepeatedNotificationInterval() * 1000L) {
LOGGER.error("Task {} is stalled (started {}; progress is still {}, observed since {}){}", task, new Date(lastProgressEntry.lastStartedTimestamp), lastProgressEntry.measuredProgress, new Date(lastProgressEntry.measurementTimestamp), lastProgressEntry.lastNotificationIssuedTimestamp != 0 ? " [this is a repeated notification]" : "");
lastProgressEntry.lastNotificationIssuedTimestamp = currentTimestamp;
try {
taskThreadsDumper.recordTaskThreadsDump(task.getOid(), SchemaConstants.INTERNAL_URI, result);
} catch (SchemaException | ObjectNotFoundException | ObjectAlreadyExistsException | RuntimeException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't record thread dump for stalled task {}", e, task);
}
markTaskStalled(task, lastProgressEntry.measurementTimestamp, result);
}
}
}
}
// clean-up obsolete progress entries
lastProgressMap.keySet().removeIf(s -> !runningTasks.containsKey(s));
LOGGER.trace("checkStalledTasks lastProgress map after cleaning up = {}", lastProgressMap);
}
use of com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException in project midpoint by Evolveum.
the class NodeRegistrar method createOrUpdateNodeInRepo.
/**
* Executes node startup registration: if Node object with a give name (node ID) exists, deletes it.
* Then creates a new Node with the information relevant to this node.
*
* @param result Node prism to be used for periodic re-registrations.
*/
NodeType createOrUpdateNodeInRepo(OperationResult result) throws TaskManagerInitializationException {
NodeType nodeToBe = createLocalNodeObject(configuration);
LOGGER.info("Registering this node in the repository as {} at {}", nodeToBe.getNodeIdentifier(), nodeToBe.getHostname());
List<PrismObject<NodeType>> nodesInRepo;
try {
nodesInRepo = findNodesWithGivenName(result, PolyString.getOrig(nodeToBe.getName()));
} catch (SchemaException e) {
throw new TaskManagerInitializationException("Node registration failed because of schema exception", e);
}
if (nodesInRepo.size() == 1) {
PrismObject<NodeType> nodeInRepo = nodesInRepo.get(0);
// copy all information that need to be preserved from the repository
if (configuration.getTaskExecutionLimitations() != null) {
// In this (special) case, we overwrite repository information by statically configured values.
LOGGER.info("Using statically-defined task execution limitations for the current node");
} else {
// But usually we take execution limitations from the repository.
nodeToBe.setTaskExecutionLimitations(nodeInRepo.asObjectable().getTaskExecutionLimitations());
}
nodeToBe.setUrlOverride(applyDefault(nodeInRepo.asObjectable().getUrlOverride(), configuration.getUrl()));
// URL is refreshed later, in cluster manager thread
nodeToBe.setUrl(nodeInRepo.asObjectable().getUrl());
if (shouldRenewSecret(nodeInRepo.asObjectable())) {
LOGGER.info("Renewing node secret for the current node");
} else {
nodeToBe.setSecret(nodeInRepo.asObjectable().getSecret());
nodeToBe.setSecretUpdateTimestamp(nodeInRepo.asObjectable().getSecretUpdateTimestamp());
}
ObjectDelta<NodeType> nodeDelta = nodeInRepo.diff(nodeToBe.asPrismObject(), EquivalenceStrategy.DATA);
LOGGER.debug("Applying delta to existing node object:\n{}", nodeDelta.debugDumpLazily());
try {
repositoryService.modifyObject(NodeType.class, nodeInRepo.getOid(), nodeDelta.getModifications(), result);
LOGGER.debug("Node was successfully updated in the repository.");
nodeToBe.setOid(nodeInRepo.getOid());
setCachedLocalNodeObject(nodeToBe.asPrismObject());
return nodeToBe;
} catch (ObjectNotFoundException | SchemaException | ObjectAlreadyExistsException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't update node object on system initialization; will re-create the node", e);
}
}
if (nodesInRepo.size() > 1) {
LOGGER.warn("More than one node with the name of {}: removing all of them.", nodeToBe.getName());
}
for (PrismObject<NodeType> n : nodesInRepo) {
LOGGER.debug("Removing existing NodeType with oid = {}, name = {}", n.getOid(), n.getName());
try {
repositoryService.deleteObject(NodeType.class, n.getOid(), result);
} catch (ObjectNotFoundException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Cannot remove NodeType with oid = {}, name = {}, because it does not exist.", e, n.getOid(), n.getElementName());
// continue, because the error is not that severe (we hope so)
}
}
try {
String oid = repositoryService.addObject(nodeToBe.asPrismObject(), null, result);
nodeToBe.setOid(oid);
setCachedLocalNodeObject(nodeToBe.asPrismObject());
} catch (ObjectAlreadyExistsException e) {
localNodeState.setErrorState(NodeErrorStateType.NODE_REGISTRATION_FAILED);
throw new TaskManagerInitializationException("Cannot register this node, because it already exists (this should not happen, as nodes with such a name were just removed)", e);
} catch (SchemaException e) {
localNodeState.setErrorState(NodeErrorStateType.NODE_REGISTRATION_FAILED);
throw new TaskManagerInitializationException("Cannot register this node because of schema exception", e);
}
LOGGER.debug("Node was successfully registered (created) in the repository.");
return nodeToBe;
}
Aggregations