diff --git a/src/main/java/sh/libre/scim/core/ScimDispatcher.java b/src/main/java/sh/libre/scim/core/ScimDispatcher.java
index 4146c3011963389d45dddecd3cd3bc65bb78f1fb..d3d675108bfd300398a80d9f97ecbf8115b15387 100644
--- a/src/main/java/sh/libre/scim/core/ScimDispatcher.java
+++ b/src/main/java/sh/libre/scim/core/ScimDispatcher.java
@@ -113,7 +113,7 @@ public class ScimDispatcher {
         if (matchingClient.isPresent()) {
             try {
                 operationToDispatch.acceptThrows(matchingClient.get());
-                LOGGER.infof("[SCIM] User operation dispatched to SCIM server %s", matchingClient.get().getConfiguration().getId());
+                LOGGER.infof("[SCIM] User operation dispatched to SCIM server %s", matchingClient.get().getConfiguration().getName());
             } catch (ScimPropagationException e) {
                 exceptionHandler.handleException(matchingClient.get().getConfiguration(), e);
             }
@@ -130,7 +130,7 @@ public class ScimDispatcher {
         if (matchingClient.isPresent()) {
             try {
                 operationToDispatch.acceptThrows(matchingClient.get());
-                LOGGER.infof("[SCIM] Group operation dispatched to SCIM server %s", matchingClient.get().getConfiguration().getId());
+                LOGGER.infof("[SCIM] Group operation dispatched to SCIM server %s", matchingClient.get().getConfiguration().getName());
             } catch (ScimPropagationException e) {
                 exceptionHandler.handleException(matchingClient.get().getConfiguration(), e);
             }
diff --git a/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java b/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java
index 0df9cedacc6fdaa73aae07d8f96772da7f75909b..23755fdfa0ec4d68eed9c3a49a2edd6197e88ccb 100644
--- a/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java
+++ b/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java
@@ -18,6 +18,7 @@ public class ScrimEndPointConfiguration {
 
     private final String endPoint;
     private final String id;
+    private final String name;
     private final String contentType;
     private final String authorizationHeaderValue;
     private final ImportAction importAction;
@@ -42,6 +43,7 @@ public class ScrimEndPointConfiguration {
             contentType = scimProviderConfiguration.get(CONF_KEY_CONTENT_TYPE, "");
             endPoint = scimProviderConfiguration.get(CONF_KEY_ENDPOINT, "");
             id = scimProviderConfiguration.getId();
+            name = scimProviderConfiguration.getName();
             importAction = ImportAction.valueOf(scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT_ACTION));
             pullFromScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT, false);
             pushToScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_REFRESH, false);
@@ -70,6 +72,10 @@ public class ScrimEndPointConfiguration {
         return id;
     }
 
+    public String getName() {
+        return name;
+    }
+
     public ImportAction getImportAction() {
         return importAction;
     }
diff --git a/src/main/java/sh/libre/scim/core/exceptions/InvalidResponseFromScimEndpointException.java b/src/main/java/sh/libre/scim/core/exceptions/InvalidResponseFromScimEndpointException.java
index 27c5c97b810621e588ae608207dee279b39344cb..079443622be9e2a9f77031e2b1a8c00b6ca557d3 100644
--- a/src/main/java/sh/libre/scim/core/exceptions/InvalidResponseFromScimEndpointException.java
+++ b/src/main/java/sh/libre/scim/core/exceptions/InvalidResponseFromScimEndpointException.java
@@ -2,16 +2,27 @@ package sh.libre.scim.core.exceptions;
 
 import de.captaingoldfish.scim.sdk.client.response.ServerResponse;
 
+import java.util.Optional;
+
 public class InvalidResponseFromScimEndpointException extends ScimPropagationException {
-    
-    private final ServerResponse response;
+
+    private final transient Optional<ServerResponse> response;
 
     public InvalidResponseFromScimEndpointException(ServerResponse response, String message) {
         super(message);
-        this.response = response;
+        this.response = Optional.of(response);
     }
 
-    public ServerResponse getResponse() {
+    public InvalidResponseFromScimEndpointException(String message, Exception e) {
+        super(message, e);
+        this.response = Optional.empty();
+    }
+
+
+    /**
+     * Empty response can occur if a major exception was thrown while retrying the request.
+     */
+    public Optional<ServerResponse> getResponse() {
         return response;
     }
 
diff --git a/src/main/java/sh/libre/scim/core/exceptions/RollbackApproach.java b/src/main/java/sh/libre/scim/core/exceptions/RollbackApproach.java
index aeca5e930c09e0dba3af6b48bf363a00b88ba604..d1fb108930679b91dc213e8e3d77b7c68b5313d0 100644
--- a/src/main/java/sh/libre/scim/core/exceptions/RollbackApproach.java
+++ b/src/main/java/sh/libre/scim/core/exceptions/RollbackApproach.java
@@ -40,10 +40,16 @@ public enum RollbackApproach implements RollbackStrategy {
         }
 
         private boolean shouldRollbackBecauseOfResponse(InvalidResponseFromScimEndpointException e) {
-            // We consider that 404 are acceptable, otherwise rollback
-            int httpStatus = e.getResponse().getHttpStatus();
-            ArrayList<Integer> acceptableStatus = Lists.newArrayList(200, 204, 404);
-            return !acceptableStatus.contains(httpStatus);
+            // If we have a response
+            return e.getResponse().map(r -> {
+                // We consider that 404 are acceptable, otherwise rollback
+                ArrayList<Integer> acceptableStatus = Lists.newArrayList(200, 204, 404);
+                return !acceptableStatus.contains(r.getHttpStatus());
+            }).orElse(
+                    // Never got an answer, server was either misconfigured or unreachable
+                    // No rollback in that case.
+                    false
+            );
         }
     }
 }
diff --git a/src/main/java/sh/libre/scim/core/exceptions/ScimExceptionHandler.java b/src/main/java/sh/libre/scim/core/exceptions/ScimExceptionHandler.java
index b525ae1279976b2c0829f30d1187ac30aa1a8d61..993f287ff5a2157ec936bce5a2624ff99144dd9e 100644
--- a/src/main/java/sh/libre/scim/core/exceptions/ScimExceptionHandler.java
+++ b/src/main/java/sh/libre/scim/core/exceptions/ScimExceptionHandler.java
@@ -32,10 +32,10 @@ public class ScimExceptionHandler {
      * @param e                         the occuring exception
      */
     public void handleException(ScrimEndPointConfiguration scimProviderConfiguration, ScimPropagationException e) {
-        String errorMessage = "[SCIM] Error while propagating to SCIM endpoint " + scimProviderConfiguration.getId();
+        String errorMessage = "[SCIM] Error while propagating to SCIM endpoint " + scimProviderConfiguration.getName();
         if (rollbackStrategy.shouldRollback(scimProviderConfiguration, e)) {
             session.getTransactionManager().rollback();
-            LOGGER.error(errorMessage, e);
+            LOGGER.error("TRANSACTION ROLLBACK - " + errorMessage, e);
         } else {
             LOGGER.warn(errorMessage);
         }
diff --git a/src/main/java/sh/libre/scim/core/exceptions/ScimPropagationException.java b/src/main/java/sh/libre/scim/core/exceptions/ScimPropagationException.java
index 7b1a747b2167bd19791965fd1e775c64328cdfe0..bee5ee18fdfb0babae5203f0559c6427cbff9bac 100644
--- a/src/main/java/sh/libre/scim/core/exceptions/ScimPropagationException.java
+++ b/src/main/java/sh/libre/scim/core/exceptions/ScimPropagationException.java
@@ -2,11 +2,11 @@ package sh.libre.scim.core.exceptions;
 
 public abstract class ScimPropagationException extends Exception {
 
-    public ScimPropagationException(String message) {
+    protected ScimPropagationException(String message) {
         super(message);
     }
 
-    public ScimPropagationException(String message, Exception e) {
+    protected ScimPropagationException(String message, Exception e) {
         super(message, e);
     }
 }
diff --git a/src/main/java/sh/libre/scim/core/service/GroupScimService.java b/src/main/java/sh/libre/scim/core/service/GroupScimService.java
index 5297acdac350b678e58e24f3893b27af8f1d5334..bd09f3e9b2442bad39b340eb59070eec278a244e 100644
--- a/src/main/java/sh/libre/scim/core/service/GroupScimService.java
+++ b/src/main/java/sh/libre/scim/core/service/GroupScimService.java
@@ -24,7 +24,7 @@ import java.util.TreeSet;
 import java.util.stream.Stream;
 
 public class GroupScimService extends AbstractScimService<GroupModel, Group> {
-    private final Logger LOGGER = Logger.getLogger(GroupScimService.class);
+    private static final Logger LOGGER = Logger.getLogger(GroupScimService.class);
 
     public GroupScimService(KeycloakSession keycloakSession, ScrimEndPointConfiguration scimProviderConfiguration, SkipOrStopStrategy skipOrStopStrategy) {
         super(keycloakSession, scimProviderConfiguration, ScimResourceType.GROUP, skipOrStopStrategy);
diff --git a/src/main/java/sh/libre/scim/core/service/ScimClient.java b/src/main/java/sh/libre/scim/core/service/ScimClient.java
index 7fcda9009173a7813e1236b1d15de0f32006b5cf..90bcfcf45987bcc9e7292155bd51daf2aa0bb4cc 100644
--- a/src/main/java/sh/libre/scim/core/service/ScimClient.java
+++ b/src/main/java/sh/libre/scim/core/service/ScimClient.java
@@ -29,7 +29,9 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
 
     private final ScimResourceType scimResourceType;
 
-    {
+    private ScimClient(ScimRequestBuilder scimRequestBuilder, ScimResourceType scimResourceType) {
+        this.scimRequestBuilder = scimRequestBuilder;
+        this.scimResourceType = scimResourceType;
         RetryConfig retryConfig = RetryConfig.custom()
                 .maxAttempts(10)
                 .intervalFunction(IntervalFunction.ofExponentialBackoff())
@@ -38,11 +40,6 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
         retryRegistry = RetryRegistry.of(retryConfig);
     }
 
-    private ScimClient(ScimRequestBuilder scimRequestBuilder, ScimResourceType scimResourceType) {
-        this.scimRequestBuilder = scimRequestBuilder;
-        this.scimResourceType = scimResourceType;
-    }
-
     public static ScimClient open(ScrimEndPointConfiguration scimProviderConfiguration, ScimResourceType scimResourceType) {
         String scimApplicationBaseUrl = scimProviderConfiguration.getEndPoint();
         Map<String, String> httpHeaders = new HashMap<>();
@@ -69,18 +66,23 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
                     "User to create should never have an existing id: %s %s".formatted(id, scimForCreationId.get())
             );
         }
-        // TODO Exception handling : check that all exceptions are wrapped in server response
-        Retry retry = retryRegistry.retry("create-%s".formatted(id.asString()));
-        ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
-                .create(getResourceClass(), getScimEndpoint())
-                .setResource(scimForCreation)
-                .sendRequest()
-        );
-        checkResponseIsSuccess(response);
-        S resource = response.getResource();
-        return resource.getId()
-                .map(EntityOnRemoteScimId::new)
-                .orElseThrow(() -> new InvalidResponseFromScimEndpointException(response, "Created SCIM resource does not have id"));
+        try {
+            Retry retry = retryRegistry.retry("create-%s".formatted(id.asString()));
+            ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
+                    .create(getResourceClass(), getScimEndpoint())
+                    .setResource(scimForCreation)
+                    .sendRequest()
+            );
+            checkResponseIsSuccess(response);
+            S resource = response.getResource();
+            return resource.getId()
+                    .map(EntityOnRemoteScimId::new)
+                    .orElseThrow(() -> new InvalidResponseFromScimEndpointException(response, "Created SCIM resource does not have id"));
+
+        } catch (Exception e) {
+            LOGGER.warn(e);
+            throw new InvalidResponseFromScimEndpointException("Exception while retrying create " + e.getMessage(), e);
+        }
     }
 
     private void checkResponseIsSuccess(ServerResponse<S> response) throws InvalidResponseFromScimEndpointException {
@@ -99,23 +101,31 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
 
     public void update(EntityOnRemoteScimId externalId, S scimForReplace) throws InvalidResponseFromScimEndpointException {
         Retry retry = retryRegistry.retry("replace-%s".formatted(externalId.asString()));
-        // TODO Exception handling : check that all exceptions are wrapped in server response
-        ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
-                .update(getResourceClass(), getScimEndpoint(), externalId.asString())
-                .setResource(scimForReplace)
-                .sendRequest()
-        );
-        checkResponseIsSuccess(response);
+        try {
+            ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
+                    .update(getResourceClass(), getScimEndpoint(), externalId.asString())
+                    .setResource(scimForReplace)
+                    .sendRequest()
+            );
+            checkResponseIsSuccess(response);
+        } catch (Exception e) {
+            LOGGER.warn(e);
+            throw new InvalidResponseFromScimEndpointException("Exception while retrying update " + e.getMessage(), e);
+        }
     }
 
     public void delete(EntityOnRemoteScimId externalId) throws InvalidResponseFromScimEndpointException {
         Retry retry = retryRegistry.retry("delete-%s".formatted(externalId.asString()));
-        // TODO Exception handling : check that all exceptions are wrapped in server response
-        ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
-                .delete(getResourceClass(), getScimEndpoint(), externalId.asString())
-                .sendRequest()
-        );
-        checkResponseIsSuccess(response);
+        try {
+            ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
+                    .delete(getResourceClass(), getScimEndpoint(), externalId.asString())
+                    .sendRequest()
+            );
+            checkResponseIsSuccess(response);
+        } catch (Exception e) {
+            LOGGER.warn(e);
+            throw new InvalidResponseFromScimEndpointException("Exception while retrying delete " + e.getMessage(), e);
+        }
     }
 
     @Override
diff --git a/src/main/java/sh/libre/scim/core/service/UserScimService.java b/src/main/java/sh/libre/scim/core/service/UserScimService.java
index cfd4a826ada5a9da1c5c71cb54b865d7be41c640..c0262f3d4aeb0b8fca2ea1c397850d1c845c7a8d 100644
--- a/src/main/java/sh/libre/scim/core/service/UserScimService.java
+++ b/src/main/java/sh/libre/scim/core/service/UserScimService.java
@@ -20,11 +20,12 @@ import sh.libre.scim.core.exceptions.UnexpectedScimDataException;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Stream;
 
 public class UserScimService extends AbstractScimService<UserModel, User> {
-    private final Logger LOGGER = Logger.getLogger(UserScimService.class);
+    private static final Logger LOGGER = Logger.getLogger(UserScimService.class);
 
     public UserScimService(
             KeycloakSession keycloakSession,
@@ -56,7 +57,9 @@ public class UserScimService extends AbstractScimService<UserModel, User> {
         if (matchedByUsername.isPresent()
             && matchedByEmail.isPresent()
             && !matchedByUsername.equals(matchedByEmail)) {
-            throw new InconsistentScimMappingException("Found 2 possible users for remote user " + matchedByUsername.get() + " - " + matchedByEmail.get());
+            String inconstencyErrorMessage = "Found 2 possible users for remote user " + matchedByUsername.get() + " - " + matchedByEmail.get();
+            LOGGER.warn(inconstencyErrorMessage);
+            throw new InconsistentScimMappingException(inconstencyErrorMessage);
         }
         if (matchedByUsername.isPresent()) {
             return matchedByUsername;
@@ -94,12 +97,12 @@ public class UserScimService extends AbstractScimService<UserModel, User> {
         String firstAndLastName = String.format("%s %s",
                 StringUtils.defaultString(roleMapperModel.getFirstName()),
                 StringUtils.defaultString(roleMapperModel.getLastName())).trim();
-        String displayName = StringUtils.defaultString(firstAndLastName, roleMapperModel.getUsername());
+        String displayName = Objects.toString(firstAndLastName, roleMapperModel.getUsername());
         Stream<RoleModel> groupRoleModels = roleMapperModel.getGroupsStream().flatMap(RoleMapperModel::getRoleMappingsStream);
         Stream<RoleModel> roleModels = roleMapperModel.getRoleMappingsStream();
         Stream<RoleModel> allRoleModels = Stream.concat(groupRoleModels, roleModels);
         List<PersonRole> roles = allRoleModels
-                .filter((r) -> BooleanUtils.TRUE.equals(r.getFirstAttribute("scim")))
+                .filter(r -> BooleanUtils.TRUE.equals(r.getFirstAttribute("scim")))
                 .map(RoleModel::getName)
                 .map(roleName -> {
                     PersonRole personRole = new PersonRole();
diff --git a/src/main/java/sh/libre/scim/event/ScimBackgroundGroupMembershipUpdater.java b/src/main/java/sh/libre/scim/event/ScimBackgroundGroupMembershipUpdater.java
index d7a0731573135672a450d48ec3b850309372aed4..4c49f74f671b1679698bc3c5710e5eb6d9b9f171 100644
--- a/src/main/java/sh/libre/scim/event/ScimBackgroundGroupMembershipUpdater.java
+++ b/src/main/java/sh/libre/scim/event/ScimBackgroundGroupMembershipUpdater.java
@@ -63,7 +63,7 @@ public class ScimBackgroundGroupMembershipUpdater {
     private boolean isDirtyGroup(GroupModel g) {
         String groupDirtySinceAttribute = g.getFirstAttribute(GROUP_DIRTY_SINCE_ATTRIBUTE_NAME);
         try {
-            int groupDirtySince = Integer.parseInt(groupDirtySinceAttribute);
+            long groupDirtySince = Long.parseLong(groupDirtySinceAttribute);
             // Must be dirty for more than DEBOUNCE_DELAY_MS
             // (otherwise update will be dispatched in next scheduled loop)
             return System.currentTimeMillis() - groupDirtySince > DEBOUNCE_DELAY_MS;
diff --git a/src/main/java/sh/libre/scim/jpa/ScimResourceDao.java b/src/main/java/sh/libre/scim/jpa/ScimResourceDao.java
index 3824ad44d89ebfc014584963ea490af1863cc1c2..4deec373b952c59c333974b645fa276b9cc37d4a 100644
--- a/src/main/java/sh/libre/scim/jpa/ScimResourceDao.java
+++ b/src/main/java/sh/libre/scim/jpa/ScimResourceDao.java
@@ -91,7 +91,6 @@ public class ScimResourceDao {
     }
 
     public void delete(ScimResourceMapping resource) {
-        EntityManager entityManager = getEntityManager();
         entityManager.remove(resource);
     }
 }
diff --git a/src/main/java/sh/libre/scim/jpa/ScimResourceMapping.java b/src/main/java/sh/libre/scim/jpa/ScimResourceMapping.java
index fabd266444cff6e9fe235658f293a270254688fa..ade6848ccd2e8aea7df643bb78554e375a166b68 100644
--- a/src/main/java/sh/libre/scim/jpa/ScimResourceMapping.java
+++ b/src/main/java/sh/libre/scim/jpa/ScimResourceMapping.java
@@ -14,8 +14,8 @@ import sh.libre.scim.core.service.KeycloakId;
 @IdClass(ScimResourceId.class)
 @Table(name = "SCIM_RESOURCE_MAPPING")
 @NamedQueries({
-        @NamedQuery(name = "findById", query = "from ScimResource where realmId = :realmId and componentId = :componentId and type = :type and id = :id"),
-        @NamedQuery(name = "findByExternalId", query = "from ScimResource where realmId = :realmId and componentId = :componentId and type = :type and externalId = :id")
+        @NamedQuery(name = "findById", query = "from ScimResourceMapping where realmId = :realmId and componentId = :componentId and type = :type and id = :id"),
+        @NamedQuery(name = "findByExternalId", query = "from ScimResourceMapping where realmId = :realmId and componentId = :componentId and type = :type and externalId = :id")
 })
 public class ScimResourceMapping {
 
diff --git a/src/main/java/sh/libre/scim/jpa/ScimResourceProvider.java b/src/main/java/sh/libre/scim/jpa/ScimResourceProvider.java
index 3dc284e22fffaf86fb1d63ab560521998fef62f2..6ef55a060e10945b5eb017559ea9b9c794122381 100644
--- a/src/main/java/sh/libre/scim/jpa/ScimResourceProvider.java
+++ b/src/main/java/sh/libre/scim/jpa/ScimResourceProvider.java
@@ -19,6 +19,7 @@ public class ScimResourceProvider implements JpaEntityProvider {
 
     @Override
     public void close() {
+        // Nothing to close
     }
 
     @Override
diff --git a/src/main/resources/META-INF/scim-resource-changelog.xml b/src/main/resources/META-INF/scim-resource-changelog.xml
index cf300faad5cfb49c61d047f5c1b2f3e1d169d310..d3e2687a57b42ea71b1f9e2bb848b9c4da56cca4 100644
--- a/src/main/resources/META-INF/scim-resource-changelog.xml
+++ b/src/main/resources/META-INF/scim-resource-changelog.xml
@@ -22,13 +22,13 @@
             </column>
         </createTable>
 
-        <addPrimaryKey constraintName="PK_SCIM_RESOURCE" tableName="SCIM_RESOURCE"
+        <addPrimaryKey constraintName="PK_SCIM_RESOURCE_MAPPING" tableName="SCIM_RESOURCE_MAPPING"
                        columnNames="ID,REALM_ID,TYPE,COMPONENT_ID,EXTERNAL_ID"/>
-        <addForeignKeyConstraint baseTableName="SCIM_RESOURCE" baseColumnNames="REALM_ID"
-                                 constraintName="FK_SCIM_RESOURCE_REALM" referencedTableName="REALM"
+        <addForeignKeyConstraint baseTableName="SCIM_RESOURCE_MAPPING" baseColumnNames="REALM_ID"
+                                 constraintName="FK_SCIM_RESOURCE_MAPPING_REALM" referencedTableName="REALM"
                                  referencedColumnNames="ID" onDelete="CASCADE" onUpdate="CASCADE"/>
-        <addForeignKeyConstraint baseTableName="SCIM_RESOURCE" baseColumnNames="COMPONENT_ID"
-                                 constraintName="FK_SCIM_RESOURCE_COMPONENT" referencedTableName="COMPONENT"
+        <addForeignKeyConstraint baseTableName="SCIM_RESOURCE_MAPPING" baseColumnNames="COMPONENT_ID"
+                                 constraintName="FK_SCIM_RESOURCE_MAPPING_COMPONENT" referencedTableName="COMPONENT"
                                  referencedColumnNames="ID" onDelete="CASCADE" onUpdate="CASCADE"/>
     </changeSet>