9.4. Change Notification For Your Applications

Some applications require notification when directory data updates occur. For example, an application might need to sync directory data with another database, or the application might need to kick off other processing when certain updates occur.

In addition to supporting persistent search operations, OpenDJ provides an external change log mechanism to allow applications to be notified of changes to directory data.

Procedure 9.10. To Enable the External Change Log

OpenDJ directory servers without replication cannot expose an external change log. The OpenDJ server that exposes the change log must function both as a directory server, and also as a replication server for the suffix whose changes you want logged.

  • Enable replication without using the --noReplicationServer or --onlyReplicationServer options.

    With replication enabled, the changelog data can be accessed under cn=changelog. For example, the following search shows the publicly visible data available before any changes have been made.

    $ ldapsearch --baseDN cn=changelog --port 1389 "(objectclass=*)" \* +
    dn: cn=changelog
    cn: changelog
    objectClass: top
    objectClass: container
    subschemaSubentry: cn=schema
    hasSubordinates: false
    entryDN: cn=changelog
    

Procedure 9.11. To Use the External Change Log

You read the external change log over LDAP. In addition, when you poll the change log periodically, you can get the list of updates that happened since your last request.

The external change log mechanism uses an LDAP control with OID 1.3.6.1.4.1.26027.1.5.4 to allow the exchange of cookies for the client application to bookmark the last changes seen, and then start reading the next set of changes from where it left off on the previous request.

This procedure shows the client reading the change log as cn=Directory Manager. Make sure your client application reads the changes with sufficient access to view all the changes it needs to see.

  1. Send an initial search request using the LDAP control with no cookie value.

    Notice the value of the changeLogCookie attribute for the last of the two changes.

    $ ldapsearch
     --baseDN cn=changelog
     --port 1389
     --bindDN "cn=Directory Manager"
     --bindPassword password
     --control "1.3.6.1.4.1.26027.1.5.4:false"
     "(objectclass=*)"
     \* +
    dn: cn=changelog
    cn: changelog
    objectClass: top
    objectClass: container
    subschemaSubentry: cn=schema
    hasSubordinates: true
    entryDN: cn=changelog
    
    # Public changelog exchange control(1.3.6.1.4.1.26027.1.5.4):
     dc=example,dc=com:0000013087cbc28212d100000001;
    dn: replicationCSN=0000013087cbc28212d100000001,dc=example,dc=com,cn=changelog
    targetDN: cn=arsene lupin,ou=special users,dc=example,dc=com
    changeNumber: 0
    changes:: b2JqZWN0Q2xhc3M6IHBlcnNvbgpvYmplY3RDbGFzczogdG9wCmNuOiBBcnNlbmUgTHVwaW
     4KdGVsZXBob25lTnVtYmVyOiArMzMgMSAyMyA0NSA2NyA4OQpzbjogTHVwaW4KZW50cnlVVUlEOiA5M
     GM3MTRmNy00ODZiLTRkNDctOTQwOS1iNDRkMTlkZWEzMWUKY3JlYXRlVGltZXN0YW1wOiAyMDExMDYx
     MzA2NTg1NVoKY3JlYXRvcnNOYW1lOiBjbj1EaXJlY3RvcnkgTWFuYWdlcixjbj1Sb290IEROcyxjbj1
     jb25maWcK
    changeType: add
    changeTime: 20110613065855Z
    objectClass: top
    objectClass: changeLogEntry
    targetEntryUUID: 90c714f7-486b-4d47-9409-b44d19dea31e
    replicationCSN: 0000013087cbc28212d100000001
    numSubordinates: 0
    replicaIdentifier: 4817
    changeLogCookie: dc=example,dc=com:0000013087cbc28212d100000001;
    changeInitiatorsName: cn=Directory Manager,cn=Root DNs,cn=config
    subschemaSubentry: cn=schema
    hasSubordinates: false
    entryDN: replicationCSN=0000013087cbc28212d100000001,dc=example,dc=com,cn=change
     log
    
    # Public changelog exchange control(1.3.6.1.4.1.26027.1.5.4):
     dc=example,dc=com:0000013087cbc34a12d100000002;
    dn: replicationCSN=0000013087cbc34a12d100000002,dc=example,dc=com,cn=changelog
    targetDN: cn=horace velmont,ou=special users,dc=example,dc=com
    changeNumber: 0
    changes:: b2JqZWN0Q2xhc3M6IHBlcnNvbgpvYmplY3RDbGFzczogdG9wCmNuOiBIb3JhY2UgVmVsbW
     9udAp0ZWxlcGhvbmVOdW1iZXI6ICszMyAxIDEyIDIzIDM0IDQ1CnNuOiBWZWxtb250CmVudHJ5VVVJR
     DogNmIyMjQ0MGEtNzZkMC00MDMxLTk0YjctMzViMWQ4NmYwNjdlCmNyZWF0ZVRpbWVzdGFtcDogMjAx
     MTA2MTMwNjU4NTVaCmNyZWF0b3JzTmFtZTogY249RGlyZWN0b3J5IE1hbmFnZXIsY249Um9vdCBETnM
     sY249Y29uZmlnCg==
    changeType: add
    changeTime: 20110613065855Z
    objectClass: top
    objectClass: changeLogEntry
    targetEntryUUID: 6b22440a-76d0-4031-94b7-35b1d86f067e
    replicationCSN: 0000013087cbc34a12d100000002
    numSubordinates: 0
    replicaIdentifier: 4817
    changeLogCookie: dc=example,dc=com:0000013087cbc34a12d100000002;
    changeInitiatorsName: cn=Directory Manager,cn=Root DNs,cn=config
    subschemaSubentry: cn=schema
    hasSubordinates: false
    entryDN: replicationCSN=0000013087cbc34a12d100000002,dc=example,dc=com,cn=change
     log
    

    In this example, two new users were added to another replica before the change log request was made.

    Here the changes are base64 encoded, so you can decode them using the base64 command.

    $ base64 decode --encodedData b2JqZW...ZmlnCg==
    objectClass: person
    objectClass: top
    cn: Horace Velmont
    telephoneNumber: +33 1 12 23 34 45
    sn: Velmont
    entryUUID: 6b22440a-76d0-4031-94b7-35b1d86f067e
    createTimestamp: 20110613065855Z
    creatorsName: cn=Directory Manager,cn=Root DNs,cn=config
        
  2. For the next search, provide the cookie to start reading where you left off last time.

    In this example, a description was added to Babs Jensen's entry.

    $ ldapsearch
     --baseDN cn=changelog
     --port 1389
     --bindDN "cn=Directory Manager"
     --bindPassword password
     --control "1.3.6.1.4.1.26027.1.5.4:false:
     dc=example,dc=com:0000013087cbc34a12d100000002;"
     "(objectclass=*)"
     \* +
    dn: cn=changelog
    cn: changelog
    objectClass: top
    objectClass: container
    subschemaSubentry: cn=schema
    hasSubordinates: true
    entryDN: cn=changelog
    
    # Public changelog exchange control(1.3.6.1.4.1.26027.1.5.4):
     dc=example,dc=com:0000013087d7e27f12d100000003;
    dn: replicationCSN=0000013087d7e27f12d100000003,dc=example,dc=com,cn=changelog
    targetDN: uid=bjensen,ou=people,dc=example,dc=com
    changeNumber: 0
    changes:: YWRkOiBkZXNjcmlwdGlvbgpkZXNjcmlwdGlvbjogQSB0aGlyZCBjaGFuZ2UKLQpyZXBsYW
     NlOiBtb2RpZmllcnNOYW1lCm1vZGlmaWVyc05hbWU6IGNuPURpcmVjdG9yeSBNYW5hZ2VyLGNuPVJvb
     3QgRE5zLGNuPWNvbmZpZwotCnJlcGxhY2U6IG1vZGlmeVRpbWVzdGFtcAptb2RpZnlUaW1lc3RhbXA6
     IDIwMTEwNjEzMDcxMjEwWgotCg==
    changeType: modify
    changeTime: 20110613071210Z
    objectClass: top
    objectClass: changeLogEntry
    targetEntryUUID: fc252fd9-b982-3ed6-b42a-c76d2546312c
    replicationCSN: 0000013087d7e27f12d100000003
    numSubordinates: 0
    replicaIdentifier: 4817
    changeLogCookie: dc=example,dc=com:0000013087d7e27f12d100000003;
    changeInitiatorsName: cn=Directory Manager,cn=Root DNs,cn=config
    subschemaSubentry: cn=schema
    hasSubordinates: false
    entryDN: replicationCSN=0000013087d7e27f12d100000003,dc=example,dc=com,cn=change
     log
        

    If we base64-decode the changes, we see the following.

    $ base64 decode --encodedData YWRkO...gotCg==
    add: description
    description: A third change
    -
    replace: modifiersName
    modifiersName: cn=Directory Manager,cn=Root DNs,cn=config
    -
    replace: modifyTimestamp
    modifyTimestamp: 20110613071210Z
    -
    
  3. If for some reason you lose the cookie, you can start over from the earliest available change by sending a search request with no value for the cookie.

