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 2023/11/21 22:15:45 UTC

(directory-scimple) 05/06: Move PatchOperationPath parsing into util method.

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

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

commit b38454fffae7b37168d744f4ccb5c55152d8ff55
Author: Brian Demers <bd...@apache.org>
AuthorDate: Tue Nov 21 15:42:09 2023 -0500

    Move PatchOperationPath parsing into util method.
    
    Construction of object now happens in util method as to not be vunlerable to finalizer attacks.
    This is probably a nit, but SpotBugs/FindSecBugs flagged this issue in the latest update.
    
    There are a few other minor related issues flagged by the spotbugs upgrade as well
    - missing static keywords
    - fields that could be private
---
 .../scim/client/rest/ScimUserClientTest.java       |  2 +-
 .../scim/core/repository/PatchHandlerImpl.java     |  2 +-
 .../scim/core/repository/RepositoryRegistry.java   | 17 +++++++------
 .../scim/core/repository/UpdateRequest.java        |  8 ++-----
 .../directory/scim/core/spi/ScimpleComponents.java |  4 +++-
 .../scim/core/repository/PatchHandlerTest.java     | 28 +++++++++++-----------
 .../core/repository/RepositoryRegistryTest.java    |  2 +-
 .../scim/core/repository/UpdateRequestTest.java    |  2 +-
 .../scim/protocol/adapter/FilterWrapper.java       |  4 ++--
 .../spec/adapter/PatchOperationPathAdapter.java    |  2 +-
 .../scim/spec/patch/PatchOperationPath.java        | 28 ++++++++++++----------
 .../directory/scim/spec/resources/PhoneNumber.java | 22 ++++++++---------
 .../scim/spec/patch/PatchOperationPathTest.java    |  2 +-
 src/pmd/ruleset.xml                                |  4 ++++
 src/spotbugs/excludes.xml                          |  5 ++++
 .../scim/spring/ScimpleSpringConfiguration.java    |  4 +++-
 16 files changed, 73 insertions(+), 63 deletions(-)

