Menu

Unexpected Attribute Name in Change LDIF?

2015-08-20
2015-09-01
  • Jason "JRSofty" Reed

    Hi,

    I'm just starting out working with your SDK for use in importing a change LDIF and checking that there are no errors before applying it to the Directory Service. My first work right now is trying to see how to actually read through the change LDIF file I'm doing this by creating an instance of the LDIFReader(pathToFile) and iterating thorugh the file with the readChangeRecord() method. While this happens I get the following message:

    LDIFException(lineNumber=61444, mayContinueReading=true, message='The modify change record starting at or near line 61444 has attribute name mhsDLMembers;binary where mhsDLMembers

    When I browse the Directory Service I see that the mhsDLMembers attribute for this record is a table with two columns which only the second column is filled. The mhsDLMembers;binary contains Base64 encoded data that I'm pretty sure describes this table or at least a row entry on this table.

    What seems really confusing to me is that the LDIFReader throws this exception but how does it know to expect the mhsDLMembers element but not the mhsDLMembers;binary? I've not made a connection to the DS as of yet since I'm just working with the LDIF right now. According to the stack trace the exception is thrown from LDIFReader.java:3253.

    Regards,
    Jason Reed

     

    Last edit: Jason "JRSofty" Reed 2015-08-20
  • Neil Wilson

    Neil Wilson - 2015-08-20

    The exception message indicates that the LDIF modify change record looks something like:

    dn: cn=something,dc=naming,dc=context
    changetype: modify
    add: mhsDLMembers
    mhsDLMembers;binary:: {base64-encoded-data}
    

    It should actually look something like:

    dn: cn=something,dc=naming,dc=context
    changetype: modify
    add: mhsDLMembers;binary
    mhsDLMembers;binary:: {base64-encoded-data}
    

    That is, you should use the exact same attribute description (including attribute options) in the add/delete/replace line as in the line(s) containing the value(s) for that attribute.

     
  • Jason "JRSofty" Reed

    Hi Neil, thanks for the information. I'll have to see if that fix works. The problem though is that in the future I have no control over the generation of the ldif files. Is there a way I catch this sort of problem and handle it during the reading process? I looked at the LDIFREaderEntryTranslator interface, and have tried to get an implementation of it working but it doesn't seem to be called.

    [Edit] You were right about the naming in the ldif. thanks.[/Edit]

     

    Last edit: Jason "JRSofty" Reed 2015-08-25
  • Neil Wilson

    Neil Wilson - 2015-08-25

    Unfortunately, there's not really anything you can do other than correct the LDIF file. The LDIFReaderEntryTranslator interface is only invoked after the LDIF record has been parsed, but in this case the mismatch between attribute descriptions prevents it from being parsed.

     
  • Jason "JRSofty" Reed

    I'm not sure the LDIFReaderEntryTranslator is called at all actually. I know that there are some valid values in the LDIF and my LDIFReaderEntryTranslator implementation isn't being called even on valid entries. Must the entire file be parsed before this is used, or is it because I'm using the readChangeRecord() method during processing?

    [Edit] Confirmed you have to use the readEntry() method for the LDIFREaderEntryTranslator to be called, and the readEntry() is not really for handling change records it looks like.[/Edit]

     

    Last edit: Jason "JRSofty" Reed 2015-08-26
  • Neil Wilson

    Neil Wilson - 2015-08-26

    As you found, the LDIFReaderEntryTranslator is only called for the readEntry method. There is an LDIFReaderChangeRecordTranslator that is committed in the repository but not yet included in any release, and it will be invoked for the readChangeRecord method. You can use it if you check out and build the LDAP SDK for yourself (and as long as you don't alter the SDK code itself, a build you create for yourself from code checked out of the repository will be just as supported as official releases).

    The question of the attribute description mismatch problem that you ran into is still a little fuzzy. It's not clear from any of the official specifications that the specific situation you've encountered is legal, but I did find at least one example on a non-authoritative site that didn't include the ";binary" option in the line indicating the modification type but did include it in the line specifying the target attribute value. I'll see if I can update the LDAP SDK to accept this particular case.

     
  • Jason "JRSofty" Reed

    Hi Neil,

    Thanks for the information, it would be nice if the LDAP SDK could handle that attribute issue. I had assumed that it was a standards problem and that our customer's system wasn't exactly living up to the standard.

    When is the next planned release for the LDAP SDK, then I can make the determination if we should make a local build of the SDK from source.

     
  • Neil Wilson

    Neil Wilson - 2015-08-31

    There's not yet a definite date for the next release of the LDAP SDK, although it will probably be at least a couple of months.

    I have a number of changes to the LDAP SDK that I hope to get in later this week, including some changes to the LDIF reader. I'll see if I can add in some leniency for the ";binary" handling along with the other changes.

     
  • Neil Wilson

    Neil Wilson - 2015-08-31

    I just committed a change that should allow the LDIF reader to handle the case in which an LDIF change record did not include the binary option when specifying the target attribute description, but the binary option is included when the values are provided.

     
  • Jason "JRSofty" Reed

    Thanks for the fix Neil that seems to be working fine, it is no longer complaining about the mhsDLMembers being in binary.

    I do have a question about the LDIFReaderChangeRecordTranslator object that you've added. I looked at your example ValidateLDIF example and it seems that you are validating with the EntryValidator class but it requires an "Entry" argument in the isEntryValid() method. So I was wondering if it would work if I create an Entry object using a new Entry(LDIFChangeRecord.getDN()), or do you plan on also creating a change record version of the validator?

     
  • Neil Wilson

    Neil Wilson - 2015-09-01

    The com.unboundid.ldap.sdk.schema.EntryValidator class may be used to determine whether an entry conforms to a given schema. It provides support for a lot of different kinds of validation, including ensuring that all attribute types and object classes are defined in the schema, that all required attributes are present, that no prohibited attribute types are present, that attribute values conform to the expected syntax, that there is exactly one structural object class, that the DN complies with any appropriate name form definition, that single-valued attributes aren't given multiple values, etc.

    In general, this doesn't make any sense for LDIF change records, and especially not in isolation, because you often need more context than just what is in the change record.

    It could work for add change records because they do represent complete entries, but in that case you can just pass the entry returned by the LDIFAddChangeRecord.getEntryToAdd method to an EntryValidator.

    It doesn't make any sense for delete change records because you're deleting the entry and therefore there will be nothing to validate.

    For a modify change record, you can't really validate the modification in isolation because you need to know what the entry looks like before the modification so that you can determine whether the change will introduce any violations. If you can get the existing entry, then you can use the Entry.applyModifications method to see what the entry will look like after the changes are applied, and then you can use the EntryValidator to determine whether that is valid.

    A modify DN change record should also be treated mostly in the same way as a modify: get the entry, update it to reflect the new DN (and make any associated changes to the attributes in the entry), and pass the updated entry to an EntryValidator.

     

Log in to post a comment.