[midPoint] Working around a constraint violation in user name?

Mikko Pekkarinen mikko.pekkarinen at datactica.fi
Tue Mar 28 15:56:42 CEST 2017


Hello,

I'm trying to synchronize users into midPoint. The names of the users are generated from the email address. The shadows are correlated to users using a separate GUID field in an extension.

Problem: when the resource contains 2 user accounts whose normalized email addresses are equal, my mappings fail. If there are accounts with identical emails, the iteration works as expected. That is:

 - Import 2 accounts with different GUIDs but same email "sauli.ahtisaari at rosvo.fi"  => 2 midPoint users created, with names
"sauli.ahtisaari at rosvo.fi" and "sauli.ahtisaari+1 at rosvo.fi".

- Import a third account with email "sauliahtisaari at rosvo.fi" (differs by a missing '.') => user is not created. Instead, getting an exception:
2017-03-28 12:55:31,177 [] [midPointScheduler_Worker-10] ERROR (com.evolveum.midpoint.model.impl.sync.SynchronizationServiceImpl): SYNCHRONIZATION: Error in synchronization on resource:43ec8c33-1d9d-4129-8ee4-80cfbac8eb46(Feikki-SAHA) for situation UNMATCHED: ObjectAlreadyExistsException: Conflicting object already exists (violated constraint 'uc_user_name'). Change was ResourceObjectShadowChangeDescription(objectDelta=null, currentShadow=shadow:584ddb51-9555-4f44-883d-72d1e97eee9b(c41bd105-73ec-515c-bb91-e57229fb0ac8), oldShadow=shadow:584ddb51-9555-4f44-883d-72d1e97eee9b(c41bd105-73ec-515c-bb91-e57229fb0ac8), sourceChannel=http://midpoint.evolveum.com/xml/ns/public/provisioning/channels-3#liveSync, resource=resource:43ec8c33-1d9d-4129-8ee4-80cfbac8eb46(Feikki-SAHA))
com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException: Conflicting object already exists (violated constraint 'uc_user_name')
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
...
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uc_user_name"
  Detail: Key (name_norm)=(sauliahtisaarirosvofi) already exists.
...


Some config:

Inbound mapping:
            <inbound>
               <name>User Name</name>
               <description>"name" is a mandatory attribute for midPoint Users. Getting error "No name in new object null as produced by template null in iteration 0,               we cannot process an object without a name" if it's not set." Therefore, setting it. Furthermore, the database schema requires that the field is unique => email is likely the best choice here.</description>
               <authoritative>true</authoritative>
               <exclusive>false</exclusive>
               <strength>weak</strength>
               <expression>
                  <script>
                     <code>return basic.toAscii(input)?.replaceFirst('@', sprintf("+%x@", new Random().nextInt(10000)));</code>
                  </script>
               </expression>
               <target>
                  <c:path>name</c:path>
               </target>
            </inbound>

(Putting a random token in the value here, or else the user creation fails already here, before the user template is processed. 
I know, this fails with probability 1/10000, but I can live with that. Iteration would be better, but that's not supported in inbound mappings?)

Object template:
   <mapping>
      <name>Generate unique midPoint username</name>
      <strength>strong</strength>
      <source>
         <c:path>emailAddress</c:path>
      </source>
      <expression>
         <script>
            <code>
            tmp = basic.toAscii(emailAddress);
            if (basic.isEmpty(iterationToken) || !tmp.contains('@')) {
                return tmp + iterationToken;
            } else {
                return tmp.replaceFirst('@', "+$iterationToken@");
            }
            </code>
         </script>
      </expression>
      <target>
         <c:path>name</c:path>
      </target>
      <condition>
         <script>
            <code>emailAddress != null</code>
         </script>
      </condition>

It seems that the iteration is only checking if the name is already in use, but it does not consider the unique constraint "uc_user_name" at all.
As a workaround I could probably use midpoint.searchObjects to check if a conflicting user already exists, but that seems expensive.
Any better ideas?


Mikko
   








More information about the midPoint mailing list