diff --git a/scim-client/src/test/java/org/apache/directory/scim/client/rest/ScimUserClientTest.java b/scim-client/src/test/java/org/apache/directory/scim/client/rest/ScimUserClientTest.java
index 06dc741e..3af1812f 100644
--- a/scim-client/src/test/java/org/apache/directory/scim/client/rest/ScimUserClientTest.java
+++ b/scim-client/src/test/java/org/apache/directory/scim/client/rest/ScimUserClientTest.java
@@ -207,7 +207,7 @@ public class ScimUserClientTest extends ClientTestSupport {
     PatchRequest patchRequest = new PatchRequest().add(
       new PatchOperation()
         .setOperation(PatchOperation.Type.REMOVE)
-        .setPath(new PatchOperationPath("name.honorificPrefix"))
+        .setPath(PatchOperationPath.fromString("name.honorificPrefix"))
     );
 
     ScimUser expectedUser = new ScimUser();
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java
index ac704c98..ef341e41 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchHandlerImpl.java
@@ -134,7 +134,7 @@ public class PatchHandlerImpl implements PatchHandler {
 
   private PatchOperationPath tryGetOperationPath(String key) {
     try {
-      return new PatchOperationPath(key);
+      return PatchOperationPath.fromString(key);
     } catch (FilterParseException e) {
       log.warn("Parsing path failed with exception.", e);
       throw new UnsupportedFilterException("Cannot parse path expression: " + e.getMessage());
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 91bdd5f3..4e533b0e 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
@@ -46,17 +46,16 @@ public class RepositoryRegistry {
     this.schemaRegistry = schemaRegistry;
   }
 
-  public RepositoryRegistry(SchemaRegistry schemaRegistry, List<Repository<? extends ScimResource>> scimRepositories) {
-    this.schemaRegistry = schemaRegistry;
+  public void registerRepositories(List<Repository<? extends ScimResource>> scimRepositories) {
     scimRepositories.stream()
-      .map(repository -> (Repository<ScimResource>) repository)
+      .map(repository -> (Repository<? extends ScimResource>) repository)
       .forEach(repository -> {
-      try {
-        registerRepository(repository.getResourceClass(), repository);
-      } catch (InvalidRepositoryException e) {
-        throw new ScimResourceInvalidException("Failed to register repository " + repository.getClass() + " for ScimResource type " + repository.getResourceClass(), e);
-      }
-    });
+        try {
+          registerRepository(repository.getResourceClass(), repository);
+        } 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 {
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/repository/UpdateRequest.java b/scim-core/src/main/java/org/apache/directory/scim/core/repository/UpdateRequest.java
index a39adac3..52a2e245 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/repository/UpdateRequest.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/repository/UpdateRequest.java
@@ -313,9 +313,7 @@ public class UpdateRequest<T extends ScimResource> {
     operation.setOperation(patchOpType);
     
     AttributeReference attributeReference = new AttributeReference(parseData.pathUri, null);
-    PatchOperationPath patchOperationPath = new PatchOperationPath();
-    ValuePathExpression valuePathExpression = new ValuePathExpression(attributeReference);
-    patchOperationPath.setValuePathExpression(valuePathExpression);
+    PatchOperationPath patchOperationPath = new PatchOperationPath(new ValuePathExpression(attributeReference));
     
     operation.setPath(patchOperationPath);
     operation.setValue(determineValue(patchOpType, valueNode, parseData));
@@ -447,9 +445,7 @@ public class UpdateRequest<T extends ScimResource> {
       subAttribute = subAttributes.get(0);
     }
     AttributeReference attributeReference = new AttributeReference(parseData.pathUri, attribute, subAttribute);
-    PatchOperationPath patchOperationPath = new PatchOperationPath();
-    ValuePathExpression valuePathExpression = new ValuePathExpression(attributeReference, valueFilterExpression);
-    patchOperationPath.setValuePathExpression(valuePathExpression);
+    PatchOperationPath patchOperationPath = new PatchOperationPath(new ValuePathExpression(attributeReference, valueFilterExpression));
 
     operation.setPath(patchOperationPath);
     operation.setValue(value);
diff --git a/scim-core/src/main/java/org/apache/directory/scim/core/spi/ScimpleComponents.java b/scim-core/src/main/java/org/apache/directory/scim/core/spi/ScimpleComponents.java
index dfde898d..ef981376 100644
--- a/scim-core/src/main/java/org/apache/directory/scim/core/spi/ScimpleComponents.java
+++ b/scim-core/src/main/java/org/apache/directory/scim/core/spi/ScimpleComponents.java
@@ -44,7 +44,9 @@ public class ScimpleComponents {
   @Produces
   @ApplicationScoped
   public RepositoryRegistry repositoryRegistry(SchemaRegistry schemaRegistry, Instance<Repository<? extends ScimResource>> repositoryInstances) {
-    return new RepositoryRegistry(schemaRegistry, repositoryInstances.stream().collect(Collectors.toList()));
+    RepositoryRegistry registry = new RepositoryRegistry(schemaRegistry);
+    registry.registerRepositories(repositoryInstances.stream().collect(Collectors.toList()));
+    return registry;
   }
 
   /*
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java
index a430df61..2cd31c2f 100644
--- a/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/PatchHandlerTest.java
@@ -322,7 +322,7 @@ public class PatchHandlerTest {
   public void applyWithFilterExpression() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REPLACE);
-    op.setPath(new PatchOperationPath("emails[type EQ \"home\"].value"));
+    op.setPath(PatchOperationPath.fromString("emails[type EQ \"home\"].value"));
     op.setValue("new-home@example.com");
     ScimUser updatedUser = patchHandler.apply(user(), List.of(op));
     List<Email> emails = updatedUser.getEmails();
@@ -341,7 +341,7 @@ public class PatchHandlerTest {
   public void replaceItem() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REPLACE);
-    op.setPath(new PatchOperationPath("emails[type EQ \"home\"]"));
+    op.setPath(PatchOperationPath.fromString("emails[type EQ \"home\"]"));
     op.setValue(Map.of(
       "type", "other",
       "value", "other@example.com"
@@ -395,7 +395,7 @@ public class PatchHandlerTest {
   public void replaceCollection() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REPLACE);
-    op.setPath(new PatchOperationPath("emails"));
+    op.setPath(PatchOperationPath.fromString("emails"));
     op.setValue(List.of(
       Map.of(
         "value", "first@example.com",
@@ -422,7 +422,7 @@ public class PatchHandlerTest {
   public void deleteItemWithFilter() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REMOVE);
-    op.setPath(new PatchOperationPath("emails[type EQ \"home\"]"));
+    op.setPath(PatchOperationPath.fromString("emails[type EQ \"home\"]"));
     ScimUser updatedUser = patchHandler.apply(user(), List.of(op));
     List<Email> emails = updatedUser.getEmails();
     assertThat(emails).isEqualTo(List.of(
@@ -437,7 +437,7 @@ public class PatchHandlerTest {
   public void deleteAttributeWithPath() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REMOVE);
-    op.setPath(new PatchOperationPath("nickName"));
+    op.setPath(PatchOperationPath.fromString("nickName"));
     ScimUser updatedUser = patchHandler.apply(user(), List.of(op));
     assertThat(updatedUser.getNickName()).isNull();
   }
@@ -446,7 +446,7 @@ public class PatchHandlerTest {
   public void deleteCollectionWithPath() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REMOVE);
-    op.setPath(new PatchOperationPath("emails"));
+    op.setPath(PatchOperationPath.fromString("emails"));
     ScimUser updatedUser = patchHandler.apply(user(), List.of(op));
     assertThat(updatedUser.getEmails()).isNull();
   }
@@ -455,7 +455,7 @@ public class PatchHandlerTest {
   public void deleteItemWithComplexFilter() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(REMOVE);
-    op.setPath(new PatchOperationPath("emails[type EQ \"home\"] and value ew \"example.com\""));
+    op.setPath(PatchOperationPath.fromString("emails[type EQ \"home\"] and value ew \"example.com\""));
     ScimUser updatedUser = patchHandler.apply(user(), List.of(op));
     assertThat(updatedUser.getEmails()).isEqualTo(List.of(
       new Email()
@@ -469,7 +469,7 @@ public class PatchHandlerTest {
   public void addAttribute() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(ADD);
-    op.setPath(new PatchOperationPath("profileUrl"));
+    op.setPath(PatchOperationPath.fromString("profileUrl"));
     op.setValue("https://profile.example.com");
 
     ScimUser expectedUser = user()
@@ -483,7 +483,7 @@ public class PatchHandlerTest {
   public void addItem() throws FilterParseException {
     PatchOperation op = new PatchOperation();
     op.setOperation(ADD);
-    op.setPath(new PatchOperationPath("emails"));
+    op.setPath(PatchOperationPath.fromString("emails"));
     op.setValue(Map.of(
       "type", "other",
       "value", "other@example.com"));
@@ -537,11 +537,11 @@ public class PatchHandlerTest {
   public void multiplePatchOperations() throws FilterParseException {
     PatchOperation opRm = new PatchOperation();
     opRm.setOperation(REMOVE);
-    opRm.setPath(new PatchOperationPath("emails[type EQ \"home\"]"));
+    opRm.setPath(PatchOperationPath.fromString("emails[type EQ \"home\"]"));
 
     PatchOperation opAdd = new PatchOperation();
     opAdd.setOperation(ADD);
-    opAdd.setPath(new PatchOperationPath("emails"));
+    opAdd.setPath(PatchOperationPath.fromString("emails"));
     opAdd.setValue(Map.of(
       "value", "babs@example.com",
       "type", "other")
@@ -564,11 +564,11 @@ public class PatchHandlerTest {
   public void replaceCollectionWithMultipleOps() throws FilterParseException {
     PatchOperation opRm = new PatchOperation();
     opRm.setOperation(REMOVE);
-    opRm.setPath(new PatchOperationPath("emails"));
+    opRm.setPath(PatchOperationPath.fromString("emails"));
 
     PatchOperation opAdd = new PatchOperation();
     opAdd.setOperation(ADD);
-    opAdd.setPath(new PatchOperationPath("emails"));
+    opAdd.setPath(PatchOperationPath.fromString("emails"));
     opAdd.setValue(List.of(
       Map.of(
         "value", "first@example.com",
@@ -597,7 +597,7 @@ public class PatchHandlerTest {
     PatchOperation op = new PatchOperation();
     op.setOperation(operationType);
     if (path != null) {
-      op.setPath(new PatchOperationPath(path));
+      op.setPath(PatchOperationPath.fromString(path));
     }
     if (value != null) {
       op.setValue(value);
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 a179dda3..745652ae 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
@@ -44,7 +44,7 @@ public class RepositoryRegistryTest {
 
     doThrow(new InvalidRepositoryException("test exception")).when(repository).getExtensionList();
 
-    assertThrows(ScimResourceInvalidException.class, () -> new RepositoryRegistry(schemaRegistry, List.of(repository)));
+    assertThrows(ScimResourceInvalidException.class, () -> new RepositoryRegistry(schemaRegistry).registerRepositories(List.of(repository)));
   }
 
   @Test
diff --git a/scim-core/src/test/java/org/apache/directory/scim/core/repository/UpdateRequestTest.java b/scim-core/src/test/java/org/apache/directory/scim/core/repository/UpdateRequestTest.java
index 4bf487d9..3dbdfedb 100644
--- a/scim-core/src/test/java/org/apache/directory/scim/core/repository/UpdateRequestTest.java
+++ b/scim-core/src/test/java/org/apache/directory/scim/core/repository/UpdateRequestTest.java
@@ -917,7 +917,7 @@ public class UpdateRequestTest {
     List<PatchOperation> patchOperations = new ArrayList<>();
     PatchOperation removePhoneNumberOp = new PatchOperation();
     removePhoneNumberOp.setOperation(Type.REMOVE);
-    removePhoneNumberOp.setPath(new PatchOperationPath("phoneNumbers[type eq \"home\"]"));
+    removePhoneNumberOp.setPath(PatchOperationPath.fromString("phoneNumbers[type eq \"home\"]"));
     patchOperations.add(removePhoneNumberOp);
     return patchOperations;
   }
diff --git a/scim-spec/scim-spec-protocol/src/main/java/org/apache/directory/scim/protocol/adapter/FilterWrapper.java b/scim-spec/scim-spec-protocol/src/main/java/org/apache/directory/scim/protocol/adapter/FilterWrapper.java
index 44438dd6..e9183e84 100644
--- a/scim-spec/scim-spec-protocol/src/main/java/org/apache/directory/scim/protocol/adapter/FilterWrapper.java
+++ b/scim-spec/scim-spec-protocol/src/main/java/org/apache/directory/scim/protocol/adapter/FilterWrapper.java
@@ -33,9 +33,9 @@ import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
 @Data
-public class FilterWrapper {
+final public class FilterWrapper {
 
-  public Filter filter;
+  final public Filter filter;
   
   public FilterWrapper(String string) {
     
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/adapter/PatchOperationPathAdapter.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/adapter/PatchOperationPathAdapter.java
index f7672304..243f0046 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/adapter/PatchOperationPathAdapter.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/adapter/PatchOperationPathAdapter.java
@@ -29,7 +29,7 @@ public class PatchOperationPathAdapter extends XmlAdapter<String, PatchOperation
     if (v == null) {
       return null;
     }
-    return new PatchOperationPath(v);
+    return PatchOperationPath.fromString(v);
   }
 
   @Override
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/patch/PatchOperationPath.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/patch/PatchOperationPath.java
index 10144a5f..6e795791 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/patch/PatchOperationPath.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/patch/PatchOperationPath.java
@@ -19,8 +19,10 @@
 
 package org.apache.directory.scim.spec.patch;
 
-import org.antlr.v4.runtime.ANTLRInputStream;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
 import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.RecognitionException;
 import org.antlr.v4.runtime.Recognizer;
@@ -31,29 +33,25 @@ import org.apache.directory.scim.spec.filter.FilterLexer;
 import org.apache.directory.scim.spec.filter.FilterParser;
 import org.apache.directory.scim.spec.filter.FilterParseException;
 import org.apache.directory.scim.spec.filter.ValuePathExpression;
-import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 
 import java.io.Serializable;
 
-@Data
 @Slf4j
+@EqualsAndHashCode
 public class PatchOperationPath implements Serializable {
 
   private static final long serialVersionUID = 449365558879593512L;
 
-  private ValuePathExpression valuePathExpression;
+  @Getter
+  private final ValuePathExpression valuePathExpression;
 
-  public PatchOperationPath() {
-    
+  public PatchOperationPath(ValuePathExpression valuePathExpression) {
+    this. valuePathExpression = valuePathExpression;
   }
 
-  public PatchOperationPath(String patchPath) throws FilterParseException {
-    parsePatchPath(patchPath);
-  }
-
-  protected void parsePatchPath(String patchPath) throws FilterParseException {
-    FilterLexer l = new FilterLexer(new ANTLRInputStream(patchPath));
+  static ValuePathExpression parsePatchPath(String patchPath) throws FilterParseException {
+    FilterLexer l = new FilterLexer(CharStreams.fromString(patchPath));
     FilterParser p = new FilterParser(new CommonTokenStream(l));
     p.setBuildParseTree(true);
 
@@ -69,7 +67,7 @@ public class PatchOperationPath implements Serializable {
       PatchPathListener patchPathListener = new PatchPathListener();
       ParseTreeWalker.DEFAULT.walk(patchPathListener, tree);
 
-      this.valuePathExpression = patchPathListener.getValuePathExpression();
+      return patchPathListener.getValuePathExpression();
     } catch (IllegalStateException e) {
       throw new FilterParseException(e);
     }
@@ -80,4 +78,8 @@ public class PatchOperationPath implements Serializable {
     return valuePathExpression.toFilter();
   }
 
+  public static PatchOperationPath fromString(String patchPath) throws FilterParseException {
+    return new PatchOperationPath(parsePatchPath(patchPath));
+  }
+
 }
diff --git a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/PhoneNumber.java b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/PhoneNumber.java
index 4f8a7c94..73579c46 100644
--- a/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/PhoneNumber.java
+++ b/scim-spec/scim-spec-schema/src/main/java/org/apache/directory/scim/spec/resources/PhoneNumber.java
@@ -321,17 +321,17 @@ public class PhoneNumber implements Serializable, TypedAttribute {
 
     static final Logger LOGGER = LoggerFactory.getLogger(PhoneNumberBuilder.class);
 
-    final String HYPHEN = "-";
-    final String INTERNATIONAL_PREFIX = "+";
-    final String PREFIX = "tel:%s";
-    final String EXTENSTION_PREFIX = ";ext=%s";
-    final String ISUB_PREFIX = ";isub=%s";
-    final String CONTEXT_PREFIX = ";phone-context=%s";
-    final String PARAMS_STRING = ";%s=%s";
-    final String LOCAL_SUBSCRIBER_NUMBER_REGEX = "^[\\d\\.\\-\\(\\)]+$";
-    final String DOMAIN_NAME_REGEX = "^[a-zA-Z0-9\\.\\-]+$";
-    final String GLOBAL_NUMBER_REGEX = "^(\\+)?[\\d\\.\\-\\(\\)]+$";
-    final String COUNTRY_CODE_REGEX = "^(\\+)?[1-9][0-9]{0,2}$";
+    static final String HYPHEN = "-";
+    static final String INTERNATIONAL_PREFIX = "+";
+    static final String PREFIX = "tel:%s";
+    static final String EXTENSTION_PREFIX = ";ext=%s";
+    static final String ISUB_PREFIX = ";isub=%s";
+    static final String CONTEXT_PREFIX = ";phone-context=%s";
+    static final String PARAMS_STRING = ";%s=%s";
+    static final String LOCAL_SUBSCRIBER_NUMBER_REGEX = "^[\\d\\.\\-\\(\\)]+$";
+    static final String DOMAIN_NAME_REGEX = "^[a-zA-Z0-9\\.\\-]+$";
+    static final String GLOBAL_NUMBER_REGEX = "^(\\+)?[\\d\\.\\-\\(\\)]+$";
+    static final String COUNTRY_CODE_REGEX = "^(\\+)?[1-9][0-9]{0,2}$";
 
     String number;
     String display;
diff --git a/scim-spec/scim-spec-schema/src/test/java/org/apache/directory/scim/spec/patch/PatchOperationPathTest.java b/scim-spec/scim-spec-schema/src/test/java/org/apache/directory/scim/spec/patch/PatchOperationPathTest.java
index f38c4b34..eb7b2817 100644
--- a/scim-spec/scim-spec-schema/src/test/java/org/apache/directory/scim/spec/patch/PatchOperationPathTest.java
+++ b/scim-spec/scim-spec-schema/src/test/java/org/apache/directory/scim/spec/patch/PatchOperationPathTest.java
@@ -39,7 +39,7 @@ public class PatchOperationPathTest {
   @ParameterizedTest
   @MethodSource("pathValues")
   public void testPathParsing(String value) throws Exception {
-    PatchOperationPath path = new PatchOperationPath(value);
+    PatchOperationPath path = PatchOperationPath.fromString(value);
     log.debug("ValuePathExpression: {}", path.getValuePathExpression());
     
     String result = path.toString();
diff --git a/src/pmd/ruleset.xml b/src/pmd/ruleset.xml
index 2e8750a2..3939e6eb 100644
--- a/src/pmd/ruleset.xml
+++ b/src/pmd/ruleset.xml
@@ -22,6 +22,10 @@ under the License.
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
 
+  <description>
+    PMD Ruleset for used by Apache SCIMple.
+  </description>
+
   <rule ref="category/java/bestpractices.xml/AvoidUsingHardCodedIP" />
   <rule ref="category/java/bestpractices.xml/CheckResultSet" />
   <rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation" />
diff --git a/src/spotbugs/excludes.xml b/src/spotbugs/excludes.xml
index b50f714f..44f5890e 100644
--- a/src/spotbugs/excludes.xml
+++ b/src/spotbugs/excludes.xml
@@ -61,4 +61,9 @@
   <!-- doesn't seem to play well with lombok -->
   <Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/>
 
+  <Match>
+    <Class name="org.apache.directory.scim.client.rest.BaseScimClient"/>
+    <Bug pattern="CT_CONSTRUCTOR_THROW"/>
+  </Match>
+
 </FindBugsFilter>
diff --git a/support/spring-boot/src/main/java/org/apache/directory/scim/spring/ScimpleSpringConfiguration.java b/support/spring-boot/src/main/java/org/apache/directory/scim/spring/ScimpleSpringConfiguration.java
index 0d066d0e..898c8332 100644
--- a/support/spring-boot/src/main/java/org/apache/directory/scim/spring/ScimpleSpringConfiguration.java
+++ b/support/spring-boot/src/main/java/org/apache/directory/scim/spring/ScimpleSpringConfiguration.java
@@ -83,7 +83,9 @@ public class ScimpleSpringConfiguration {
   @Bean
   @ConditionalOnMissingBean
   RepositoryRegistry repositoryRegistry(SchemaRegistry schemaRegistry, List<Repository<? extends ScimResource>> scimResources) {
-    return new RepositoryRegistry(schemaRegistry, scimResources);
+    RepositoryRegistry registry = new RepositoryRegistry(schemaRegistry);
+    registry.registerRepositories(scimResources);
+    return registry;
   }
 
   @Bean