Merge branch 'release/2.22'
diff --git a/.gitignore b/.gitignore
index b7d13e1..4da60b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
 .settings/
 target/
 .factorypath
+.vscode/
diff --git a/pom.xml b/pom.xml
index c7d4a88..0e8582d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
 
   <groupId>edu.psu.swe.scim</groupId>
   <artifactId>scim-parent</artifactId>
-  <version>2.21</version>
+  <version>2.22</version>
   <packaging>pom</packaging>
   <name>SCIM - Parent</name>
   <description>Penn State's Open Source JavaEE implmentation of the SCIM version 2.0 specification (RFC7642, RFC7643 and RFC7644)</description>
@@ -344,9 +344,9 @@
           </configuration>
         </plugin>
         <plugin>
-          <groupId>external.atlassian.jgitflow</groupId>
+          <groupId>io.ultreia.java4all.jgitflow</groupId>
           <artifactId>jgitflow-maven-plugin</artifactId>
-          <version>1.0-m4.3</version>
+          <version>1.0.0-rc-1</version>
           <configuration>
             <autoVersionSubmodules>true</autoVersionSubmodules>
             <flowInitContext>
diff --git a/scim-client/pom.xml b/scim-client/pom.xml
index 37d6851..4bf5c50 100644
--- a/scim-client/pom.xml
+++ b/scim-client/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
   <artifactId>scim-client</artifactId>
   <name>SCIM - Client</name>
diff --git a/scim-client/src/main/java/edu/psu/swe/scim/client/rest/BaseScimClient.java b/scim-client/src/main/java/edu/psu/swe/scim/client/rest/BaseScimClient.java
index b9e216b..3008319 100644
--- a/scim-client/src/main/java/edu/psu/swe/scim/client/rest/BaseScimClient.java
+++ b/scim-client/src/main/java/edu/psu/swe/scim/client/rest/BaseScimClient.java
@@ -32,6 +32,9 @@
 
 public abstract class BaseScimClient<T extends ScimResource> implements AutoCloseable {
 
+  static final String ATTRIBUTES_QUERY_PARAM = "attributes";
+  static final String EXCLUDED_ATTRIBUTES_QUERY_PARAM = "excludedAttributes";
+
   private final Client client;
   private final Class<T> scimResourceClass;
   private final GenericType<ListResponse<T>> scimResourceListResponseGenericType;
@@ -141,7 +144,7 @@
     handleResponse(response);
   }
 
