Skip to content

Commit

Permalink
Add notification-only async updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Mar 13, 2019
1 parent 483dbe5 commit fb4e874
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 1 deletion.
Expand Up @@ -72,6 +72,7 @@ public abstract class TestAsyncUpdate extends AbstractProvisioningIntegrationTes
private static final File CHANGE_100 = new File(TEST_DIR, "change-100-banderson-first-occurrence.xml");
private static final File CHANGE_110 = new File(TEST_DIR, "change-110-banderson-delta.xml");
private static final File CHANGE_120 = new File(TEST_DIR, "change-120-banderson-new-state.xml");
private static final File CHANGE_125 = new File(TEST_DIR, "change-125-banderson-notification-only.xml");
private static final File CHANGE_130 = new File(TEST_DIR, "change-130-banderson-delete.xml");

public static final QName RESOURCE_ACCOUNT_OBJECTCLASS = new QName(MidPointConstants.NS_RI, "AccountObjectClass");
Expand Down Expand Up @@ -365,6 +366,57 @@ public void test120ListeningForShadowReplace() throws Exception {
checkRepoShadow(accountRepo, ShadowKindType.ACCOUNT, getNumberOfAccountAttributes());
}


@Test
public void test125ListeningForNotificationOnly() throws Exception {

if (!hasReadCapability()) {
System.out.println("Skipping this test because there's no real read capability");
return;
}

final String TEST_NAME = "test125ListeningForNotificationOnly";
TestUtil.displayTestTitle(TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestAsyncUpdate.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

MockAsyncUpdateSource.INSTANCE.reset();
MockAsyncUpdateSource.INSTANCE.prepareMessage(prismContext.parserFor(CHANGE_125).parseRealValue());

syncServiceMock.reset();

ResourceShadowDiscriminator coords = new ResourceShadowDiscriminator(RESOURCE_ASYNC_OID,
ProvisioningTestUtil.getDefaultAccountObjectClass(resource.asObjectable()));

setDummyAccountTestAttribute("banderson", "value125");

provisioningService.startListeningForAsyncUpdates(coords, task, result);

syncServiceMock.assertNotifyChange();

ResourceObjectShadowChangeDescription lastChange = syncServiceMock.getLastChange();
display("The change", lastChange);

PrismObject<? extends ShadowType> oldShadow = lastChange.getOldShadow();
assertNotNull("Old shadow missing", oldShadow);
assertNotNull("Old shadow does not have an OID", oldShadow.getOid());

assertNull("Delta is present although it should not be", lastChange.getObjectDelta());
assertNotNull("Current shadow is missing", lastChange.getCurrentShadow());

display("change current shadow", lastChange.getCurrentShadow());

PrismObject<ShadowType> accountRepo = findAccountShadowByUsername("banderson", resource, result);
assertNotNull("Shadow is not present in the repository", accountRepo);
display("Repository shadow", accountRepo);
checkRepoShadow(accountRepo, ShadowKindType.ACCOUNT, getNumberOfAccountAttributes());
}

protected boolean hasReadCapability() {
return false;
}

@Test
public void test130ListeningForShadowDelete() throws Exception {
final String TEST_NAME = "test130ListeningForShadowDelete";
Expand Down
Expand Up @@ -80,4 +80,9 @@ protected void setDummyAccountTestAttribute(String name, String... values) {
throw new AssertionError(e);
}
}

@Override
protected boolean hasReadCapability() {
return true;
}
}
Expand Up @@ -40,6 +40,14 @@ public final class Change implements DebugDumpable {
private PrismObject<ShadowType> oldShadow;
private PrismObject<ShadowType> currentShadow;

/**
* This means that the change is just a notification that a resource object has changed. To know about its state
* it has to be fetched. For notification-only changes the objectDelta and currentShadow has to be null.
* (And this flag is introduced to distinguish intentional notification-only changes from malformed ones that have
* both currentShadow and objectDelta missing.)
*/
private boolean notificationOnly;

public Change(Collection<ResourceAttribute<?>> identifiers, ObjectDelta<ShadowType> change, PrismProperty<?> token) {
this.identifiers = identifiers;
this.objectDelta = change;
Expand All @@ -66,6 +74,16 @@ public Change(ObjectDelta<ShadowType> change, PrismProperty<?> token) {
this.token = token;
}

private Change() {
}

public static Change createNotificationOnly(Collection<ResourceAttribute<?>> identifiers) {
Change rv = new Change();
rv.identifiers = identifiers;
rv.notificationOnly = true;
return rv;
}

public ObjectDelta<ShadowType> getObjectDelta() {
return objectDelta;
}
Expand Down Expand Up @@ -118,6 +136,14 @@ public boolean isTokenOnly() {
return identifiers == null && objectDelta == null && currentShadow == null && token != null;
}

public void setNotificationOnly(boolean notificationOnly) {
this.notificationOnly = notificationOnly;
}

public boolean isNotificationOnly() {
return notificationOnly;
}

public boolean isDelete() {
return objectDelta != null && objectDelta.isDelete();
}
Expand All @@ -142,7 +168,11 @@ public String debugDump() {
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.indentDebugDump(sb, 0);
sb.append("Change\n");
sb.append("Change");
if (notificationOnly) {
sb.append(" (notification only)");
}
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "identifiers", identifiers, indent + 1);
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "objectDelta", objectDelta, indent + 1);
Expand Down
4 changes: 4 additions & 0 deletions provisioning/ucf-impl-builtin/pom.xml
Expand Up @@ -90,6 +90,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations-java5</artifactId>
</dependency>

<!-- Testing dependecies -->
<dependency>
Expand Down
Expand Up @@ -140,6 +140,9 @@ private Change createChange(UcfChangeType changeBean) throws SchemaException {
Collection<ResourceAttribute<?>> identifiers = getIdentifiers(changeBean, objectClassDef);
Change change = new Change(identifiers, toPrismObject(changeBean.getObject()), null, delta);
change.setObjectClassDefinition(objectClassDef);
if (change.getCurrentShadow() == null && change.getObjectDelta() == null) {
change.setNotificationOnly(true);
}
return change;
}

Expand Down

0 comments on commit fb4e874

Please sign in to comment.