You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by bd...@apache.org on 2022/09/15 23:05:58 UTC

[directory-scimple] 01/01: Move ScimExtensionRegistry logic into SchemaRegistry

This is an automated email from the ASF dual-hosted git repository.

bdemers pushed a commit to branch remove-ext-reg
in repository https://gitbox.apache.org/repos/asf/directory-scimple.git

commit 62010d859d1d74db6d79ac776ee81a402d7d50f7
Author: Brian Demers <bd...@apache.org>
AuthorDate: Fri Sep 9 20:45:58 2022 -0400

    Move ScimExtensionRegistry logic into SchemaRegistry
    
    Move ResourceType generation into SchemaRegistry
---
 .../directory/scim/core/repository/Repository.java |  5 +-
 .../scim/core/repository/RepositoryRegistry.java   | 64 +---------------
 .../extensions/ScimExtensionRegistryProducer.java  | 33 ---------
 .../directory/scim/core/schema/SchemaRegistry.java | 85 ++++++++++++++++++++--
 .../core/repository/RepositoryRegistryTest.java    | 10 +--
 .../repository/RepositorySchemaRegistryTest.java   |  2 +-
 .../scim/core/schema/SchemaRegistryTest.java       | 20 +++--
 .../scim/server/rest/BulkResourceImpl.java         |  4 +-
 .../scim/server/rest/ObjectMapperFactory.java      | 16 +++-
 .../scim/server/rest/ScimResourceDeserializer.java |  2 +-
 .../scim/server/rest/BulkResourceImplTest.java     |  5 +-
 .../scim/server/rest/ObjectMapperFactoryTest.java  | 12 +--
 .../scim/spec/extension/ScimExtensionRegistry.java | 74 -------------------
 .../scim/spec/resources/ScimResource.java          |  4 -
 14 files changed, 120 insertions(+), 216 deletions(-)

diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
index 36283801..942f68b0 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
@@ -19,6 +19,7 @@
 
 package org.apache.directory.scim.core.repository;
 
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.directory.scim.spec.exception.ResourceException;
@@ -117,5 +118,7 @@ public interface Repository<T extends ScimResource> {
    * @throws ResourceException If the repository cannot return
    *         the appropriate list.
    */
-  List<Class<? extends ScimExtension>> getExtensionList() throws ResourceException;
+  default List<Class<? extends ScimExtension>> getExtensionList() throws ResourceException {
+    return Collections.emptyList();
+  }
 }
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java
index f2db29f5..02cab32b 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/RepositoryRegistry.java
@@ -25,18 +25,12 @@ import jakarta.inject.Inject;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.directory.scim.core.Initializable;
-import org.apache.directory.scim.spec.annotation.ScimExtensionType;
-import org.apache.directory.scim.spec.annotation.ScimResourceType;
 import org.apache.directory.scim.spec.exception.ResourceException;
 import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
-import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
 import org.apache.directory.scim.spec.resources.ScimExtension;
 import org.apache.directory.scim.spec.resources.ScimResource;
-import org.apache.directory.scim.spec.schema.ResourceType;
 import org.apache.directory.scim.core.schema.SchemaRegistry;
