Hello,
In a Spring Boot 2.1.6 project I'm using the embedded LDAP service (UnboundID LDAP). I need to define new attribute types and object classes. My LDIF file contains something like that:
However, when I deploy my WAR on tomcat I get this exception:
org.springframework.beans.factory.BeanCreationException:Errorcreatingbeanwithname'directoryServer'definedinclasspathresource[org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfiguration.class]:Beaninstantiationviafactorymethodfailed;nestedexceptionisorg.springframework.beans.BeanInstantiationException:Failedtoinstantiate[com.unboundid.ldap.listener.InMemoryDirectoryServer]:Factorymethod'directoryServer'threwexception;nestedexceptionisjava.lang.IllegalStateException:UnabletoloadLDIFclasspath:test.ldif...Causedby:org.springframework.beans.BeanInstantiationException:Failedtoinstantiate[com.unboundid.ldap.listener.InMemoryDirectoryServer]:Factorymethod'directoryServer'threwexception;nestedexceptionisjava.lang.IllegalStateException:UnabletoloadLDIFclasspath:test.ldif...Causedby:LDAPException(resultCode=68(entryalreadyexists),errorMessage='Unable to add an entry with a DN that is the same as or subordinate to the subschema subentry DN 'cn=schema'.',ldapSDKVersion=4.0.11,revision=34e39aab27ea4fb92659a6888933db08099c7e41)atcom.unboundid.ldap.listener.InMemoryRequestHandler.addEntry(InMemoryRequestHandler.java:4916)atcom.unboundid.ldap.listener.InMemoryRequestHandler.importFromLDIF(InMemoryRequestHandler.java:4624)atcom.unboundid.ldap.listener.InMemoryDirectoryServer.importFromLDIF(InMemoryDirectoryServer.java:1255)atorg.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration.importLdif(EmbeddedLdapAutoConfiguration.java:164)...76more
What happens obviously is that, for some reason, the LDAP service "thinks" that I'm trying to ad the entry "cn=schema", and refuses the operation as the entry already exists, while I'm trying to modify it, hence the statememnt "changetype: modify" in the LDIF file.
Could someone please advise me what I'm doing wrong ?
Many thanks in advance.
Kind regards,
Nicolas
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It sounds like you're trying to import the file rather than apply the changes it contains. An LDIF import can only be used to create entries in the server, and cannot be used with change records.
If you want to get custom schema into the in-memory directory server, you have a few options:
You could use use the InMemoryDirectoryServer.applyChangesFromLDIF method, which does allow you to apply changes read from an LDIF file.
If you'd rather have the changes in code rather than in an LDIF file, then you could use the InMemoryDirectoryServer.modify method to apply the change.
If you want to have custom schema loaded into the server when it starts, you can use the InMemoryDirectoryServerConfig.setSchema method before creating the directory server instance. Note that in that case, you need to provide the entire schema you want to use rather than just the custom elements.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Neil,
Many thanks for your answer. I think that the 3rd scenario would be the most appropriated, however, as mentioned in the post, I'm using Spring Boot. Accordingly, I'm not creating at any point any directory server as these details are automatically provided by the framework. The only thing I have to do is to set the following two properties: spring.ldap.embedded.ldif: the name of the file, on the classpath, containing the directory data spring.ldap.embedded.validate.schema: the name of the custom schema I want the embedded LDAP service to use.
So I used the schema file that comes with you distribution (standard-schema. ldif) and I used it as the value of the spring.ldap.embedded.validate.schema property, after having adjusted such to add somme new attributes and object classes, for example:
NAME 'customAttribute'
EQUALITY caseIgnoreMatch
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
...
objectClasses: ( 2.5.6.6
NAME 'person'
SUP top
STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $
telephoneNumber $
seeAlso $
description $
customAttribute )
Here I added customAttribute to the person object class. I don't know whether the modified schema is loaded but using the new attribute in the directory data, for example:
raises an exception saying the customeAttribute is not defined in the current schema. So I would like to use the InMemoryDirectoryServerConfig.setSchema () as you advised but I don't know how to wire it as I'm not handling any instance of the directory service in the code.
Could you please shade some light here ? Many thanks in advance.
Kind regards,
Nicolas
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm sorry, but I don't know anything about Spring Boot or how they're using the LDAP SDK.
However, assuming that you have the ability to get a connection to the server once it has been created, you can alter the schema after the fact by applying a modification, like:
You can do the same with object classes (using the "objectClasses" attribute instead of "attributeTypes"). However, in your case it looks like you're trying to alter a standard object class, which is really not a good idea. You should create a custom object class that extends the standard one and then include that object class in your entry. In your case, it looks like you want your custom object class to inherit from inetOrgPerson rather than person. You could do that like:
Thanks again for your reply. I'll try that but I would prefer to put the attributes/objectclasses definition in an LDIF file and load it. The applyChangesFromLdif() method seems to be what I need, right ? Supposing that I'm able to get the connection object, would it be a way to use it ?
Kind regards,
Nicolas
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Unfortunately, the InMemoryDirectoryServer.applyChangesFromLDIF method isn't one that you can use with a connection. However, you can accomplish the same thing with code like the following:
Hello,
In a Spring Boot 2.1.6 project I'm using the embedded LDAP service (UnboundID LDAP). I need to define new attribute types and object classes. My LDIF file contains something like that:
However, when I deploy my WAR on tomcat I get this exception:
What happens obviously is that, for some reason, the LDAP service "thinks" that I'm trying to ad the entry "cn=schema", and refuses the operation as the entry already exists, while I'm trying to modify it, hence the statememnt "changetype: modify" in the LDIF file.
Could someone please advise me what I'm doing wrong ?
Many thanks in advance.
Kind regards,
Nicolas
It sounds like you're trying to import the file rather than apply the changes it contains. An LDIF import can only be used to create entries in the server, and cannot be used with change records.
If you want to get custom schema into the in-memory directory server, you have a few options:
Hi Neil,
Many thanks for your answer. I think that the 3rd scenario would be the most appropriated, however, as mentioned in the post, I'm using Spring Boot. Accordingly, I'm not creating at any point any directory server as these details are automatically provided by the framework. The only thing I have to do is to set the following two properties:
spring.ldap.embedded.ldif: the name of the file, on the classpath, containing the directory data
spring.ldap.embedded.validate.schema: the name of the custom schema I want the embedded LDAP service to use.
So I used the schema file that comes with you distribution (standard-schema. ldif) and I used it as the value of the spring.ldap.embedded.validate.schema property, after having adjusted such to add somme new attributes and object classes, for example:
NAME 'customAttribute'
EQUALITY caseIgnoreMatch
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
...
objectClasses: ( 2.5.6.6
NAME 'person'
SUP top
STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $
telephoneNumber $
seeAlso $
description $
customAttribute )
Here I added customAttribute to the person object class. I don't know whether the modified schema is loaded but using the new attribute in the directory data, for example:
raises an exception saying the customeAttribute is not defined in the current schema. So I would like to use the InMemoryDirectoryServerConfig.setSchema () as you advised but I don't know how to wire it as I'm not handling any instance of the directory service in the code.
Could you please shade some light here ? Many thanks in advance.
Kind regards,
Nicolas
I'm sorry, but I don't know anything about Spring Boot or how they're using the LDAP SDK.
However, assuming that you have the ability to get a connection to the server once it has been created, you can alter the schema after the fact by applying a modification, like:
You can do the same with object classes (using the "objectClasses" attribute instead of "attributeTypes"). However, in your case it looks like you're trying to alter a standard object class, which is really not a good idea. You should create a custom object class that extends the standard one and then include that object class in your entry. In your case, it looks like you want your custom object class to inherit from inetOrgPerson rather than person. You could do that like:
And then you could add your test user like:
Hi Neil,
Thanks again for your reply. I'll try that but I would prefer to put the attributes/objectclasses definition in an LDIF file and load it. The applyChangesFromLdif() method seems to be what I need, right ? Supposing that I'm able to get the connection object, would it be a way to use it ?
Kind regards,
Nicolas
Unfortunately, the InMemoryDirectoryServer.applyChangesFromLDIF method isn't one that you can use with a connection. However, you can accomplish the same thing with code like the following:
Thank you Neil.
Kind regards,
Nicolas