Procedure 9.12. To Include Unchanged Attributes in the External Change Log

As shown above, the changes returned from a search on the external change log include only what was actually changed. If you have applications that need additional attributes published with every change log entry, regardless of whether or not the attribute itself has changed, then specify those using ecl-include and ecl-include-for-deletes.

  1. Set the attributes to include for all update operations with ecl-include.

    $ dsconfig
     set-external-changelog-domain-prop
     --port 4444
     --hostname opendj.example.com
     --bindDN "cn=Directory Manager"
     --bindPassword password
     --provider-name "Multimaster Synchronization"
     --domain-name dc=example,dc=com
     --set ecl-include:"@person"
     --trustAll
     --no-prompt
  2. Set the attributes to include for deletes with ecl-include-for-deletes.

    $ dsconfig
     set-external-changelog-domain-prop
     --port 4444
     --hostname opendj.example.com
     --bindDN "cn=Directory Manager"
     --bindPassword password
     --provider-name "Multimaster Synchronization"
     --domain-name dc=example,dc=com
     --add ecl-include-for-deletes:"*"
     --add ecl-include-for-deletes:"+"
     --trustAll
     --no-prompt

Procedure 9.13. To Limit External Change Log Content

You can limit external change log content by disabling the domain for a base DN. By default, cn=schema and cn=admin data are not enabled.

  • Prevent OpenDJ from logging changes by disabling the domain.

    $ dsconfig
     set-external-changelog-domain-prop
     --port 4444
     --hostname opendj.example.com
     --bindDN "cn=Directory Manager"
     --bindPassword password
     --provider-name "Multimaster Synchronization"
     --domain-name dc=example,dc=com
     --set enabled:false
     --trustAll
     --no-prompt

The external change log can also work for applications that follow the Internet-Draft: Definition of an Object Class to Hold LDAP Change Records. Nothing special is required to get the objects specified for this legacy format. Such applications cannot however use the change log cookies that are shared across the replication topology, and therefore can continue to be used after failover to another replica in a multi-master replication environment.