-  private static <E, T> E handleResponse(Response response, T type, Function<T, E> readEntity) throws ScimException {
+  static <E, T> E handleResponse(Response response, T type, Function<T, E> readEntity) throws ScimException {
     E entity;
 
     try {
@@ -159,7 +162,7 @@
     return entity;
   }
 
-  private static void handleResponse(Response response) throws ScimException {
+  static void handleResponse(Response response) throws ScimException {
     try {
       if (!RestClientUtil.isSuccessful(response)) {
         Status status = Status.fromStatusCode(response.getStatus());
@@ -175,6 +178,15 @@
     }
   }
 
+  static ScimException toScimException(RestClientException restClientException) {
+    ScimException scimException;
+    Status status = restClientException.getErrorMessage().getStatus();
+    ErrorResponse errorResponse = new ErrorResponse(status, String.join("\n", restClientException.getErrorMessage().getErrorMessageList()));
+    scimException = new ScimException(errorResponse, status);
+
+    return scimException;
+  }
+
   public RestCall getInvoke() {
     return this.invoke;
   }
@@ -185,25 +197,12 @@
 
   private class InternalScimClient implements BaseResourceTypeResource<T> {
 
-    private static final String ATTRIBUTES_QUERY_PARAM = "attributes";
-    private static final String EXCLUDED_ATTRIBUTES_QUERY_PARAM = "excludedAttributes";
     private static final String FILTER_QUERY_PARAM = "filter";
     private static final String SORT_BY_QUERY_PARAM = "sortBy";
     private static final String SORT_ORDER_QUERY_PARAM = "sortOrder";
     private static final String START_INDEX_QUERY_PARAM = "startIndex";
     private static final String COUNT_QUERY_PARAM = "count";
 
-    private ScimException toScimException(RestClientException restClientException) {
-      ScimException scimException;
-      
-      Status status = restClientException.getErrorMessage().getStatus();
-      ErrorResponse errorResponse = new ErrorResponse(status, String.join("\n", restClientException.getErrorMessage().getErrorMessageList()));
-
-      scimException = new ScimException(errorResponse, status);
-
-      return scimException;
-    }
-    
     @Override
     public Response getById(String id, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
       Response response;
diff --git a/scim-client/src/main/java/edu/psu/swe/scim/client/rest/ScimSelfClient.java b/scim-client/src/main/java/edu/psu/swe/scim/client/rest/ScimSelfClient.java
new file mode 100644
index 0000000..161fcdd
--- /dev/null
+++ b/scim-client/src/main/java/edu/psu/swe/scim/client/rest/ScimSelfClient.java
@@ -0,0 +1,160 @@
+package edu.psu.swe.scim.client.rest;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import edu.psu.swe.commons.jaxrs.RestCall;
+import edu.psu.swe.commons.jaxrs.exceptions.RestClientException;
+import edu.psu.swe.scim.spec.protocol.Constants;
+import edu.psu.swe.scim.spec.protocol.SelfResource;
+import edu.psu.swe.scim.spec.protocol.attribute.AttributeReferenceListWrapper;
+import edu.psu.swe.scim.spec.protocol.data.PatchRequest;
+import edu.psu.swe.scim.spec.protocol.exception.ScimException;
+import edu.psu.swe.scim.spec.resources.ScimUser;
+
+// purposefully does not extend BaseScimClient, has a different utility than other clients
+
+public class ScimSelfClient implements AutoCloseable {
+
+  private Client client;
+  private WebTarget target;
+  private SelfResourceClient selfResourceClient;
+  private RestCall invoke = Invocation::invoke;
+
+  public ScimSelfClient(Client client, String baseUrl) {
+    this.client = client;
+    this.target = this.client.target(baseUrl).path(SelfResource.PATH);
+    this.selfResourceClient = new SelfResourceClient();
+  }
+
+  public ScimSelfClient(Client client, String baseUrl, RestCall invoke) {
+    this(client, baseUrl);
+
+    this.invoke = invoke;
+  }
+
+  public ScimUser getSelf(AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
+    ScimUser self;
+    Response response = this.selfResourceClient.getSelf(attributes, excludedAttributes);
+    self = BaseScimClient.handleResponse(response, ScimUser.class, response::readEntity);
+
+    return self;
+  }
+
+  public ScimUser getSelf() throws ScimException {
+    ScimUser self = this.getSelf(null, null);
+
+    return self;
+  }
+
+  public void updateSelf(ScimUser scimUser, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
+    Response response = this.selfResourceClient.update(scimUser, attributes, excludedAttributes);
+
+    BaseScimClient.handleResponse(response);
+  }
+
+  public void updateSelf(ScimUser scimUser) throws ScimException {
+    this.updateSelf(scimUser, null, null);
+  }
+
+  public void patchSelf(PatchRequest patchRequest, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
+    Response response = this.selfResourceClient.patch(patchRequest, attributes, excludedAttributes);
+
+    BaseScimClient.handleResponse(response);
+  }
+
+  public void patchSelf(PatchRequest patchRequest) throws ScimException {
+    this.patchSelf(patchRequest, null, null);
+  }
+
+  public void deleteSelf() throws ScimException {
+    Response response = this.selfResourceClient.delete();
+
+    BaseScimClient.handleResponse(response);
+  }
+
+  public RestCall getInvoke() {
+    return this.invoke;
+  }
+
+  public void setInvoke(RestCall invoke) {
+    this.invoke = invoke;
+  }
+
+  @Override
+  public void close() throws Exception {
+    this.client.close();
+  }
+
+  private class SelfResourceClient implements SelfResource {
+
+    @Override
+    public Response getSelf(AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
+      Response response;
+      Invocation request = ScimSelfClient.this.target
+          .queryParam(BaseScimClient.ATTRIBUTES_QUERY_PARAM, attributes)
+          .queryParam(BaseScimClient.EXCLUDED_ATTRIBUTES_QUERY_PARAM, excludedAttributes)
+          .request(Constants.SCIM_CONTENT_TYPE)
+          .buildGet();
+
+      try {
+        response = ScimSelfClient.this.invoke.apply(request);
+      } catch (RestClientException restClientException) {
+        throw BaseScimClient.toScimException(restClientException);
+      }
+      return response;
+    }
+
+    @Override
+    public Response update(ScimUser scimUser, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
+      Response response;
+      Invocation request = ScimSelfClient.this.target
+          .queryParam(BaseScimClient.ATTRIBUTES_QUERY_PARAM, attributes)
+          .queryParam(BaseScimClient.EXCLUDED_ATTRIBUTES_QUERY_PARAM, excludedAttributes)
+          .request(Constants.SCIM_CONTENT_TYPE)
+          .buildPut(Entity.entity(scimUser, Constants.SCIM_CONTENT_TYPE));
+
+      try {
+        response = ScimSelfClient.this.invoke.apply(request);
+      } catch (RestClientException restClientException) {
+        throw BaseScimClient.toScimException(restClientException);
+      }
+      return response;
+    }
+
+    @Override
+    public Response patch(PatchRequest patchRequest, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
+      Response response;
+      Invocation request = ScimSelfClient.this.target
+          .queryParam(BaseScimClient.ATTRIBUTES_QUERY_PARAM, attributes)
+          .queryParam(BaseScimClient.EXCLUDED_ATTRIBUTES_QUERY_PARAM, excludedAttributes)
+          .request(Constants.SCIM_CONTENT_TYPE)
+          .build(Constants.PATCH, Entity.entity(patchRequest, Constants.SCIM_CONTENT_TYPE));
+
+      try {
+        response = ScimSelfClient.this.invoke.apply(request);
+      } catch (RestClientException restClientException) {
+        throw BaseScimClient.toScimException(restClientException);
+      }
+      return response;
+    }
+
+    @Override
+    public Response delete() throws ScimException {
+      Response response;
+      Invocation request = ScimSelfClient.this.target
+          .request(Constants.SCIM_CONTENT_TYPE)
+          .buildDelete();
+
+      try {
+        response = ScimSelfClient.this.invoke.apply(request);
+      } catch (RestClientException restClientException) {
+        throw BaseScimClient.toScimException(restClientException);
+      }
+      return response;
+    }
+  }
+}
diff --git a/scim-common/pom.xml b/scim-common/pom.xml
index 332954e..7b8e3ac 100644
--- a/scim-common/pom.xml
+++ b/scim-common/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-common</artifactId>
@@ -14,12 +14,12 @@
     <dependency>
       <groupId>edu.psu.swe.scim</groupId>
       <artifactId>scim-spec-protocol</artifactId>
-      <version>2.21</version>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>edu.psu.swe.scim</groupId>
       <artifactId>scim-spec-schema</artifactId>
-      <version>2.21</version>
+      <version>${project.version}</version>
     </dependency>
   </dependencies>
 
diff --git a/scim-compliance/pom.xml b/scim-compliance/pom.xml
index 9df4eb3..c8ee951 100644
--- a/scim-compliance/pom.xml
+++ b/scim-compliance/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-compliance</artifactId>
diff --git a/scim-compliance/scim-compliance-client/pom.xml b/scim-compliance/scim-compliance-client/pom.xml
index 4fd7d53..7a58e5a 100644
--- a/scim-compliance/scim-compliance-client/pom.xml
+++ b/scim-compliance/scim-compliance-client/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-compliance</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-compliance-client</artifactId>
diff --git a/scim-compliance/scim-compliance-server/pom.xml b/scim-compliance/scim-compliance-server/pom.xml
index a32ff05..c04aef8 100644
--- a/scim-compliance/scim-compliance-server/pom.xml
+++ b/scim-compliance/scim-compliance-server/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-compliance</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-compliance-server</artifactId>
diff --git a/scim-errai/pom.xml b/scim-errai/pom.xml
index 004e19f..dc2571a 100644
--- a/scim-errai/pom.xml
+++ b/scim-errai/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-errai</artifactId>
@@ -50,31 +50,6 @@
       </resource>
     </resources>
 
-    <pluginManagement>
-      <plugins>
-        <plugin>
-          <groupId>org.projectlombok</groupId>
-          <artifactId>lombok-maven-plugin</artifactId>
-          <version>1.16.10.0</version>
-          <executions>
-            <execution>
-              <phase>generate-sources</phase>
-              <goals>
-                <goal>delombok</goal>
-              </goals>
-            </execution>
-          </executions>
-        </plugin>
-      </plugins>
-    </pluginManagement>
-
-    <plugins>
-      <plugin>
-        <groupId>org.projectlombok</groupId>
-        <artifactId>lombok-maven-plugin</artifactId>
-      </plugin>
-    </plugins>
-
   </build>
 
   <profiles>
@@ -137,6 +112,7 @@
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
+      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.mockito</groupId>
diff --git a/scim-server/pom.xml b/scim-server/pom.xml
index eea5713..ccf990c 100644
--- a/scim-server/pom.xml
+++ b/scim-server/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-server</artifactId>
diff --git a/scim-server/scim-server-common/pom.xml b/scim-server/scim-server-common/pom.xml
index 7cb3adb..7f117ec 100644
--- a/scim-server/scim-server-common/pom.xml
+++ b/scim-server/scim-server-common/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-server</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-server-common</artifactId>
@@ -35,6 +35,11 @@
       <artifactId>jackson-jaxrs-json-provider</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
diff --git a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/Provider.java b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/Provider.java
index 876a2c5..4a09e62 100644
--- a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/Provider.java
+++ b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/Provider.java
@@ -2,11 +2,15 @@
 
 import java.util.List;
 
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
 import edu.psu.swe.scim.server.exception.UnableToCreateResourceException;
 import edu.psu.swe.scim.server.exception.UnableToDeleteResourceException;
 import edu.psu.swe.scim.server.exception.UnableToRetrieveExtensionsException;
 import edu.psu.swe.scim.server.exception.UnableToRetrieveResourceException;
 import edu.psu.swe.scim.server.exception.UnableToUpdateResourceException;
+import edu.psu.swe.scim.server.rest.BaseResourceTypeResourceImpl;
 import edu.psu.swe.scim.spec.protocol.filter.FilterResponse;
 import edu.psu.swe.scim.spec.protocol.search.Filter;
 import edu.psu.swe.scim.spec.protocol.search.PageRequest;
@@ -97,5 +101,21 @@
    *         the appropriate list.
    */
   List<Class<? extends ScimExtension>> getExtensionList() throws UnableToRetrieveExtensionsException;
-  
+
+  /**
+   * <p>In the case where the provider throws an unhandled exception, this
+   * method will be passed that exception in order for the provider to convert
+   * it into the desired response.</p>
+   * <p>The returned response SHOULD fulfill the requirements for SCIM error
+   * responses as defined in <a
+   * href="https://tools.ietf.org/html/rfc7644#section-3.12">3.12. HTTP Status
+   * and Error Response Handling</a> of the SCIM specification.</p>
+   * <p>By default, exceptions are converted into a <code>500 Internal Server
+   * Error</code>.</p>
+   * @param unhandled
+   * @return
+   */
+  default Response handleException(Throwable unhandled) {
+    return BaseResourceTypeResourceImpl.createGenericExceptionResponse(unhandled, Status.INTERNAL_SERVER_ERROR);
+  }
 }
diff --git a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/UpdateRequest.java b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/UpdateRequest.java
index a3c1df7..cd09adf 100644
--- a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/UpdateRequest.java
+++ b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/provider/UpdateRequest.java
@@ -175,8 +175,7 @@
   }
 
   private T applyPatchOperations() {
-    // TODO Auto-generated method stub
-    return resource;
+    throw new java.lang.UnsupportedOperationException("PATCH operations are not implemented at this time.");
   }
   
   /**
diff --git a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/rest/BaseResourceTypeResourceImpl.java b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/rest/BaseResourceTypeResourceImpl.java
index d27d85c..167f5e8 100644
--- a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/rest/BaseResourceTypeResourceImpl.java
+++ b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/rest/BaseResourceTypeResourceImpl.java
@@ -118,7 +118,9 @@
           return createGenericExceptionResponse(e2, e2.getStatus());
         }
       } catch (Exception e) {
-        throw new ScimServerException(Status.INTERNAL_SERVER_ERROR, "Uncaught provider exception: " + e.getMessage(), e);
+        log.error("Uncaught provider exception", e);
+
+        return provider.handleException(e);
       }
 
       if (resource != null) {
@@ -257,7 +259,8 @@
         return er.toResponse();
       } catch (Exception e) {
         log.error("Uncaught provider exception", e);
-        return createGenericExceptionResponse(e, Status.INTERNAL_SERVER_ERROR);
+
+        return provider.handleException(e);
       }
 
       EntityTag etag = null;
@@ -343,7 +346,8 @@
         return createGenericExceptionResponse(e1, e1.getStatus());
       } catch (Exception e) {
         log.error("Uncaught provider exception", e);
-        return createGenericExceptionResponse(e, Status.INTERNAL_SERVER_ERROR);
+
+        return provider.handleException(e);
       }
 
       // If no resources are found, we should still return a ListResponse with
@@ -432,7 +436,8 @@
         return createGenericExceptionResponse(e2, e2.getStatus());
       } catch (Exception e) {
         log.error("Uncaught provider exception", e);
-        return createGenericExceptionResponse(e, Status.INTERNAL_SERVER_ERROR);
+
+        return provider.handleException(e);
       }
 
       if (stored == null) {
@@ -460,7 +465,9 @@
       } catch (UnableToUpdateResourceException e1) {
         return createGenericExceptionResponse(e1, e1.getStatus());
       } catch (Exception e1) {
-        return createGenericExceptionResponse(e1, Status.INTERNAL_SERVER_ERROR);
+        log.error("Uncaught provider exception", e1);
+
+        return provider.handleException(e1);
       }
 
       // Process Attributes
@@ -531,7 +538,8 @@
         return createGenericExceptionResponse(e2, e2.getStatus());
       } catch (Exception e) {
         log.error("Uncaught provider exception", e);
-        return createGenericExceptionResponse(e, Status.INTERNAL_SERVER_ERROR);
+
+        return provider.handleException(e);
       }
 
       if (stored == null) {
@@ -558,8 +566,12 @@
         updated = provider.update(updateRequest);
       } catch (UnableToUpdateResourceException e1) {
         return createGenericExceptionResponse(e1, e1.getStatus());
+      } catch (UnsupportedOperationException e2) {
+        return createGenericExceptionResponse(e2, Status.NOT_IMPLEMENTED);
       } catch (Exception e1) {
-        return createGenericExceptionResponse(e1, Status.INTERNAL_SERVER_ERROR);
+        log.error("Uncaught provider exception", e1);
+
+        return provider.handleException(e1);
       }
 
       // Process Attributes
@@ -608,31 +620,34 @@
 
   @Override
   public Response delete(String id) {
+    Response response;
     try {
-      Response response;
       Provider<T> provider = getProviderInternal();
 
-      endpointUtil.process(uriInfo);
-      response = Response.noContent()
-                         .build();
+      try {
+        endpointUtil.process(uriInfo);
+        response = Response.noContent()
+                           .build();
 
-      provider.delete(id);
-      return response;
-    } catch (UnableToDeleteResourceException e) {
-      Status status = e.getStatus();
-      Response response = Response.status(status)
-                                  .build();
+        provider.delete(id);
+        return response;
+      } catch (UnableToDeleteResourceException e) {
+        Status status = e.getStatus();
+        response = Response.status(status)
+                           .build();
 
-      log.error("Unable to delete resource", e);
+        log.error("Unable to delete resource", e);
 
-      return response;
+        return response;
+      } catch (Exception e) {
+        log.error("Uncaught provider exception", e);
+
+        return provider.handleException(e);
+      }
     } catch (ScimServerException sse) {
       LOG.error("Error Processing SCIM Request", sse);
       return sse.getErrorResponse()
                 .toResponse();
-    } catch (Exception e) {
-      log.error("Uncaught provider exception", e);
-      return createGenericExceptionResponse(e, Status.INTERNAL_SERVER_ERROR);
     }
   }
 
@@ -668,7 +683,7 @@
                   .build();
   }
 
-  private Response createGenericExceptionResponse(Exception e1, Status status) {
+  public static Response createGenericExceptionResponse(Throwable e1, Status status) {
     Status myStatus = status;
     if (myStatus == null) {
       myStatus = Status.INTERNAL_SERVER_ERROR;
diff --git a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/utility/AttributeUtil.java b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/utility/AttributeUtil.java
index 8b4b176..f26dad2 100644
--- a/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/utility/AttributeUtil.java
+++ b/scim-server/scim-server-common/src/main/java/edu/psu/swe/scim/server/utility/AttributeUtil.java
@@ -7,6 +7,7 @@
 import java.io.ObjectOutputStream;
 import java.lang.reflect.Field;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map.Entry;
@@ -82,7 +83,6 @@
   }
   
   private <T extends ScimResource> T setAttributesForDisplayInternal(T resource, Returned ... removeAttributesOfTypes) throws IllegalArgumentException, IllegalAccessException, AttributeDoesNotExistException, IOException {
-
     T copy = cloneScimResource(resource);
     String resourceType = copy.getResourceType();
     Schema schema = registry.getBaseSchemaOfResourceType(resourceType);
@@ -110,7 +110,7 @@
       return setAttributesForDisplay(resource);
     } else {
       T copy = cloneScimResource(resource);
-
+      
       String resourceType = copy.getResourceType();
       Schema schema = registry.getBaseSchemaOfResourceType(resourceType);
 
@@ -198,7 +198,6 @@
   }
 
   private void processAttributes(Object object, AttributeContainer attributeContainer, Function<Attribute, Boolean> function) throws IllegalArgumentException, IllegalAccessException {
-
     if (attributeContainer != null && object != null) {
       for (Attribute attribute : attributeContainer.getAttributes()) {
         Field field = attribute.getField();
@@ -276,7 +275,9 @@
 
     for (AttributeReference attributeReference : attributeReferences) {
       Set<Attribute> findAttributes = findAttribute(attributeReference, includeAttributeChain);
-      attributes.addAll(findAttributes);
+      if (!findAttributes.isEmpty()) {
+        attributes.addAll(findAttributes);
+      }
     }
 
     return attributes;
@@ -285,12 +286,14 @@
   private Set<Attribute> findAttribute(AttributeReference attributeReference, boolean includeAttributeChain) throws AttributeDoesNotExistException {
     String schemaUrn = attributeReference.getUrn();
     Schema schema = null;
-
+    Set<Attribute> attributes;
+    
     if (!StringUtils.isEmpty(schemaUrn)) {
       schema = registry.getSchema(schemaUrn);
 
-      Set<Attribute> attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
-      if (attributes == null) {
+      attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
+      if (attributes.isEmpty()) {
+        log.error("Attribute " + attributeReference.getFullyQualifiedAttributeName() + "not found in schema " + schemaUrn);
         throw new AttributeDoesNotExistException(attributeReference.getFullyQualifiedAttributeName());
       }
       return attributes;
@@ -298,22 +301,27 @@
 
     // Handle unqualified attributes, look in the core schemas
     schema = registry.getSchema(ScimUser.SCHEMA_URI);
-    Set<Attribute> attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
-    if (attributes != null) {
+    attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
+    if (!attributes.isEmpty()) {
       return attributes;
     }
 
     schema = registry.getSchema(ScimGroup.SCHEMA_URI);
     attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
-    if (attributes != null) {
+    if (!attributes.isEmpty()) {
       return attributes;
     }
 
+    log.error("Attribute " + attributeReference.getFullyQualifiedAttributeName() + "not found in any schema.");
     throw new AttributeDoesNotExistException(attributeReference.getFullyQualifiedAttributeName());
   }
 
   private Set<Attribute> findAttributeInSchema(Schema schema, AttributeReference attributeReference, boolean includeAttributeChain) {
     AttributeContainer attributeContainer = schema;
+    if (attributeContainer == null) {
+      return Collections.emptySet();
+    }
+    
     String[] attributeNames = attributeReference.getAttributeName();
 
     Set<Attribute> attributes = new HashSet<>();
@@ -322,7 +330,7 @@
       attributeContainer = attributeContainer.getAttribute(attributeName);
 
       if (attributeContainer == null) {
-        return null;
+        return Collections.emptySet();
       }
 
       if (includeAttributeChain) {
diff --git a/scim-server/scim-server-common/src/test/java/edu/psu/swe/scim/server/provider/UpdateRequestTest.java b/scim-server/scim-server-common/src/test/java/edu/psu/swe/scim/server/provider/UpdateRequestTest.java
index 613970d..81f5d2f 100644
--- a/scim-server/scim-server-common/src/test/java/edu/psu/swe/scim/server/provider/UpdateRequestTest.java
+++ b/scim-server/scim-server-common/src/test/java/edu/psu/swe/scim/server/provider/UpdateRequestTest.java
@@ -111,15 +111,12 @@
               .isNotNull();
   }
 
-  @Test
-  @Ignore
+  @Test(expected=UnsupportedOperationException.class)
   public void testPatchToUpdate() throws Exception {
     UpdateRequest<ScimUser> updateRequest = new UpdateRequest<>(registry);
     updateRequest.initWithPatch("1234", createUser1(), createUser1PatchOps());
-    ScimUser result = updateRequest.getResource();
-    log.info("testPatchToUpdate: " + result);
-    Assertions.assertThat(result)
-              .isNotNull();
+        
+    updateRequest.getResource();
   }
 
   @Test
diff --git a/scim-server/scim-server-example/pom.xml b/scim-server/scim-server-example/pom.xml
index 897bbda..b1cc9a4 100644
--- a/scim-server/scim-server-example/pom.xml
+++ b/scim-server/scim-server-example/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-server</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-server-examples</artifactId>
diff --git a/scim-server/scim-server-example/scim-server-couchdb/pom.xml b/scim-server/scim-server-example/scim-server-couchdb/pom.xml
index 88af26a..eb22667 100644
--- a/scim-server/scim-server-example/scim-server-couchdb/pom.xml
+++ b/scim-server/scim-server-example/scim-server-couchdb/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-server-examples</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-server-couchdb</artifactId>
diff --git a/scim-server/scim-server-example/scim-server-memory/pom.xml b/scim-server/scim-server-example/scim-server-memory/pom.xml
index 4322dfb..9ccbb3b 100644
--- a/scim-server/scim-server-example/scim-server-memory/pom.xml
+++ b/scim-server/scim-server-example/scim-server-memory/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-server-examples</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-server-memory</artifactId>
@@ -21,6 +21,11 @@
       <artifactId>scim-server-common</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/scim-server/scim-server-example/scim-server-rdbms/pom.xml b/scim-server/scim-server-example/scim-server-rdbms/pom.xml
index 820e0d9..a329966 100644
--- a/scim-server/scim-server-example/scim-server-rdbms/pom.xml
+++ b/scim-server/scim-server-example/scim-server-rdbms/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-server-examples</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-server-rdbms</artifactId>
@@ -30,6 +30,11 @@
     	<groupId>edu.psu.swe.scim</groupId>
     	<artifactId>scim-common</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
 </project>
diff --git a/scim-spec/pom.xml b/scim-spec/pom.xml
index c7e39b6..e2c6a16 100644
--- a/scim-spec/pom.xml
+++ b/scim-spec/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-spec</artifactId>
diff --git a/scim-spec/scim-spec-protocol/pom.xml b/scim-spec/scim-spec-protocol/pom.xml
index 2414c2f..95ec1ad 100644
--- a/scim-spec/scim-spec-protocol/pom.xml
+++ b/scim-spec/scim-spec-protocol/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-spec</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-spec-protocol</artifactId>
@@ -50,6 +50,7 @@
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
+      <scope>provided</scope>
     </dependency>
 
     <dependency>
diff --git a/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/Constants.java b/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/Constants.java
index 34cfc73..ffb28ff 100644
--- a/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/Constants.java
+++ b/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/Constants.java
@@ -6,4 +6,5 @@
   }
   
   public static final String SCIM_CONTENT_TYPE = "application/scim+json";
+  public static final String PATCH = "PATCH";
 }
diff --git a/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/SelfResource.java b/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/SelfResource.java
index 42f9987..fbbfccf 100644
--- a/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/SelfResource.java
+++ b/scim-spec/scim-spec-protocol/src/main/java/edu/psu/swe/scim/spec/protocol/SelfResource.java
@@ -42,10 +42,12 @@
  */
 //@formatter:on
 
-@Path("Me")
+@Path(SelfResource.PATH)
 @Api("SCIM")
 public interface SelfResource {
 
+  public static final String PATH = "Me";
+
   /**
    * @see <a href="https://tools.ietf.org/html/rfc7644#section-3.4.1">Scim spec,
    *      retrieving known resources</a>
@@ -62,7 +64,7 @@
                   @ApiResponse(code=501, message="Not Implemented")
                 })
     default Response getSelf(@ApiParam(value="attributes", required=false) @QueryParam("attributes") AttributeReferenceListWrapper attributes,
-                             @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) {
+                             @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) throws Exception {
     return Response.status(Status.NOT_IMPLEMENTED).build();
   }
 
@@ -78,7 +80,7 @@
   @ApiResponses(value = { @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 409, message = "Conflict"), @ApiResponse(code = 500, message = "Internal Server Error"), @ApiResponse(code = 501, message = "Not Implemented") })
   default Response create(ScimUser resource,
                           @ApiParam(value="attributes", required=false) @QueryParam("attributes") AttributeReferenceListWrapper attributes,
-                          @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) {
+                          @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) throws Exception {
     return Response.status(Status.NOT_IMPLEMENTED).build();
   }
 
@@ -94,7 +96,7 @@
   @ApiResponses(value = { @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 500, message = "Internal Server Error"), @ApiResponse(code = 501, message = "Not Implemented") })
   default Response update(ScimUser resource, 
                           @ApiParam(value="attributes", required=false) @QueryParam("attributes") AttributeReferenceListWrapper attributes,
-                          @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) {
+                          @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) throws Exception {
     return Response.status(Status.NOT_IMPLEMENTED).build();
   }
 
@@ -105,14 +107,14 @@
   @ApiResponses(value = { @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 404, message = "Not found"), @ApiResponse(code = 500, message = "Internal Server Error"), @ApiResponse(code = 501, message = "Not Implemented") })
   default Response patch(PatchRequest patchRequest,
                          @ApiParam(value="attributes", required=false) @QueryParam("attributes") AttributeReferenceListWrapper attributes,
-                         @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes)  {
+                         @ApiParam(value="excludedAttributes", required=false) @QueryParam("excludedAttributes") AttributeReferenceListWrapper excludedAttributes) throws Exception {
     return Response.status(Status.NOT_IMPLEMENTED).build();
   }
 
   @DELETE
   @ApiOperation(value = "Delete self record", code = 204)
   @ApiResponses(value = { @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 404, message = "Not found"), @ApiResponse(code = 500, message = "Internal Server Error"), @ApiResponse(code = 501, message = "Not Implemented") })
-  default Response delete() {
+  default Response delete() throws Exception {
     return Response.status(Status.NOT_IMPLEMENTED).build();
   }
 }
diff --git a/scim-spec/scim-spec-schema/pom.xml b/scim-spec/scim-spec-schema/pom.xml
index 6ff0e70..90d9138 100644
--- a/scim-spec/scim-spec-schema/pom.xml
+++ b/scim-spec/scim-spec-schema/pom.xml
@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>edu.psu.swe.scim</groupId>
 		<artifactId>scim-spec</artifactId>
-		<version>2.21</version>
+		<version>2.22</version>
 	</parent>
 
 	<artifactId>scim-spec-schema</artifactId>
@@ -22,6 +22,7 @@
 		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>
+			<scope>provided</scope>
 		</dependency>
 
 		<dependency>
diff --git a/scim-spec/scim-spec-schema/src/main/java/edu/psu/swe/scim/spec/resources/PhoneNumber.java b/scim-spec/scim-spec-schema/src/main/java/edu/psu/swe/scim/spec/resources/PhoneNumber.java
index e81b532..7b8c750 100644
--- a/scim-spec/scim-spec-schema/src/main/java/edu/psu/swe/scim/spec/resources/PhoneNumber.java
+++ b/scim-spec/scim-spec-schema/src/main/java/edu/psu/swe/scim/spec/resources/PhoneNumber.java
@@ -71,7 +71,7 @@
   @ScimAttribute(description = "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g. the preferred phone number or primary phone number. The primary attribute value 'true' MUST appear no more than once.")
   @Getter
   @Setter
-  Boolean primary;
+  Boolean primary = false;
 
   @Setter(AccessLevel.NONE)
   @Getter
diff --git a/scim-tools/pom.xml b/scim-tools/pom.xml
index 25742ce..10b8663 100644
--- a/scim-tools/pom.xml
+++ b/scim-tools/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-parent</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-tools</artifactId>
diff --git a/scim-tools/scim-tools-cli/pom.xml b/scim-tools/scim-tools-cli/pom.xml
index 4f7c3bc..f8869be 100644
--- a/scim-tools/scim-tools-cli/pom.xml
+++ b/scim-tools/scim-tools-cli/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-tools</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-tools-cli</artifactId>
diff --git a/scim-tools/scim-tools-common/pom.xml b/scim-tools/scim-tools-common/pom.xml
index 64127fd..262c8d3 100644
--- a/scim-tools/scim-tools-common/pom.xml
+++ b/scim-tools/scim-tools-common/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-tools</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-tools-common</artifactId>
diff --git a/scim-tools/scim-tools-studio/pom.xml b/scim-tools/scim-tools-studio/pom.xml
index 7a0134a..2d569af 100644
--- a/scim-tools/scim-tools-studio/pom.xml
+++ b/scim-tools/scim-tools-studio/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>edu.psu.swe.scim</groupId>
     <artifactId>scim-tools</artifactId>
-    <version>2.21</version>
+    <version>2.22</version>
   </parent>
 
   <artifactId>scim-tools-studio</artifactId>