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:31:04 UTC

[directory-scimple] 01/01: Cleanup CDI scim-core

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

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

commit 92aff7af5ac271cc363c331dfcf17241abe9cd6b
Author: Brian Demers <bd...@apache.org>
AuthorDate: Thu Sep 15 13:02:43 2022 -0400

    Cleanup CDI scim-core
    
    * Replaces Initializable interface with Eager annotation
    * Removes CDI dependency in scim-core
      * adds producer to scim-server
      * change bean discovery to annotated
    * Update examples to use produce a ServerConfiguration (reduces complexity needed for implementations)
---
 scim-core/pom.xml                                  |  4 --
 .../directory/scim/core/repository/Repository.java |  4 +-
 .../scim/core/repository/RepositoryRegistry.java   | 29 ++------
 .../directory/scim/core/schema/SchemaRegistry.java |  2 -
 scim-core/src/main/resources/META-INF/beans.xml    | 22 ------
 .../core/repository/RepositoryRegistryTest.java    | 15 ++---
 .../repository/RepositorySchemaRegistryTest.java   |  2 +-
 .../scim/example/jersey/JerseyApplication.java     | 32 +++------
 .../src/main/resources/logback.xml                 |  2 +-
 .../scim/example/memory/rest/RestApplication.java  | 37 +++-------
 .../scim/server/ScimServerInitializer.java         | 49 --------------
 .../server/configuration/ServerConfiguration.java  |  5 --
 .../apache/directory/scim/server/spi/Eager.java    | 18 ++---
 .../scim/server/spi/ScimServerInitializer.java     | 78 ++++++++++++++++++++++
 .../scim/server/spi/ScimpleComponents.java         | 48 +++++++++++++
 scim-server/src/main/resources/META-INF/beans.xml  |  2 +-
 .../jakarta.enterprise.inject.spi.Extension        |  2 +-
 .../directory/scim/server/it/testapp/App.java      | 29 ++------
 .../scim/server/rest/BulkResourceImplTest.java     |  4 +-
 19 files changed, 181 insertions(+), 203 deletions(-)

diff --git a/scim-core/pom.xml b/scim-core/pom.xml
index 031452e8..ac55db48 100644
--- a/scim-core/pom.xml
+++ b/scim-core/pom.xml
@@ -36,10 +36,6 @@
       <groupId>jakarta.inject</groupId>
       <artifactId>jakarta.inject-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>jakarta.enterprise</groupId>
