diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java index aeb42642356..2a1fe937e6d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java @@ -1401,7 +1401,13 @@ public static LensProjectionContext fromLensProjectionContextType(LensProjection } // determines whether full shadow is present, based on operation result got from provisioning - public void determineFullShadowFlag(OperationResultType fetchResult) { + public void determineFullShadowFlag(PrismObject loadedShadow) { + ShadowType shadowType = loadedShadow.asObjectable(); + if (ShadowUtil.isDead(shadowType) || !ShadowUtil.isExists(shadowType)) { + setFullShadow(false); + return; + } + OperationResultType fetchResult = shadowType.getFetchResult(); if (fetchResult != null && (fetchResult.getStatus() == OperationResultStatusType.PARTIAL_ERROR || fetchResult.getStatus() == OperationResultStatusType.FATAL_ERROR) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java index 07fed8dd7f7..6c370e9a2a6 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java @@ -1059,14 +1059,17 @@ private void finishLoadOfProjectionContext(LensContext } } projContext.setLoadedObject(objectOld); - ShadowType oldShadow = objectOld.asObjectable(); if (projContext.isDoReconciliation()) { - projContext.determineFullShadowFlag(oldShadow.getFetchResult()); + projContext.determineFullShadowFlag(objectOld); } else { projContext.setFullShadow(false); } - projContext.setExists(ShadowUtil.isExists(objectOld.asObjectable())); projectionObject = objectOld; + if (!ShadowUtil.isExists(objectOld.asObjectable())) { + projContext.setExists(false); + LOGGER.debug("Foud only dead {} for projection context {}.", objectOld, projectionHumanReadableName); + refreshContextAfterShadowNotFound(context, projContext, options, task, result); + } } catch (ObjectNotFoundException ex) { LOGGER.debug("Could not find object with oid {} for projection context {}.", projectionObjectOid, projectionHumanReadableName); @@ -1268,17 +1271,16 @@ public void loadFullShadow(LensContext context, LensPr Collection> options = SelectorOptions.createCollection(getOptions); applyAttributesToGet(projCtx, options); try { - PrismObject objectCurrent = provisioningService.getObject(ShadowType.class, - projCtx.getOid(), options, task, result); + PrismObject objectCurrent = provisioningService.getObject(ShadowType.class, projCtx.getOid(), options, task, result); Validate.notNull(objectCurrent.getOid()); // TODO: use setLoadedObject() instead? projCtx.setObjectCurrent(objectCurrent); - ShadowType oldShadow = objectCurrent.asObjectable(); - projCtx.determineFullShadowFlag(oldShadow.getFetchResult()); - // The getObject may return different OID than we have requested in case that compensation happened - // TODO: this probably need to be fixed in the consistency mechanism - // TODO: the following line is a temporary fix - projCtx.setOid(objectCurrent.getOid()); + projCtx.determineFullShadowFlag(objectCurrent); + if (!ShadowUtil.isExists(objectCurrent.asObjectable())) { + LOGGER.debug("Load of full resource object {} ended with non-existent shadow (options={})", projCtx, getOptions); + projCtx.setExists(false); + refreshContextAfterShadowNotFound(context, projCtx, options, task, result); + } } catch (ObjectNotFoundException ex) { LOGGER.debug("Load of full resource object {} ended with ObjectNotFoundException (options={})", projCtx, getOptions); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java index ee229f7f5d7..5d1e749f8bb 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ReconciliationProcessor.java @@ -161,10 +161,9 @@ private void processReconciliationFocus(LensContext co PrismObject objectOld = provisioningService.getObject(ShadowType.class, projCtx.getOid(), SelectorOptions.createCollection(rootOps), task, result); - ShadowType oldShadow = objectOld.asObjectable(); - projCtx.determineFullShadowFlag(oldShadow.getFetchResult()); + projCtx.determineFullShadowFlag(objectOld); projCtx.setLoadedObject(objectOld); - + projCtx.setExists(ShadowUtil.isExists(objectOld.asObjectable())); projCtx.recompute(); } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/errorhandling/ObjectNotFoundHandler.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/errorhandling/ObjectNotFoundHandler.java index 8297828fb53..bbfe3d4589c 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/errorhandling/ObjectNotFoundHandler.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/errorhandling/ObjectNotFoundHandler.java @@ -94,11 +94,23 @@ public PrismObject handleGetError(ProvisioningContext ctx, } if (repositoryShadow != null) { - // We always want to return repository shadow it such shadow is available. - // The shadow may be dead, or it may be marked as "not exists", but we want - // to return something if shadow exists in the repo. Otherwise model may - // unlink the shadow or otherwise "forget" about it. - LOGGER.debug("Shadow {} not found on the resource. However still have it in the repository. Therefore returning repository version.", repositoryShadow); + + if (ShadowUtil.isExists(repositoryShadow.asObjectable())) { + // This is some kind of reality mismatch. We obviously have shadow that is supposed + // to be alive (exists=true). But it does not exist on resource. + // This is NOT gestation quantum state, as that is handled directly in ShadowCache. + // This may be "lost shadow" - shadow which exists but the resource object has disappeared without trace. + // Or this may be a corpse - quantum state that has just collapsed to to tombstone. + // Either way, it should be safe to set exists=false. + LOGGER.trace("Setting {} as tombstone. This may be a quntum state collapse. Or maybe a lost shadow.", repositoryShadow); + repositoryShadow = shadowManager.markShadowDead(repositoryShadow, parentResult); + } else { + // We always want to return repository shadow it such shadow is available. + // The shadow may be dead, or it may be marked as "not exists", but we want + // to return something if shadow exists in the repo. Otherwise model may + // unlink the shadow or otherwise "forget" about it. + LOGGER.debug("Shadow {} not found on the resource. However still have it in the repository. Therefore returning repository version.", repositoryShadow); + } parentResult.setStatus(OperationResultStatus.HANDLED_ERROR); return repositoryShadow; }