Bug #124

Clean phase of db2ldap deletes all entities

Added by Jérôme Schell 10 months ago. Updated 10 months ago.

Status:Feedback Start:13/10/2009
Priority:High Due date:
Assigned to:- % Done:

0%

Category:Documentation
Target version:-
Problem in version:

Description

During the clean phase of a db2ldap job, all entities in the destination are deleted.

After tracking the problem a bit, it seems that the method clean2Ldap of org.lsc.AbstractSynchronize loops on all destination entries and calls the getObject method of org.lsc.service.AbstractJdbcService passing it the id of the entry (to look for it in the source).
The problem is that the format of the id is the DN of the LDAP entry (uid=john.do,dc=mydomain,dc=com) and in the case of a JDBC source, that value is irrelevant.

History

Updated by Jonathan Clarke 10 months ago

Hi,

Thanks for the report. Which version are you seeing this on?

The id parameter that is passed to the JDBC source should be a structure containing a string (the DN you describe), and a map of parameter names and values that are passed into your SQL select query. Could you provide an extract of your configuration (dstService.*) and an extract of your sqlMap?

Thanks,
Jonathan

Updated by Jérôme Schell 10 months ago

Hi Jonathan,

I'm using v1.1.0.

I think I don't understand how Ibatis works ;)

After adding some debugging code, I have seen what you told about the parameters map. In my case the map contains the field "uid" with the good value for it. Nevertheless the source object is not found.

Here is some portions of my configuration.
lsc.properties:

lsc.tasks.mytask.srcService.pivotAttrs = uid
lsc.tasks.mytask.srcService = org.lsc.service.InetOrgPersonJDBCService
lsc.tasks.mytask.srcService.attrs = uid userPassword mail supannCivilite sn givenName birthDate promotion supannCodeINE street postalCode l homePhone mobile supannMailPerso jpegPhoto
...
lsc.tasks.mytask.dstService.pivotAttrs = uid
lsc.tasks.mytask.dstService.filterId = (&(objectClass=inetOrgPerson)(uid={logname}))
lsc.tasks.mytask.dstService.filterAll = (&(objectClass=inetOrgPerson))
lsc.tasks.mytask.dstService.baseDn = ou=people
lsc.tasks.mytask.dstService.attrs = uid userPassword mail sn givenName cn displayName objectClass street postalCode l homePhone mobile jpegPhoto ... 
lsc.tasks.mytask.dstService = org.lsc.jndi.SimpleJndiDstService

sql-map-config.d/InetOrgPerson.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">

<sqlMap namespace="InetOrgPersonJDBCService">

        <typeAlias alias="InetOrgPerson" type="org.lsc.objects.flat.fInetOrgPerson" />

        <resultMap id="InetOrgPersonResult" class="InetOrgPerson">
                <result property="uid" column="logname"/>
                <result property="userPassword" column="logpassw"/>
                <result property="mail" column="email"/>
                <result property="sn" column="nom"/>
                <result property="givenName" column="prenom"/>
                <result property="street" column="adrl1"/>
<!-- ...  -->
        </resultMap>
        <select id="getInetOrgPerson" resultMap="InetOrgPersonResult" parameterClass="java.util.Map">
                <!-- FILL IT, BE CAREFULL AT SPECIAL CHARACTER REPRESENTATION -->
                Select
                    ideleve,
                        logname,
                        logpassw,
                        nom,
                        prenom,
                        email,
                FROM mytable
                        WHERE logname = #logname#
        </select>
        <select id="getInetOrgPersonList" resultClass="java.util.HashMap">
                <!-- FILL IT, BE CAREFULL AT SPECIAL CHARACTER REPRESENTATION -->
                Select logname
                FROM mytable
                WHERE logname IS NOT NULL AND
                logname != "" 
        </select>

The sync phase is working ok with that configuration.

Updated by Jérôme Schell 10 months ago

I think the problem is in the name of the key attribute.
Correct me if I'm wrong...

During sync phase:
  • entries are retrieved from source (database)
  • loop is performed on the list and corresponding objects are search in the destination LDAP (method synchronize2Ldap of AbstractSynchronize)
  • getObject method of AbstractJdbcService is called with attribute map containing "logname = value"
  • it works ok
During clean phase:
  • entries are retrieved from destination (LDAP)
  • loop is performed on the list and corresponding objects are search in the source database (method clean2Ldap of AbstractSynchronize)
  • getObject method of AbstractJdbcService is called with attribute map containing "uid = value"
  • it doesn't work

So what should I put in lsc.properties or SQL map in order for this to work?

Updated by Jérôme Schell 10 months ago

I resolved my problem for now by renaming the key attribute in the database table to "uid" instead of "logname".
This way it all seems to work ok.

My primary interrogation is still valid. What is the good configuration to have the clean and sync phase working when the keys have different name in database and LDAP?

Updated by Jonathan Clarke 10 months ago

  • Category changed from Core to Documentation
  • Status changed from New to Feedback

Jérôme Schell wrote:

I resolved my problem for now by renaming the key attribute in the database table to "uid" instead of "logname". This way it all seems to work ok.

My primary interrogation is still valid. What is the good configuration to have the clean and sync phase working when the keys have different name in database and LDAP?

Hi Jérôme,

You are right about the problem here - the name of the pivot is different in sync and clean modes: you use logname to sync, and uid to clean. So when iBatis runs your getInetOrgPerson request, it only has a parameter uid, but doesn't use it.

The simplest solution is to change your SQL requests to use the "SELECT <DB pivot> AS <LDAP pivot>". For example, here, you would change getInetOrgPersonList to "Select logname AS uid ...", and getInetOrgPerson to "Select ... WHERE logname = #uid#". And of course remove uid from the resultMap. And, you should then change lsc.tasks.mytask.dstService.filterId to use {uid} instead of {logname}. Please let us know how it goes.

This is bug #35 (see the discussion there). As a general rule, I try to map all information to LDAP attribute names as soon as possible (in the SQL requests).

I think the documentation doesn't reflect this clearly (or at all). Any volunteers to update the wiki?

Jonathan

Updated by Jérôme Schell 10 months ago

Ok thanks Jonathan, this works.
Nevertheless, if I remove <result property="uid" column="uid"/> from the resultMap, I get a NPE:

0    - WARN  - Starting sync for mytask (db2ldap)
620  - ERROR - java.lang.NullPointerException
java.lang.NullPointerException
        at org.lsc.AbstractSynchronize.logActionError(AbstractSynchronize.java:476)
        at org.lsc.AbstractSynchronize.synchronize2Ldap(AbstractSynchronize.java:436)
        at org.lsc.SimpleSynchronize.launchTask(SimpleSynchronize.java:291)
        at org.lsc.SimpleSynchronize.launch(SimpleSynchronize.java:179)
        at org.lsc.Launcher.run(Launcher.java:125)
        at org.lsc.Launcher.main(Launcher.java:113)

When I leave it, it works.

Also available in: Atom PDF