-      <artifactId>jakarta.enterprise.cdi-api</artifactId>
-    </dependency>
     <dependency>
       <groupId>jakarta.annotation</groupId>
       <artifactId>jakarta.annotation-api</artifactId>
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 942f68b0..1e59830a 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
@@ -115,10 +115,10 @@ public interface Repository<T extends ScimResource> {
    * associated with the ScimResource of type T.
    * 
    * @return A list of ScimExtension classes.
-   * @throws ResourceException If the repository cannot return
+   * @throws InvalidRepositoryException If the repository cannot return
    *         the appropriate list.
    */
-  default List<Class<? extends ScimExtension>> getExtensionList() throws ResourceException {
+  default List<Class<? extends ScimExtension>> getExtensionList() throws InvalidRepositoryException {
     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 02cab32b..b7b39806 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
@@ -19,13 +19,8 @@
 
 package org.apache.directory.scim.core.repository;
 
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.inject.Instance;
-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.exception.ResourceException;
 import org.apache.directory.scim.spec.exception.ScimResourceInvalidException;
 import org.apache.directory.scim.spec.resources.ScimExtension;
 import org.apache.directory.scim.spec.resources.ScimResource;
@@ -37,40 +32,30 @@ import java.util.Map;
 
 @Data
 @Slf4j
-@ApplicationScoped
-public class RepositoryRegistry implements Initializable {
+public class RepositoryRegistry {
 
   private SchemaRegistry schemaRegistry;
 
-  // 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;
-
   private Map<Class<? extends ScimResource>, Repository<? extends ScimResource>> repositoryMap = new HashMap<>();
 
-  @Inject
-  public RepositoryRegistry(SchemaRegistry schemaRegistry, Instance<Repository<? extends ScimResource>> scimRepositoryInstances) {
+  public RepositoryRegistry(SchemaRegistry schemaRegistry) {
     this.schemaRegistry = schemaRegistry;
-    this.scimRepositoryInstances = scimRepositoryInstances;
   }
 
-  RepositoryRegistry() {}
-
-  @Override
-  @SuppressWarnings("unchecked")
-  public void initialize() {
-    scimRepositoryInstances.stream()
+  public RepositoryRegistry(SchemaRegistry schemaRegistry, List<Repository<? extends ScimResource>> scimRepositories) {
+    this.schemaRegistry = schemaRegistry;
+    scimRepositories.stream()
       .map(repository -> (Repository<ScimResource>) repository)
       .forEach(repository -> {
       try {
         registerRepository(repository.getResourceClass(), repository);
-      } catch (InvalidRepositoryException | ResourceException e) {
+      } catch (InvalidRepositoryException e) {
         throw new ScimResourceInvalidException("Failed to register repository " + repository.getClass() + " for ScimResource type " + repository.getResourceClass(), e);
       }
     });
   }
 
-  public synchronized <T extends ScimResource> void registerRepository(Class<T> clazz, Repository<T> repository) throws InvalidRepositoryException, ResourceException {
+  public synchronized <T extends ScimResource> void registerRepository(Class<T> clazz, Repository<T> repository) throws InvalidRepositoryException {
     List<Class<? extends ScimExtension>> extensionList = repository.getExtensionList();
 
     log.debug("Calling addSchema on the base class: {}", clazz);
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 18578352..2334d699 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
@@ -21,7 +21,6 @@ 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;
@@ -34,7 +33,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.directory.scim.spec.schema.Schemas;
 
 @Slf4j
-@ApplicationScoped
 public class SchemaRegistry {
 
   private final Map<String, Schema> schemaMap = new HashMap<>();
diff --git a/scim-core/src/main/resources/META-INF/beans.xml b/scim-core/src/main/resources/META-INF/beans.xml
deleted file mode 100644
index a47f43b0..00000000
--- a/scim-core/src/main/resources/META-INF/beans.xml
+++ /dev/null
@@ -1,22 +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. -->
-<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
-       version="1.1" bean-discovery-mode="all">
-       
-</beans>
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 94ad6339..a8b98a9e 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
@@ -19,7 +19,6 @@
 
 package org.apache.directory.scim.core.repository;
 
-import jakarta.enterprise.inject.Instance;
 import org.apache.directory.scim.core.schema.SchemaRegistry;
 import org.apache.directory.scim.spec.annotation.ScimExtensionType;
 import org.apache.directory.scim.spec.annotation.ScimResourceType;
@@ -31,7 +30,6 @@ import org.apache.directory.scim.spec.resources.ScimUser;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
-import java.util.stream.Stream;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -40,26 +38,21 @@ import static org.mockito.Mockito.*;
 public class RepositoryRegistryTest {
 
   @Test
-  public void initializeWithException() throws InvalidRepositoryException, ResourceException {
+  public void initializeWithException() throws InvalidRepositoryException {
     SchemaRegistry schemaRegistry = new SchemaRegistry();
-    Instance<Repository<? extends ScimResource>> scimRepositoryInstances = mock(Instance.class);
     Repository<ScimUser> repository = mock(Repository.class);
-    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, scimRepositoryInstances));
 
-    when(scimRepositoryInstances.stream()).thenReturn(Stream.of(repository));
-    doThrow(new InvalidRepositoryException("test exception")).when(repositoryRegistry).registerRepository(any(), any());
+    doThrow(new InvalidRepositoryException("test exception")).when(repository).getExtensionList();
 
-    assertThrows(ScimResourceInvalidException.class, repositoryRegistry::initialize);
+    assertThrows(ScimResourceInvalidException.class, () -> new RepositoryRegistry(schemaRegistry, List.of(repository)));
   }
 
   @Test
   public void registerRepository() throws InvalidRepositoryException, ResourceException {
     SchemaRegistry schemaRegistry = spy(new SchemaRegistry());
-    Instance<Repository<? extends ScimResource>> scimRepositoryInstances = mock(Instance.class);
     Repository<StubResource> repository = mock(Repository.class);
-    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry, scimRepositoryInstances));
+    RepositoryRegistry repositoryRegistry = spy(new RepositoryRegistry(schemaRegistry));
 
-    when(scimRepositoryInstances.stream()).thenReturn(Stream.of(repository));
     when(repository.getExtensionList()).thenReturn(List.of(StubExtension.class));
 
     repositoryRegistry.registerRepository(StubResource.class, 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 1f48b3fb..a8a3445e 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);
+    repositoryRegistry = new RepositoryRegistry(schemaRegistry);
   }
 
   @Test
diff --git a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/JerseyApplication.java b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/JerseyApplication.java
index a63fd671..01b63039 100644
--- a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/JerseyApplication.java
+++ b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/JerseyApplication.java
@@ -19,14 +19,12 @@
 
 package org.apache.directory.scim.example.jersey;
 
-import jakarta.inject.Inject;
+import jakarta.enterprise.inject.Produces;
 import jakarta.ws.rs.core.UriBuilder;
-import org.apache.directory.scim.core.Initializable;
 import org.apache.directory.scim.server.configuration.ServerConfiguration;
 import org.apache.directory.scim.server.rest.ScimResourceHelper;
 
 import java.net.URI;
-import java.util.HashSet;
 import java.util.Set;
 
 import jakarta.ws.rs.core.Application;
@@ -48,30 +46,18 @@ public class JerseyApplication extends Application {
   
   @Override
   public Set<Class<?>> getClasses() {
-    Set<Class<?>> clazzes = new HashSet<>(ScimResourceHelper.getScimClassesToLoad());
-    clazzes.add(ServerConfigInitializer.class);
-    return clazzes;
+    return ScimResourceHelper.getScimClassesToLoad();
   }
 
-  /**
-   * A {@link Initializable} allow for eager initialization of beans, this class configures the {@link ServerConfiguration}.
-   */
-  public static class ServerConfigInitializer implements Initializable {
-
-    @Inject
-    private ServerConfiguration serverConfiguration;
-
-    @Override
-    public void initialize() {
-
+  @Produces
+  ServerConfiguration serverConfiguration() {
+    return new ServerConfiguration()
       // Set any unique configuration bits
-      serverConfiguration
-        .setId("scimple-jersey-example")
-        .setDocumentationUri("https://github.com/apache/directory-scimple");
+      .setId("scimple-jersey-example")
+      .setDocumentationUri("https://github.com/apache/directory-scimple");
 
-        // set the auth scheme too
-        // .addAuthenticationSchema(oauthBearer());
-    }
+    // set the auth scheme too
+    // .addAuthenticationSchema(oauthBearer());
   }
 
   public static void main(String[] args) {
diff --git a/scim-server-examples/scim-server-jersey/src/main/resources/logback.xml b/scim-server-examples/scim-server-jersey/src/main/resources/logback.xml
index e1ac3856..0731c9a2 100644
--- a/scim-server-examples/scim-server-jersey/src/main/resources/logback.xml
+++ b/scim-server-examples/scim-server-jersey/src/main/resources/logback.xml
@@ -20,7 +20,7 @@
       <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
     </encoder>
   </appender>
-  <root level="debug">
+  <root level="INFO">
     <appender-ref ref="STDOUT" />
   </root>
 </configuration>
diff --git a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/rest/RestApplication.java b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/rest/RestApplication.java
index 97f0850c..51f0893c 100644
--- a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/rest/RestApplication.java
+++ b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/rest/RestApplication.java
@@ -19,47 +19,32 @@
 
 package org.apache.directory.scim.example.memory.rest;
 
-import jakarta.inject.Inject;
-import org.apache.directory.scim.core.Initializable;
+import jakarta.enterprise.inject.Produces;
 import org.apache.directory.scim.server.configuration.ServerConfiguration;
 import org.apache.directory.scim.server.rest.ScimResourceHelper;
 
-import java.util.HashSet;
 import java.util.Set;
 
 import jakarta.ws.rs.ApplicationPath;
 import jakarta.ws.rs.core.Application;
 
+import static org.apache.directory.scim.spec.schema.ServiceProviderConfiguration.AuthenticationSchema.httpBasic;
+
 @ApplicationPath("v2")
 public class RestApplication extends Application {
   
   @Override
   public Set<Class<?>> getClasses() {
-    Set<Class<?>> clazzes = new HashSet<>();
-    
-    clazzes.addAll(ScimResourceHelper.getScimClassesToLoad());
-    clazzes.add(ServerConfigInitializer.class);
-
-    return clazzes;
+    return ScimResourceHelper.getScimClassesToLoad();
   }
 
-  /**
-   * A {@link Initializable} allow for eager initialization of beans, this class configures the {@link ServerConfiguration}.
-   */
-  public static class ServerConfigInitializer implements Initializable {
-
-    @Inject
-    private ServerConfiguration serverConfiguration;
-
-    @Override
-    public void initialize() {
-      // Set any unique configuration bits
-      serverConfiguration
-        .setId("scimple-in-memory-example")
-        .setDocumentationUri("https://github.com/apache/directory-scimple");
+  @Produces
+  ServerConfiguration serverConfiguration() {
+    return new ServerConfiguration()
+      .setId("scimple-in-memory-example")
+      .addAuthenticationSchema(httpBasic());
 
-      // set the auth scheme too
-      // .addAuthenticationSchema(oauthBearer());
-    }
+    // set the auth scheme too
+    // .addAuthenticationSchema(oauthBearer());
   }
 }
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/ScimServerInitializer.java b/scim-server/src/main/java/org/apache/directory/scim/server/ScimServerInitializer.java
deleted file mode 100644
index ceb7ea91..00000000
--- a/scim-server/src/main/java/org/apache/directory/scim/server/ScimServerInitializer.java
+++ /dev/null
@@ -1,49 +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.server;
-
-import jakarta.enterprise.event.Observes;
-import jakarta.enterprise.inject.spi.AfterDeploymentValidation;
-import jakarta.enterprise.inject.spi.Bean;
-import jakarta.enterprise.inject.spi.BeanManager;
-import jakarta.enterprise.inject.spi.Extension;
-import jakarta.enterprise.inject.spi.ProcessBean;
-import org.apache.directory.scim.core.Initializable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ScimServerInitializer implements Extension {
-
-  private List<Bean<?>> scimConfigBeans = new ArrayList<>();
-
-  public <T> void collect(@Observes ProcessBean<T> event) {
-    if (Initializable.class.isAssignableFrom(event.getBean().getBeanClass())) {
-      scimConfigBeans.add(event.getBean());
-    }
-  }
-
-  public void load(@Observes AfterDeploymentValidation event, BeanManager beanManager) {
-    scimConfigBeans.forEach(bean -> {
-      Initializable configBean = (Initializable) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
-      configBean.initialize();
-    });
-  }
-}
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/configuration/ServerConfiguration.java b/scim-server/src/main/java/org/apache/directory/scim/server/configuration/ServerConfiguration.java
index 6ed666d9..4c2c8c03 100644
--- a/scim-server/src/main/java/org/apache/directory/scim/server/configuration/ServerConfiguration.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/configuration/ServerConfiguration.java
@@ -23,9 +23,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Named;
-
 import lombok.AccessLevel;
 import lombok.Data;
 import lombok.Setter;
@@ -41,8 +38,6 @@ import org.apache.directory.scim.spec.schema.ServiceProviderConfiguration.Suppor
  * @author Chris Harm &lt;crh5255@psu.edu&gt;
  */
 @Data
-@Named
-@ApplicationScoped
 public class ServerConfiguration {
   
   static final int BULK_MAXIMUM_OPERATIONS = 100;
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/Initializable.java b/scim-server/src/main/java/org/apache/directory/scim/server/spi/Eager.java
similarity index 71%
rename from scim-core/src/main/java/org/apache/directory/scim/core/Initializable.java
rename to scim-server/src/main/java/org/apache/directory/scim/server/spi/Eager.java
index cd47f1b0..ec35c52b 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/Initializable.java
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/spi/Eager.java
@@ -17,15 +17,15 @@
  * under the License.
  */
 
-package org.apache.directory.scim.core;
+package org.apache.directory.scim.server.spi;
 
-/**
- * Classes implementing ScimConfiguration will be eagerly initialized.
- *
- * CDI does not have a way to eagerly initialize beans at startup. This is a workaround using a spi extension, for
- * non-EJB based deployments.
- */
-public interface Initializable {
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
-  void initialize();
+@Retention(RUNTIME)
+@Target({TYPE, METHOD, FIELD})
+public @interface Eager {
 }
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/spi/ScimServerInitializer.java b/scim-server/src/main/java/org/apache/directory/scim/server/spi/ScimServerInitializer.java
new file mode 100644
index 00000000..2230bada
--- /dev/null
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/spi/ScimServerInitializer.java
@@ -0,0 +1,78 @@
+/*
+ * 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.server.spi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.context.spi.CreationalContext;
+import jakarta.enterprise.event.Observes;
+import jakarta.enterprise.inject.spi.*;
+import org.apache.directory.scim.server.configuration.ServerConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class ScimServerInitializer implements Extension {
+
+  private final Logger log = LoggerFactory.getLogger(ScimServerInitializer.class);
+
+  private final Set<Bean<?>> eagerBeans = new HashSet<>();
+
+  public <T> void collect(@Observes ProcessBean<T> event) {
+    if (event.getAnnotated().isAnnotationPresent(Eager.class)) {
+      eagerBeans.add(event.getBean());
+    }
+  }
+
+  public <T, X> void collect(@Observes ProcessProducerMethod<T, X> event) {
+    if (event.getAnnotated().isAnnotationPresent(Eager.class)) {
+      eagerBeans.add(event.getBean());
+    }
+  }
+
+  public <T, X> void collect(@Observes ProcessProducerField<T, X> event) {
+    if (event.getAnnotated().isAnnotationPresent(Eager.class)) {
+      eagerBeans.add(event.getBean());
+    }
+  }
+
+  public void defaultBeans(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
+    if (beanManager.getBeans(ServerConfiguration.class).isEmpty()) {
+      log.warn("It is recommended to provide a ServerConfiguration bean to configure SCIMple, a default instance will be used.");
+      afterBeanDiscovery.addBean()
+        .scope(ApplicationScoped.class)
+        .types(ServerConfiguration.class)
+        .beanClass(ServerConfiguration.class)
+        .createWith((CreationalContext<ServerConfiguration> cc) -> {
+          AnnotatedType<ServerConfiguration> at = beanManager.createAnnotatedType(ServerConfiguration.class);
+          BeanAttributes<ServerConfiguration> ba = beanManager.createBeanAttributes(at);
+          return beanManager.createBean(ba, ServerConfiguration.class, beanManager.getInjectionTargetFactory(at)).create(cc);
+        });
+    }
+  }
+
+  public void load(@Observes AfterDeploymentValidation event, BeanManager beanManager) {
+    eagerBeans.forEach(bean -> {
+      // call a real method so the proxied bean gets created
+      beanManager.getReference(bean, Object.class, beanManager.createCreationalContext(bean)).toString();
+    });
+  }
+}
diff --git a/scim-server/src/main/java/org/apache/directory/scim/server/spi/ScimpleComponents.java b/scim-server/src/main/java/org/apache/directory/scim/server/spi/ScimpleComponents.java
new file mode 100644
index 00000000..133e0869
--- /dev/null
+++ b/scim-server/src/main/java/org/apache/directory/scim/server/spi/ScimpleComponents.java
@@ -0,0 +1,48 @@
+/*
+ * 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.server.spi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.context.Dependent;
+import jakarta.enterprise.inject.Instance;
+import jakarta.enterprise.inject.Produces;
+import org.apache.directory.scim.core.repository.Repository;
+import org.apache.directory.scim.core.repository.RepositoryRegistry;
+import org.apache.directory.scim.core.schema.SchemaRegistry;
+import org.apache.directory.scim.spec.resources.ScimResource;
+
+import java.util.stream.Collectors;
+
+@Dependent
+public class ScimpleComponents {
+
+  @Produces
+  @ApplicationScoped
+  public SchemaRegistry schemaRegistry() {
+    return new SchemaRegistry();
+  }
+
+  @Produces
+  @Eager
+  @ApplicationScoped
+  public RepositoryRegistry repositoryRegistry(SchemaRegistry schemaRegistry, Instance<Repository<? extends ScimResource>> repositoryInstances) {
+    return new RepositoryRegistry(schemaRegistry, repositoryInstances.stream().collect(Collectors.toList()));
+  }
+}
diff --git a/scim-server/src/main/resources/META-INF/beans.xml b/scim-server/src/main/resources/META-INF/beans.xml
index 5f0e8418..f3962030 100644
--- a/scim-server/src/main/resources/META-INF/beans.xml
+++ b/scim-server/src/main/resources/META-INF/beans.xml
@@ -17,5 +17,5 @@ under the License.
 <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
-       version="1.1" bean-discovery-mode="all">
+       version="1.1" bean-discovery-mode="annotated">
 </beans>
diff --git a/scim-server/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension b/scim-server/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
index 2c8aac61..71979efa 100644
--- a/scim-server/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
+++ b/scim-server/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
@@ -1 +1 @@
-org.apache.directory.scim.server.ScimServerInitializer
+org.apache.directory.scim.server.spi.ScimServerInitializer
diff --git a/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/App.java b/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/App.java
index 1b52f5a4..6094f498 100644
--- a/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/App.java
+++ b/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/App.java
@@ -19,13 +19,11 @@
 
 package org.apache.directory.scim.server.it.testapp;
 
-import jakarta.inject.Inject;
+import jakarta.enterprise.inject.Produces;
 import jakarta.ws.rs.core.Application;
-import org.apache.directory.scim.core.Initializable;
 import org.apache.directory.scim.server.configuration.ServerConfiguration;
 import org.apache.directory.scim.server.rest.ScimResourceHelper;
 
-import java.util.HashSet;
 import java.util.Set;
 
 import static org.apache.directory.scim.spec.schema.ServiceProviderConfiguration.AuthenticationSchema.httpBasic;
@@ -34,26 +32,13 @@ public class App extends Application {
 
   @Override
   public Set<Class<?>> getClasses() {
-    Set<Class<?>> clazzes = new HashSet<>(ScimResourceHelper.getScimClassesToLoad());
-    clazzes.add(ServerConfigInitializer.class);
-    return clazzes;
+    return ScimResourceHelper.getScimClassesToLoad();
   }
 
-  /**
-   * A {@link Initializable} allow for eager initialization of beans, this class configures the {@link ServerConfiguration}.
-   */
-  public static class ServerConfigInitializer implements Initializable {
-
-    @Inject
-    private ServerConfiguration serverConfiguration;
-
-    @Override
-    public void initialize() {
-
-      // Set any unique configuration bits
-      serverConfiguration
-        .setId("scimple-server-its")
-        .addAuthenticationSchema(httpBasic());
-    }
+  @Produces
+  ServerConfiguration serverConfiguration() {
+    return new ServerConfiguration()
+      .setId("scimple-server-its")
+      .addAuthenticationSchema(httpBasic());
   }
 }
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 fbb27490..f78865bf 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
@@ -81,7 +81,7 @@ public class BulkResourceImplTest {
     when(emptyInstance.stream()).thenReturn(Stream.empty());
 
     SchemaRegistry schemaRegistry = new SchemaRegistry();
-    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry, emptyInstance);
+    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry);
 
     Instance<Repository<ScimUser>> userRepositoryInstance = mock(Instance.class);
     Repository<ScimUser> userRepository = mock(Repository.class);
@@ -171,7 +171,7 @@ public class BulkResourceImplTest {
     when(emptyInstance.stream()).thenReturn(Stream.empty());
 
     SchemaRegistry schemaRegistry = new SchemaRegistry();
-    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry, emptyInstance );
+    RepositoryRegistry repositoryRegistry = new RepositoryRegistry(schemaRegistry);
 
     Instance<Repository<ScimUser>> userProviderInstance = mock(Instance.class);
     Repository<ScimUser> userRepository = mock(Repository.class);