-import org.apache.directory.scim.spec.schema.Schemas;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -48,8 +42,6 @@ public class RepositoryRegistry implements Initializable {
 
   private SchemaRegistry schemaRegistry;
 
-  private ScimExtensionRegistry scimExtensionRegistry;
-
   // Weld needs the '? extends' or the repositories will not be found, some CDI
   // implementations work fine with just <ScimResources>
   private Instance<Repository<? extends ScimResource>> scimRepositoryInstances;
@@ -57,9 +49,8 @@ public class RepositoryRegistry implements Initializable {
   private Map<Class<? extends ScimResource>, Repository<? extends ScimResource>> repositoryMap = new HashMap<>();
 
   @Inject
-  public RepositoryRegistry(SchemaRegistry schemaRegistry, ScimExtensionRegistry scimExtensionRegistry, Instance<Repository<? extends ScimResource>> scimRepositoryInstances) {
+  public RepositoryRegistry(SchemaRegistry schemaRegistry, Instance<Repository<? extends ScimResource>> scimRepositoryInstances) {
     this.schemaRegistry = schemaRegistry;
-    this.scimExtensionRegistry = scimExtensionRegistry;
     this.scimRepositoryInstances = scimRepositoryInstances;
   }
 
@@ -80,20 +71,10 @@ public class RepositoryRegistry implements Initializable {
   }
 
   public synchronized <T extends ScimResource> void registerRepository(Class<T> clazz, Repository<T> repository) throws InvalidRepositoryException, ResourceException {
-
-    ResourceType resourceType = generateResourceType(clazz, repository);
-
     List<Class<? extends ScimExtension>> extensionList = repository.getExtensionList();
 
     log.debug("Calling addSchema on the base class: {}", clazz);
-    schemaRegistry.addSchema(clazz, resourceType, extensionList);
-
-    if (extensionList != null) {
-      for (Class<? extends ScimExtension> scimExtension : extensionList) {
-        log.debug("Registering a extension of type: " + scimExtension);
-        scimExtensionRegistry.registerExtension(clazz, scimExtension);
-      }
-    }
+    schemaRegistry.addSchema(clazz, extensionList);
     repositoryMap.put(clazz, repository);
   }
 
@@ -101,45 +82,4 @@ public class RepositoryRegistry implements Initializable {
   public <T extends ScimResource> Repository<T> getRepository(Class<T> clazz) {
     return (Repository<T>) repositoryMap.get(clazz);
   }
-
-  private ResourceType generateResourceType(Class<? extends ScimResource> base, Repository<? extends ScimResource> repository) throws InvalidRepositoryException, ResourceException {
-
-    ScimResourceType scimResourceType = base.getAnnotation(ScimResourceType.class);
-
-    if (scimResourceType == null) {
-      throw new InvalidRepositoryException("Missing annotation: @ScimResourceType must be at the top of scim resource classes");
-    }
-
-    ResourceType resourceType = new ResourceType();
-    resourceType.setDescription(scimResourceType.description());
-    resourceType.setId(scimResourceType.id());
-    resourceType.setName(scimResourceType.name());
-    resourceType.setEndpoint(scimResourceType.endpoint());
-    resourceType.setSchemaUrn(scimResourceType.schema());
-
-    List<Class<? extends ScimExtension>> extensionList = repository.getExtensionList();
-
-    if (extensionList != null) {
-
-      List<ResourceType.SchemaExtentionConfiguration> extensionSchemaList = new ArrayList<>();
-
-      for (Class<? extends ScimExtension> se : extensionList) {
-
-        ScimExtensionType extensionType = se.getAnnotation(ScimExtensionType.class);
-
-        if (extensionType == null) {
-          throw new InvalidRepositoryException("Missing annotation: ScimExtensionType must be at the top of scim extension classes");
-        }
-
-        ResourceType.SchemaExtentionConfiguration ext = new ResourceType.SchemaExtentionConfiguration();
-        ext.setRequired(extensionType.required());
-        ext.setSchemaUrn(extensionType.id());
-        extensionSchemaList.add(ext);
-      }
-
-      resourceType.setSchemaExtensions(extensionSchemaList);
-    }
-
-    return resourceType;
-  }
 }
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/extensions/ScimExtensionRegistryProducer.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/extensions/ScimExtensionRegistryProducer.java
deleted file mode 100644
index a26f1740..00000000
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/extensions/ScimExtensionRegistryProducer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
- 
-* http://www.apache.org/licenses/LICENSE-2.0
-
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-package org.apache.directory.scim.core.repository.extensions;
-
-import jakarta.enterprise.inject.Produces;
-
-import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
-
-public class ScimExtensionRegistryProducer {
-
-  @Produces
-  public ScimExtensionRegistry produceScimExtensionRegistry() {
-    return ScimExtensionRegistry.getInstance();
-  }
-  
-}
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java b/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java
index 37e5a0c5..18578352 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/schema/SchemaRegistry.java
@@ -22,7 +22,9 @@ package org.apache.directory.scim.core.schema;
 import java.util.*;
 
 import jakarta.enterprise.context.ApplicationScoped;
+import org.apache.directory.scim.spec.annotation.ScimExtensionType;
 import org.apache.directory.scim.spec.annotation.ScimResourceType;
+import org.apache.directory.scim.spec.exception.InvalidExtensionException;
 import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
 import org.apache.directory.scim.spec.resources.ScimExtension;
 import org.apache.directory.scim.spec.resources.ScimResource;
@@ -35,13 +37,15 @@ import org.apache.directory.scim.spec.schema.Schemas;
 @ApplicationScoped
 public class SchemaRegistry {
 
-  private Map<String, Schema> schemaMap = new HashMap<>();
+  private final Map<String, Schema> schemaMap = new HashMap<>();
   
-  private Map<String, Class<? extends ScimResource>> schemaUrnToScimResourceClass = new HashMap<>();
+  private final Map<String, Class<? extends ScimResource>> schemaUrnToScimResourceClass = new HashMap<>();
 
-  private Map<String, Class<? extends ScimResource>> endpointToScimResourceClass = new HashMap<>();
+  private final Map<String, Class<? extends ScimResource>> endpointToScimResourceClass = new HashMap<>();
 
-  private Map<String, ResourceType> resourceTypeMap = new HashMap<>();
+  private final Map<String, ResourceType> resourceTypeMap = new HashMap<>();
+
+  private final Map<Class<? extends ScimResource>, Map<String, Class<? extends ScimExtension>>> resourceExtensionsMap = new HashMap<>();
 
   public Schema getSchema(String urn) {
     return schemaMap.get(urn);
@@ -70,13 +74,15 @@ public class SchemaRegistry {
     schemaMap.put(schema.getId(), schema);
   }
 
-  public <T extends ScimResource> void addSchema(Class<T> clazz, ResourceType resourceType, List<Class<? extends ScimExtension>> extensionList) {
+  public <T extends ScimResource> void addSchema(Class<T> clazz, List<Class<? extends ScimExtension>> extensionList) {
 
     ScimResourceType scimResourceType = clazz.getAnnotation(ScimResourceType.class);
     if (scimResourceType == null) {
       throw new ScimResourceInvalidException("Missing annotation: ScimResource must be annotated with @ScimResourceType.");
     }
 
+    ResourceType resourceType = generateResourceType(scimResourceType, extensionList);
+
     String schemaUrn = scimResourceType.schema();
     String endpoint = scimResourceType.endpoint();
 
@@ -89,6 +95,8 @@ public class SchemaRegistry {
       for (Class<? extends ScimExtension> scimExtension : extensionList) {
         log.debug("Calling addSchema on an extension: " + scimExtension);
         addSchema(Schemas.schemaForExtension(scimExtension));
+        log.debug("Registering a extension of type: " + scimExtension);
+        addExtension(clazz, scimExtension);
       }
     }
   }
@@ -101,14 +109,14 @@ public class SchemaRegistry {
     endpointToScimResourceClass.put(endpoint, scimResourceClass);
   }
 
-  public <T extends ScimResource> Class<T> findScimResourceClassFromEndpoint(String endpoint) {
+  public <T extends ScimResource> Class<T> getScimResourceClassFromEndpoint(String endpoint) {
     @SuppressWarnings("unchecked")
     Class<T> scimResourceClass = (Class<T>) endpointToScimResourceClass.get(endpoint);
 
     return scimResourceClass;
   }
 
-  public <T extends ScimResource> Class<T> findScimResourceClass(String schemaUrn) {
+  public <T extends ScimResource> Class<T> getScimResourceClass(String schemaUrn) {
     @SuppressWarnings("unchecked")
     Class<T> scimResourceClass = (Class<T>) schemaUrnToScimResourceClass.get(schemaUrn);
 
@@ -126,4 +134,67 @@ public class SchemaRegistry {
   private void addResourceType(ResourceType resourceType) {
     resourceTypeMap.put(resourceType.getName(), resourceType);
   }
+
+  public Class<? extends ScimExtension> getExtensionClass(Class<? extends ScimResource> resourceClass, String urn) {
+    Class<? extends ScimExtension> extensionClass = null;
+    if(resourceExtensionsMap.containsKey(resourceClass)) {
+      Map<String, Class<? extends ScimExtension>> resourceMap = resourceExtensionsMap.get(resourceClass);
+      if(resourceMap.containsKey(urn)) {
+        extensionClass = resourceMap.get(urn);
+      }
+    }
+    return extensionClass;
+  }
+
+  public void addExtension(Class<? extends ScimResource> resourceClass, Class<? extends ScimExtension> extensionClass) {
+    ScimExtensionType[] se = extensionClass.getAnnotationsByType(ScimExtensionType.class);
+
+    if (se.length != 1) {
+      throw new InvalidExtensionException("Registered extensions must a single @ScimExtensionType annotation");
+    }
+
+    String urn = se[0].id();
+
+    log.debug("Registering extension for URN: '{}' associated resource class: '{}' and extension class: '{}'",
+      urn, resourceClass.getSimpleName(), extensionClass.getSimpleName() );
+
+    Map<String, Class<? extends ScimExtension>> resourceMap = resourceExtensionsMap.computeIfAbsent(resourceClass, k -> new HashMap<>());
+
+    if(!resourceMap.containsKey(urn)) {
+      resourceMap.put(urn, extensionClass);
+    }
+  }
+
+  private ResourceType generateResourceType(ScimResourceType scimResourceType, List<Class<? extends ScimExtension>> extensionList) throws InvalidExtensionException {
+
+    ResourceType resourceType = new ResourceType();
+    resourceType.setDescription(scimResourceType.description());
+    resourceType.setId(scimResourceType.id());
+    resourceType.setName(scimResourceType.name());
+    resourceType.setEndpoint(scimResourceType.endpoint());
+    resourceType.setSchemaUrn(scimResourceType.schema());
+
+    if (extensionList != null) {
+
+      List<ResourceType.SchemaExtentionConfiguration> extensionSchemaList = new ArrayList<>();
+
+      for (Class<? extends ScimExtension> se : extensionList) {
+
+        ScimExtensionType extensionType = se.getAnnotation(ScimExtensionType.class);
+
+        if (extensionType == null) {
+          throw new InvalidExtensionException("Missing annotation: @ScimExtensionType on ScimExtensionL " + se.getSimpleName());
+        }
+
+        ResourceType.SchemaExtentionConfiguration ext = new ResourceType.SchemaExtentionConfiguration();
+        ext.setRequired(extensionType.required());
+        ext.setSchemaUrn(extensionType.id());
+        extensionSchemaList.add(ext);
+      }
+
+      resourceType.setSchemaExtensions(extensionSchemaList);
+    }
+
+    return resourceType;
+  }
 }
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java
index f5e4f892..94ad6339 100644
--- a/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositoryRegistryTest.java
@@ -25,7 +25,6 @@ import org.apache.directory.scim.spec.annotation.ScimExtensionType;
 import org.apache.directory.scim.spec.annotation.ScimResourceType;
 import org.apache.directory.scim.spec.exception.ResourceException;
 import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
-import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
 import org.apache.directory.scim.spec.resources.ScimExtension;
 import org.apache.directory.scim.spec.resources.ScimResource;
 import org.apache.directory.scim.spec.resources.ScimUser;
@@ -45,7 +44,7 @@ public class RepositoryRegistryTest {
     SchemaRegistry schemaRegistry = new SchemaRegistry();
     Instance<Repository<? extends ScimResource>> scimRepositoryInstances = mock(Instance.class);
     Repository<ScimUser> repository = mock(Repository.class);
-    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, ScimExtensionRegistry.getInstance(), scimRepositoryInstances));
+    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, scimRepositoryInstances));
 
     when(scimRepositoryInstances.stream()).thenReturn(Stream.of(repository));
     doThrow(new InvalidRepositoryException("test exception")).when(repositoryRegistry).registerRepository(any(), any());
@@ -58,16 +57,13 @@ public class RepositoryRegistryTest {
     SchemaRegistry schemaRegistry = spy(new SchemaRegistry());
     Instance<Repository<? extends ScimResource>> scimRepositoryInstances = mock(Instance.class);
     Repository<StubResource> repository = mock(Repository.class);
-    ScimExtensionRegistry extensionRegistry = ScimExtensionRegistry.getInstance();
-    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, extensionRegistry, scimRepositoryInstances));
+    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, scimRepositoryInstances));
 
     when(scimRepositoryInstances.stream()).thenReturn(Stream.of(repository));
     when(repository.getExtensionList()).thenReturn(List.of(StubExtension.class));
 
-    // TODO: need to refactor out the ScimExtensionRegistry to make it easier for test
-    assertThat(extensionRegistry.getExtensionClass(StubResource.class, StubExtension.URN)).isNull();
     repositoryRegistry.registerRepository(StubResource.class, repository);
-    assertThat(extensionRegistry.getExtensionClass(StubResource.class, StubExtension.URN)).isNotNull();
+    assertThat(schemaRegistry.getExtensionClass(StubResource.class, StubExtension.URN)).isNotNull();
 
     assertThat(repositoryRegistry.getRepository(StubResource.class)).isEqualTo(repository);
   }
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositorySchemaRegistryTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositorySchemaRegistryTest.java
index 64bb0a6d..1f48b3fb 100644
--- a/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositorySchemaRegistryTest.java
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/RepositorySchemaRegistryTest.java
@@ -41,7 +41,7 @@ public class RepositorySchemaRegistryTest {
   
   public RepositorySchemaRegistryTest() {
     schemaRegistry = new SchemaRegistry();
-    repositoryRegistry = new RepositoryRegistry(schemaRegistry, null, null);
+    repositoryRegistry = new RepositoryRegistry(schemaRegistry, null);
   }
 
   @Test
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java
index 731ae1c2..ed640e8e 100644
--- a/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/schema/SchemaRegistryTest.java
@@ -42,25 +42,31 @@ public class SchemaRegistryTest {
     Schema extSchema = Schemas.schemaForExtension(ExampleObjectExtension.class);
 
     ResourceType userType = new ResourceType();
-    userType.setId("user");
+    userType.setId(ScimUser.RESOURCE_NAME);
+    userType.setEndpoint("/Users");
     userType.setSchemaUrn(ScimUser.SCHEMA_URI);
     userType.setName(ScimUser.RESOURCE_NAME);
+    userType.setDescription("Top level ScimUser");
+    userType.setSchemaExtensions(List.of(new ResourceType.SchemaExtentionConfiguration().setSchemaUrn(ExampleObjectExtension.URN)));
+
     ResourceType groupType = new ResourceType();
-    groupType.setId("group");
+    groupType.setId(ScimGroup.RESOURCE_NAME);
+    groupType.setEndpoint("/Groups");
     groupType.setSchemaUrn(ScimGroup.SCHEMA_URI);
     groupType.setName(ScimGroup.RESOURCE_NAME);
+    groupType.setDescription("Top level ScimGroup");
 
-    schemaRegistry.addSchema(ScimUser.class, userType, List.of(ExampleObjectExtension.class));
-    schemaRegistry.addSchema(ScimGroup.class, groupType, List.of());
+    schemaRegistry.addSchema(ScimUser.class, List.of(ExampleObjectExtension.class));
+    schemaRegistry.addSchema(ScimGroup.class, null);
 
     assertThat(schemaRegistry.getSchema(ScimUser.SCHEMA_URI)).isEqualTo(userSchema);
     assertThat(schemaRegistry.getAllSchemas()).containsOnly(userSchema, groupsSchema, extSchema);
     assertThat(schemaRegistry.getAllSchemaUrns()).containsOnly(ScimUser.SCHEMA_URI, ScimGroup.SCHEMA_URI, ExampleObjectExtension.URN);
     assertThat(schemaRegistry.getAllResourceTypes()).containsOnly(userType, groupType);
     assertThat(schemaRegistry.getResourceType(ScimUser.RESOURCE_NAME)).isEqualTo(userType);
-    assertThat(schemaRegistry.findScimResourceClassFromEndpoint("/Users")).isEqualTo(ScimUser.class);
-    assertThat(schemaRegistry.findScimResourceClassFromEndpoint("/Groups")).isEqualTo(ScimGroup.class);
-    assertThat(schemaRegistry.findScimResourceClass(ScimUser.SCHEMA_URI)).isEqualTo(ScimUser.class);
+    assertThat(schemaRegistry.getScimResourceClassFromEndpoint("/Users")).isEqualTo(ScimUser.class);
+    assertThat(schemaRegistry.getScimResourceClassFromEndpoint("/Groups")).isEqualTo(ScimGroup.class);
+    assertThat(schemaRegistry.getScimResourceClass(ScimUser.SCHEMA_URI)).isEqualTo(ScimUser.class);
     assertThat(schemaRegistry.getBaseSchemaOfResourceType(ScimUser.RESOURCE_NAME)).isEqualTo(Schemas.schemaFor(ScimUser.class));
   }
 }
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java b/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java
index 6aa6eb42..102ef79d 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/rest/BulkResourceImpl.java
@@ -174,7 +174,7 @@ public class BulkResourceImpl implements BulkResource {
             createAndSetErrorResponse(operationRequest, Status.BAD_REQUEST, "path is not a valid path (e.g. \"/Groups/123abc\", \"/Users/123xyz\", ...)");
           } else {
             String endPoint = path.substring(0, path.lastIndexOf('/'));
-            Class<ScimResource> clazz = (Class<ScimResource>) schemaRegistry.findScimResourceClassFromEndpoint(endPoint);
+            Class<ScimResource> clazz = (Class<ScimResource>) schemaRegistry.getScimResourceClassFromEndpoint(endPoint);
 
             if (clazz == null) {
               errorOccurred = true;
@@ -400,7 +400,7 @@ public class BulkResourceImpl implements BulkResource {
     if (scimResource == null) {
       String path = operationResult.getPath();
       String endPoint = path.substring(0, path.lastIndexOf('/'));
-      Class<ScimResource> clazz = (Class<ScimResource>) schemaRegistry.findScimResourceClassFromEndpoint(endPoint);
+      Class<ScimResource> clazz = (Class<ScimResource>) schemaRegistry.getScimResourceClassFromEndpoint(endPoint);
       scimResourceClass = clazz;
     } else {
       @SuppressWarnings("unchecked")
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/rest/ObjectMapperFactory.java b/scim-server/src/main/java/org/apache/directory/scim/server/rest/ObjectMapperFactory.java
index 64bb88c0..bbc7153a 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/rest/ObjectMapperFactory.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/rest/ObjectMapperFactory.java
@@ -29,7 +29,6 @@ import jakarta.enterprise.inject.Produces;
 import jakarta.inject.Inject;
 import jakarta.ws.rs.ext.Provider;
 import org.apache.directory.scim.core.schema.SchemaRegistry;
-import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
 import org.apache.directory.scim.spec.resources.ScimExtension;
 import org.apache.directory.scim.spec.resources.ScimResource;
 
@@ -61,26 +60,36 @@ public class ObjectMapperFactory {
 
   static class ScimResourceModule extends SimpleModule {
 
+    private final SchemaRegistry schemaRegistry;
+
     public ScimResourceModule(SchemaRegistry schemaRegistry) {
       super("scim-resources", Version.unknownVersion());
+      this.schemaRegistry = schemaRegistry;
       addDeserializer(ScimResource.class, new ScimResourceDeserializer(schemaRegistry));
     }
 
     @Override
     public void setupModule(SetupContext context) {
       super.setupModule(context);
-      context.addDeserializationProblemHandler(new UnknownPropertyHandler());
+      context.addDeserializationProblemHandler(new UnknownPropertyHandler(schemaRegistry));
     }
   }
 
   static class UnknownPropertyHandler extends DeserializationProblemHandler {
+
+    private final SchemaRegistry schemaRegistry;
+
+    UnknownPropertyHandler(SchemaRegistry schemaRegistry) {
+      this.schemaRegistry = schemaRegistry;
+    }
+
     @Override
     public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException {
 
       if (beanOrClass instanceof ScimResource) {
         ScimResource scimResource = (ScimResource) beanOrClass;
         Class<? extends ScimResource> resourceClass = scimResource.getClass();
-        Class<? extends ScimExtension> extensionClass = ScimExtensionRegistry.getInstance().getExtensionClass(resourceClass, propertyName);
+        Class<? extends ScimExtension> extensionClass = schemaRegistry.getExtensionClass(resourceClass, propertyName);
 
         if (extensionClass != null) {
           ScimExtension ext = ctxt.readPropertyValue(p, null, extensionClass);
@@ -92,5 +101,4 @@ public class ObjectMapperFactory {
       return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
     }
   }
-
 }
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/rest/ScimResourceDeserializer.java b/scim-server/src/main/java/org/apache/directory/scim/server/rest/ScimResourceDeserializer.java
index 16de41d9..9f3f6b9a 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/rest/ScimResourceDeserializer.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/rest/ScimResourceDeserializer.java
@@ -47,7 +47,7 @@ public class ScimResourceDeserializer extends StdDeserializer<ScimResource> {
 
     Class<? extends ScimResource> scimResourceClass = StreamSupport.stream(schemas.spliterator(), false)
       .map(JsonNode::textValue)
-      .map(schemaRegistry::findScimResourceClass)
+      .map(schemaRegistry::getScimResourceClass)
       .filter(Objects::nonNull)
       .findFirst()
       .orElseThrow(() -> new JsonParseException(jsonParser, "Could not find a valid schema in: " + schemas + ", valid schemas are: " + schemaRegistry.getAllSchemaUrns(), location));
diff --git a/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java b/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java
index 73893675..fbb27490 100644
--- a/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java
+++ b/scim-server/src/test/java/org/apache/directory/scim/server/rest/BulkResourceImplTest.java
@@ -26,7 +26,6 @@ import jakarta.ws.rs.core.UriInfo;
 import org.apache.directory.scim.server.exception.UnableToCreateResourceException;
 import org.apache.directory.scim.core.repository.Repository;
 import org.apache.directory.scim.core.repository.RepositoryRegistry;
-import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
 import org.apache.directory.scim.protocol.data.BulkOperation;
 import org.apache.directory.scim.protocol.data.BulkRequest;
 import org.apache.directory.scim.protocol.data.BulkResponse;
@@ -82,7 +81,7 @@ public class BulkResourceImplTest {
     when(emptyInstance.stream()).thenReturn(Stream.empty());
 
     SchemaRegistry schemaRegistry = new SchemaRegistry();
-    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry, ScimExtensionRegistry.getInstance(), emptyInstance);
+    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry, emptyInstance);
 
     Instance<Repository<ScimUser>> userRepositoryInstance = mock(Instance.class);
     Repository<ScimUser> userRepository = mock(Repository.class);
@@ -172,7 +171,7 @@ public class BulkResourceImplTest {
     when(emptyInstance.stream()).thenReturn(Stream.empty());
 
     SchemaRegistry schemaRegistry = new SchemaRegistry();
-    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry, ScimExtensionRegistry.getInstance(), emptyInstance );
+    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry, emptyInstance );
 
     Instance<Repository<ScimUser>> userProviderInstance = mock(Instance.class);
     Repository<ScimUser> userRepository = mock(Repository.class);
diff --git a/scim-server/src/test/java/org/apache/directory/scim/server/rest/ObjectMapperFactoryTest.java b/scim-server/src/test/java/org/apache/directory/scim/server/rest/ObjectMapperFactoryTest.java
index d43afc83..a3dec7fb 100644
--- a/scim-server/src/test/java/org/apache/directory/scim/server/rest/ObjectMapperFactoryTest.java
+++ b/scim-server/src/test/java/org/apache/directory/scim/server/rest/ObjectMapperFactoryTest.java
@@ -23,10 +23,8 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.directory.scim.core.schema.SchemaRegistry;
 import org.apache.directory.scim.server.utility.ExampleObjectExtension;
-import org.apache.directory.scim.spec.extension.ScimExtensionRegistry;
 import org.apache.directory.scim.spec.resources.ScimResource;
 import org.apache.directory.scim.spec.resources.ScimUser;
-import org.apache.directory.scim.spec.schema.ResourceType;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -36,15 +34,9 @@ public class ObjectMapperFactoryTest {
 
   @Test
   public void serialize() throws JsonProcessingException {
-
-    ScimExtensionRegistry.getInstance().registerExtension(ScimUser.class, ExampleObjectExtension.class);
-
-    ResourceType userType = new ResourceType();
-    userType.setId("user");
-    userType.setSchemaUrn(ScimUser.SCHEMA_URI);
-    userType.setName(ScimUser.RESOURCE_NAME);
     SchemaRegistry schemaRegistry = new SchemaRegistry();
-    schemaRegistry.addSchema(ScimUser.class, userType, List.of(ExampleObjectExtension.class));
+    schemaRegistry.addSchema(ScimUser.class, List.of(ExampleObjectExtension.class));
+    schemaRegistry.addExtension(ScimUser.class, ExampleObjectExtension.class);
 
     ScimResource resource = new ScimUser().setId("test1");
     ExampleObjectExtension extension = new ExampleObjectExtension().setValueDefault("test-value");
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java
deleted file mode 100644
index 2a272b4b..00000000
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/extension/ScimExtensionRegistry.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
- 
-* http://www.apache.org/licenses/LICENSE-2.0
-
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-package org.apache.directory.scim.spec.extension;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.directory.scim.spec.annotation.ScimExtensionType;
-import org.apache.directory.scim.spec.exception.InvalidExtensionException;
-import org.apache.directory.scim.spec.resources.ScimExtension;
-import org.apache.directory.scim.spec.resources.ScimResource;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public final class ScimExtensionRegistry {
-    
-  private static final ScimExtensionRegistry INSTANCE = new ScimExtensionRegistry();
-  
-  private Map<Class<? extends ScimResource>, Map<String, Class<? extends ScimExtension>>> registry = new HashMap<>();
-  
-  private ScimExtensionRegistry() {}
-  
-  public Class<? extends ScimExtension> getExtensionClass(Class<? extends ScimResource> resourceClass, String urn) {
-    Class<? extends ScimExtension> extensionClass = null;
-    if(registry.containsKey(resourceClass)) {
-      Map<String, Class<? extends ScimExtension>> resourceMap = registry.get(resourceClass);
-      if(resourceMap.containsKey(urn)) {
-        extensionClass = resourceMap.get(urn);
-      }
-    }
-    return extensionClass;
-  }
-  
-  public static ScimExtensionRegistry getInstance() {
-    return INSTANCE;
-  }
-  
-  public void registerExtension(Class<? extends ScimResource> resourceClass, Class<? extends ScimExtension> extensionClass) {
-    ScimExtensionType[] se = extensionClass.getAnnotationsByType(ScimExtensionType.class);
-
-    if (se.length != 1) {
-      throw new InvalidExtensionException("Registered extensions must a single @ScimExtensionType annotation");
-    }
-    
-    String urn = se[0].id();
-    
-    log.debug("Registering extension for URN: '{}' associated resource class: '{}' and extension class: '{}'",
-      urn, resourceClass.getSimpleName(), extensionClass.getSimpleName() );
-
-    Map<String, Class<? extends ScimExtension>> resourceMap = registry.computeIfAbsent(resourceClass, k -> new HashMap<>());
-
-    if(!resourceMap.containsKey(urn)) {
-      resourceMap.put(urn, extensionClass);
-    }
-  }
-
-}
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/ScimResource.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/ScimResource.java
index 4d54c723..d152b94b 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/ScimResource.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/ScimResource.java
@@ -20,14 +20,12 @@
 package org.apache.directory.scim.spec.resources;
 
 import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.apache.directory.scim.spec.annotation.ScimAttribute;
 import org.apache.directory.scim.spec.annotation.ScimExtensionType;
 import org.apache.directory.scim.spec.annotation.ScimResourceType;
 import org.apache.directory.scim.spec.exception.InvalidExtensionException;
-import org.apache.directory.scim.spec.json.ObjectMapperFactory;
 import org.apache.directory.scim.spec.schema.Meta;
 import org.apache.directory.scim.spec.schema.Schema.Attribute.Returned;
 import org.slf4j.Logger;
@@ -57,8 +55,6 @@ public abstract class ScimResource extends BaseResource implements Serializable
 
   private static final Logger LOG = LoggerFactory.getLogger(ScimResource.class);
 
-  private transient final ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
-
   @XmlElement
   @NotNull
   @ScimAttribute(returned = Returned.ALWAYS)