h2. Adding Entries Adding entries is one of the basic operations a user can do on a *LDAP* server. Nevertheless, such an operation implies a lot of checks, and frequently the user gets some weird error messages. We will see how we can add an entry using the *LDAP API*, and then analyze the different error cases we can face. h3. Adding an Entry We will first see the easiest way to add an entry into the server, assuming that the entry is correct. In order to add an entry, you only have to provide the place where this entry will be stored (its *[DIRAPI:Dn]*) and the list of its *[DIRAPI:Attribute]s*. Here are two examples where we inject the entry using *LDIF*: {code:java} @Test public void testAddLdif() throws Exception { AddResponse response = connection.add( new DefaultEntry( "cn=testadd,ou=system", // The Dn "ObjectClass: top", "ObjectClass: person", "cn: testadd_cn", "sn: testadd_sn" ) ); assertNotNull( response ); assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() ); assertTrue( session.exists( "cn=testadd,ou=system" ) ); } {code} In this basic example we are adding a new entry created using some *LDIF* formatted parameters, the first one being the entry's Dn. Note that it is possible to use some variables in the *LDIF* instead of pure text. Here is the same example resulting to the same entry being added: {code:java} @Test public void testAddLdif() throws Exception { String cn = "testadd_cn"; String sn = "testadd_sn"; AddResponse response = connection.add( new DefaultEntry( "cn=testadd,ou=system", // The Dn "ObjectClass: top", "ObjectClass: person", "cn", cn, // Note : there is no ':' when using a variable "sn", sn ) ); assertNotNull( response ); assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() ); assertTrue( session.exists( "cn=testadd,ou=system" ) ); } {code} Down the line, what is important is that the _add()_ operation is taking a full *[DIRAPI:Entry]*. We can also create the *[DIRAPI:Entry]* in a different way, which will be explained in the following paragraphs. h3. Sending an *[DIRAPI:AddRequest]* Sometimes, we want more control. We can ask the server to add an entry by sending an *[DIRAPI:AddRequest]*, which allows you to send a *[DIRAPI:Control]* simultaneously. Here is an example (note that the control is just injected to demonstrate the feature, it does nothing in this case): {code:java} @Test public void testAddWithControl() throws Exception { assertFalse( session.exists( "cn=testadd,ou=system" ) ); Entry entry = new DefaultEntry( "cn=testadd,ou=system", "ObjectClass : top", "ObjectClass : person", "cn: testadd_sn", "sn: testadd_sn" ); AddRequest addRequest = new AddRequestImpl(); addRequest.setEntry( entry ); addRequest.addControl( new ManageDsaITImpl() ); AddResponse response = connection.add( addRequest ); assertNotNull( response ); assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() ); assertTrue( session.exists( "cn=testadd,ou=system" ) ); } {code} h4. Asynchronous Addition Some may want to add an entry but will not check the result immediately. It's just a matter of calling the _addAsync()_ method, which will return a _Future_ that can be checked somewhere else in the code: {code:java} @Test public void testAddAsyncLdif() throws Exception { Entry entry = new DefaultEntry( "cn=testAsyncAdd,ou=system", "ObjectClass: top", "ObjectClass: person", "cn: testAsyncAdd_cn", "sn: testAsyncAdd_sn" ); assertFalse( session.exists( "cn=testAsyncAdd,ou=system" ) ); AddRequest addRequest = new AddRequestImpl(); addRequest.setEntry( entry ); AddFuture addFuture = connection.addAsync( addRequest ); // Here, we can do something else before checking that the entry has been added AddResponse addResponse = addFuture.get( 1000, TimeUnit.MILLISECONDS ); assertNotNull( addResponse ); assertEquals( ResultCodeEnum.SUCCESS, addResponse.getLdapResult().getResultCode() ); assertTrue( session.exists( "cn=testAsyncAdd,ou=system" ) ); } {code} h3. Do's and Don'ts Successfully adding an entry assumes that the entry is correct; i.e., that the attributes and the values are compatible with the schema. There are many things checked by the server. Here is a list of constraints that you should respect in order to get your entry injected: * The entry must have at least one *Structural* *[DIRAPI:ObjectClass]*. * If the entry has more than one *Structural* *[DIRAPI:ObjectClass]*, then they must be hierarchically related. * The *[DIRAPI:ObjectClass]es* define the list of allowed *Structural* *[DIRAPI:AttributeType]s* that can be used (*MAY* and *MUST*). * All the *MUST* *[DIRAPI:AttributeType]s* must be present. * Each added value must follow the *[DIRAPI:AttributeType]* *[DIRAPI:Syntax]*. * If the *[DIRAPI:AttributeType]* is single valued, then you can't add more than one value. * The entry's *[DIRAPI:Dn]* must have a parent * As a user you are not allowed to inject operational attributes, unless they have the *USER-MODIFICATION* flag set to true. There are also some other constraints, depending on the server, if it implements *[DIRAPI:NameForm]s*, *[DIRAPI:DITStructureRule]s* or *[DIRAPI:DITContentRule]s*. One other reason your entry can be rejected is that you don't have enough privileges to add it. You have to check that the server configuration allows you to add an entry where you want to add it. h3. Errors {note} At first, you might expect to get an exception if the entry addition has failed. If the server is rejecting the addition, *you will get NO exception*. Exceptions are only thrown client side if the entry is not built correctly, or if the connection is not opened. In any other case, the server will simply return a *[DIRAPI:LdapResult]* instance containing either *SUCCESS* or the cause of the rejection. {note} Usually, if you get an error while adding an entry, the message might be pretty tedious. Most of the cases it's because either your entry already exists, or because your entry has some schema violation. The *[DIRAPI:LdapResult]* in the response will give you a clue about what is going on.