From 97ca7b81487172761e42fe7ecd2e5184336825f2 Mon Sep 17 00:00:00 2001
From: Bogdan Irimie <bogdan.irimie@aserto.com>
Date: Fri, 29 Dec 2023 17:38:37 +0200
Subject: [PATCH] Throw UninitilizedClientException when trying to call a
 directory operation with an uninitialised client. Bump artefact version to
 0.21.0 Add new constructor to DirectoryClient.

---
 pom.xml                                       |   2 +-
 .../aserto/directory/v3/DirectoryClient.java  | 187 +++++++++++++-----
 .../directory/v3/DirectoryClientExporter.java |   4 +-
 .../directory/v3/DirectoryClientImporter.java |   2 +-
 .../directory/v3/DirectoryClientModel.java    |   6 +-
 .../directory/v3/DirectoryClientReader.java   |  30 +--
 .../directory/v3/DirectoryClientWriter.java   |  18 +-
 .../v3/UninitilizedClientException.java       |   7 +
 src/test/java/DirectoryClientTest.java        |  51 +++--
 9 files changed, 198 insertions(+), 109 deletions(-)
 create mode 100644 src/main/java/com/aserto/directory/v3/UninitilizedClientException.java

diff --git a/pom.xml b/pom.xml
index a0331a3..02fc799 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
     <groupId>com.aserto</groupId>
     <artifactId>aserto-java</artifactId>
-    <version>0.20.11</version>
+    <version>0.21.00</version>
 
     <name>${project.groupId}:${project.artifactId}</name>
     <description>Java SDK to interact with aserto services</description>
diff --git a/src/main/java/com/aserto/directory/v3/DirectoryClient.java b/src/main/java/com/aserto/directory/v3/DirectoryClient.java
index d6301c8..57d8a77 100644
--- a/src/main/java/com/aserto/directory/v3/DirectoryClient.java
+++ b/src/main/java/com/aserto/directory/v3/DirectoryClient.java
@@ -50,7 +50,27 @@ public class DirectoryClient implements DirectoryClientReader,
     private ModelGrpc.ModelBlockingStub modelClient;
     private ModelGrpc.ModelStub modelClientAsync;
 
-    public DirectoryClient() {
+    public DirectoryClient(ManagedChannel readerChannel, ManagedChannel writerChannel, ManagedChannel importerChannel, ManagedChannel exporterChannel, ManagedChannel modelChannel) {
+        if (readerChannel != null) {
+            readerClient = ReaderGrpc.newBlockingStub(readerChannel);
+        }
+
+        if (writerChannel != null) {
+            writerClient = WriterGrpc.newBlockingStub(writerChannel);
+        }
+
+        if (importerChannel != null) {
+            importerClient = ImporterGrpc.newStub(importerChannel);
+        }
+
+        if (exporterChannel != null) {
+            exporterClient = ExporterGrpc.newBlockingStub(exporterChannel);
+        }
+
+        if (modelChannel != null) {
+            modelClient = ModelGrpc.newBlockingStub(modelChannel);
+            modelClientAsync = ModelGrpc.newStub(modelChannel);
+        }
     }
 
     public DirectoryClient(ManagedChannel managedChannel) {
@@ -62,33 +82,16 @@ public DirectoryClient(ManagedChannel managedChannel) {
         modelClientAsync = ModelGrpc.newStub(managedChannel);
     }
 
-    public void withReaderChannel(ManagedChannel readerChannel) {
-        this.readerClient = ReaderGrpc.newBlockingStub(readerChannel);
-    }
-
-    public void withWriterChannel(ManagedChannel writerChannel) {
-        this.writerClient = WriterGrpc.newBlockingStub(writerChannel);
-    }
-
-    public void withImporterChannel(ManagedChannel importerChannel) {
-        this.importerClient = ImporterGrpc.newStub(importerChannel);
-    }
-
-    public void withExporterChannel(ManagedChannel exporterChannel) {
-        this.exporterClient = ExporterGrpc.newBlockingStub(exporterChannel);
-    }
-
-    public void withModelChannel(ManagedChannel modelChannel) {
-        this.modelClient = ModelGrpc.newBlockingStub(modelChannel);
-        this.modelClientAsync = ModelGrpc.newStub(modelChannel);
-    }
-
     @Override
-    public GetObjectResponse getObject(String type, String id) {
+    public GetObjectResponse getObject(String type, String id) throws UninitilizedClientException {
         return getObject(type, id, false);
     }
     @Override
-    public GetObjectResponse getObject(String type, String id, boolean withRelations) {
+    public GetObjectResponse getObject(String type, String id, boolean withRelations) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.getObject(GetObjectRequest.newBuilder()
                 .setObjectType(type)
                 .setObjectId(id)
@@ -97,12 +100,16 @@ public GetObjectResponse getObject(String type, String id, boolean withRelations
     }
 
     @Override
-    public GetObjectsResponse getObjects(String type) {
+    public GetObjectsResponse getObjects(String type) throws UninitilizedClientException {
         return getObjects(type, 100, "");
     }
 
     @Override
-    public GetObjectsResponse getObjects(String type, int pageSize, String pageToken) {
+    public GetObjectsResponse getObjects(String type, int pageSize, String pageToken) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.getObjects(GetObjectsRequest.newBuilder()
                 .setObjectType(type)
                 .setPage(buildPaginationRequest(pageSize, pageToken))
@@ -110,7 +117,11 @@ public GetObjectsResponse getObjects(String type, int pageSize, String pageToken
     }
 
     @Override
-    public GetObjectManyResponse getObjectManyRequest(List<ObjectIdentifier> objectIdentifiers) {
+    public GetObjectManyResponse getObjectManyRequest(List<ObjectIdentifier> objectIdentifiers) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.getObjectMany(GetObjectManyRequest.newBuilder()
                 .addAllParam(new ObjectIdentifierList(objectIdentifiers))
                 .build());
@@ -124,17 +135,21 @@ private PaginationRequest buildPaginationRequest(int pageSize, String pageToken)
     }
 
     @Override
-    public GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) {
+    public GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException {
         return getRelation(objectType, objectId, relationName, subjectType, subjectId, "", false);
     }
 
     @Override
-    public GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation) {
+    public GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation) throws UninitilizedClientException {
         return getRelation(objectType, objectId, relationName, subjectType, subjectId, subjectRelation, false);
     }
 
     @Override
-    public GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation, boolean withObjects) {
+    public GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation, boolean withObjects) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.getRelation(GetRelationRequest.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -147,17 +162,25 @@ public GetRelationResponse getRelation(String objectType, String objectId, Strin
     }
 
     @Override
-    public GetRelationsResponse getRelations(GetRelationsRequest relationsRequest) {
+    public GetRelationsResponse getRelations(GetRelationsRequest relationsRequest) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.getRelations(relationsRequest);
     }
 
     @Override
-    public CheckPermissionResponse checkPermission(String objectType, String objectId, String subjectType, String subjectId, String permissionName) {
+    public CheckPermissionResponse checkPermission(String objectType, String objectId, String subjectType, String subjectId, String permissionName) throws UninitilizedClientException {
         return checkPermission(objectType, objectId, subjectType, subjectId, permissionName, false);
     }
 
     @Override
-    public CheckPermissionResponse checkPermission(String objectType, String objectId, String subjectType, String subjectId, String permissionName, boolean trace) {
+    public CheckPermissionResponse checkPermission(String objectType, String objectId, String subjectType, String subjectId, String permissionName, boolean trace) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.checkPermission(CheckPermissionRequest.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -169,12 +192,16 @@ public CheckPermissionResponse checkPermission(String objectType, String objectI
     }
 
     @Override
-    public CheckRelationResponse checkRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) {
+    public CheckRelationResponse checkRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException {
         return checkRelation(objectType, objectId, relationName, subjectType, subjectId, false);
     }
 
     @Override
-    public CheckRelationResponse checkRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, boolean trace) {
+    public CheckRelationResponse checkRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, boolean trace) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.checkRelation(CheckRelationRequest.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -186,12 +213,16 @@ public CheckRelationResponse checkRelation(String objectType, String objectId, S
     }
 
     @Override
-    public CheckResponse check(String objectType, String objectId, String relationName, String subjectType, String subjectId) {
+    public CheckResponse check(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException {
         return check(objectType, objectId, relationName, subjectType, subjectId, false);
     }
 
     @Override
-    public CheckResponse check(String objectType, String objectId, String relationName, String subjectType, String subjectId, boolean trace) {
+    public CheckResponse check(String objectType, String objectId, String relationName, String subjectType, String subjectId, boolean trace) throws UninitilizedClientException {
+        if (readerClient == null) {
+            throw new UninitilizedClientException("Reader client is not initialized");
+        }
+
         return readerClient.check(CheckRequest.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -208,12 +239,16 @@ public GetGraphResponse getGraph(GetGraphRequest getGraphRequest) {
     }
 
     @Override
-    public SetObjectResponse setObject(String type, String id) {
+    public SetObjectResponse setObject(String type, String id) throws UninitilizedClientException {
         return setObject(type, id, "", Struct.newBuilder().build(), "");
     }
 
     @Override
-    public SetObjectResponse setObject(String type, String id, String displayName, Struct properties, String hash) {
+    public SetObjectResponse setObject(String type, String id, String displayName, Struct properties, String hash) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         Instant time = Instant.now();
         Timestamp timestamp = Timestamp.newBuilder().setSeconds(time.getEpochSecond())
                 .setNanos(time.getNano()).build();
@@ -232,12 +267,16 @@ public SetObjectResponse setObject(String type, String id, String displayName, S
     }
 
     @Override
-    public DeleteObjectResponse deleteObject(String type, String id) {
+    public DeleteObjectResponse deleteObject(String type, String id) throws UninitilizedClientException {
         return deleteObject(type, id, false);
     }
 
     @Override
-    public DeleteObjectResponse deleteObject(String type, String id, boolean withRelations) {
+    public DeleteObjectResponse deleteObject(String type, String id, boolean withRelations) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         return writerClient.deleteObject(DeleteObjectRequest.newBuilder()
                 .setObjectType(type)
                 .setObjectId(id)
@@ -246,7 +285,11 @@ public DeleteObjectResponse deleteObject(String type, String id, boolean withRel
     }
 
     @Override
-    public SetRelationResponse setRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) {
+    public SetRelationResponse setRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         Relation relation = Relation.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -259,7 +302,11 @@ public SetRelationResponse setRelation(String objectType, String objectId, Strin
     }
 
     @Override
-    public SetRelationResponse setRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation) {
+    public SetRelationResponse setRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         Relation relation = Relation.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -273,7 +320,11 @@ public SetRelationResponse setRelation(String objectType, String objectId, Strin
     }
 
     @Override
-    public SetRelationResponse setRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation, String hash) {
+    public SetRelationResponse setRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation, String hash) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         Relation relation = Relation.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -288,7 +339,11 @@ public SetRelationResponse setRelation(String objectType, String objectId, Strin
     }
 
     @Override
-    public DeleteRelationResponse deleteRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) {
+    public DeleteRelationResponse deleteRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         return writerClient.deleteRelation(DeleteRelationRequest.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -299,7 +354,11 @@ public DeleteRelationResponse deleteRelation(String objectType, String objectId,
     }
 
     @Override
-    public DeleteRelationResponse deleteRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation) {
+    public DeleteRelationResponse deleteRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId, String subjectRelation) throws UninitilizedClientException {
+        if (writerClient == null) {
+            throw new UninitilizedClientException("Writer client is not initialized");
+        }
+
         return writerClient.deleteRelation(DeleteRelationRequest.newBuilder()
                 .setObjectType(objectType)
                 .setObjectId(objectId)
@@ -311,7 +370,11 @@ public DeleteRelationResponse deleteRelation(String objectType, String objectId,
     }
 
     @Override
-    public GetManifestResponse getManifest() {
+    public GetManifestResponse getManifest() throws UninitilizedClientException {
+        if (modelClient == null) {
+            throw new UninitilizedClientException("Model client is not initialized");
+        }
+
         GetManifestRequest manifestRequest = GetManifestRequest.newBuilder().build();
         Iterator<GetManifestResponse> manifestResponses =  modelClient.getManifest(manifestRequest);
 
@@ -340,7 +403,11 @@ public GetManifestResponse getManifest() {
     }
 
     @Override
-    public void setManifest(String manifest) throws InterruptedException {
+    public void setManifest(String manifest) throws InterruptedException, UninitilizedClientException {
+        if (modelClientAsync == null) {
+            throw new UninitilizedClientException("Model client is not initialized");
+        }
+
         CountDownLatch latch = new CountDownLatch(1);
 
         StreamObserver<SetManifestResponse> readStream = new StreamObserver<SetManifestResponse>() {
@@ -380,12 +447,20 @@ public void onCompleted() {
 
 
     @Override
-    public DeleteManifestResponse deleteManifest() {
+    public DeleteManifestResponse deleteManifest() throws UninitilizedClientException {
+        if (modelClient == null) {
+            throw new UninitilizedClientException("Model client is not initialized");
+        }
+
         return modelClient.deleteManifest(DeleteManifestRequest.newBuilder().build());
     }
 
     @Override
-    public void importData(Stream<ImportElement> importStream) throws InterruptedException {
+    public void importData(Stream<ImportElement> importStream) throws InterruptedException, UninitilizedClientException {
+        if (importerClient == null) {
+            throw new UninitilizedClientException("Import client is not initialized");
+        }
+
         CountDownLatch latch = new CountDownLatch(1);
         StreamObserver<ImportResponse> readStream = new StreamObserver<ImportResponse>() {
             @Override
@@ -423,14 +498,22 @@ public void onCompleted() {
     }
 
     @Override
-    public Iterator<ExportResponse> exportData(Option options) {
+    public Iterator<ExportResponse> exportData(Option options) throws UninitilizedClientException {
+        if (exporterClient == null) {
+            throw new UninitilizedClientException("Export client is not initialized");
+        }
+
         return exporterClient.export(ExportRequest.newBuilder()
                 .setOptions(options.getNumber())
                 .build());
     }
 
     @Override
-    public Iterator<ExportResponse> exportData(Option options, Timestamp startFrom) {
+    public Iterator<ExportResponse> exportData(Option options, Timestamp startFrom) throws UninitilizedClientException {
+        if (exporterClient == null) {
+            throw new UninitilizedClientException("Export client is not initialized");
+        }
+
         return exporterClient.export(ExportRequest.newBuilder()
                 .setOptions(options.getNumber())
                 .setStartFrom(startFrom)
diff --git a/src/main/java/com/aserto/directory/v3/DirectoryClientExporter.java b/src/main/java/com/aserto/directory/v3/DirectoryClientExporter.java
index fd5c6e3..09f0146 100644
--- a/src/main/java/com/aserto/directory/v3/DirectoryClientExporter.java
+++ b/src/main/java/com/aserto/directory/v3/DirectoryClientExporter.java
@@ -7,6 +7,6 @@
 import java.util.Iterator;
 
 public interface DirectoryClientExporter {
-    Iterator<ExportResponse> exportData(Option options);
-    Iterator<ExportResponse> exportData(Option options, Timestamp startFrom);
+    Iterator<ExportResponse> exportData(Option options) throws UninitilizedClientException;
+    Iterator<ExportResponse> exportData(Option options, Timestamp startFrom) throws UninitilizedClientException;
 }
diff --git a/src/main/java/com/aserto/directory/v3/DirectoryClientImporter.java b/src/main/java/com/aserto/directory/v3/DirectoryClientImporter.java
index aea6276..65f3efd 100644
--- a/src/main/java/com/aserto/directory/v3/DirectoryClientImporter.java
+++ b/src/main/java/com/aserto/directory/v3/DirectoryClientImporter.java
@@ -4,5 +4,5 @@
 import java.util.stream.Stream;
 
 public interface DirectoryClientImporter {
-    void importData(Stream<ImportElement> importStream) throws InterruptedException;
+    void importData(Stream<ImportElement> importStream) throws InterruptedException, UninitilizedClientException;
 }
diff --git a/src/main/java/com/aserto/directory/v3/DirectoryClientModel.java b/src/main/java/com/aserto/directory/v3/DirectoryClientModel.java
index 763c320..21645ab 100644
--- a/src/main/java/com/aserto/directory/v3/DirectoryClientModel.java
+++ b/src/main/java/com/aserto/directory/v3/DirectoryClientModel.java
@@ -4,7 +4,7 @@
 import com.aserto.directory.model.v3.GetManifestResponse;
 
 public interface DirectoryClientModel {
-    GetManifestResponse getManifest();
-    void setManifest(String manifest) throws InterruptedException;
-    DeleteManifestResponse deleteManifest();
+    GetManifestResponse getManifest() throws UninitilizedClientException;
+    void setManifest(String manifest) throws InterruptedException, UninitilizedClientException;
+    DeleteManifestResponse deleteManifest() throws UninitilizedClientException;
 }
diff --git a/src/main/java/com/aserto/directory/v3/DirectoryClientReader.java b/src/main/java/com/aserto/directory/v3/DirectoryClientReader.java
index 5a5b541..aadc21c 100644
--- a/src/main/java/com/aserto/directory/v3/DirectoryClientReader.java
+++ b/src/main/java/com/aserto/directory/v3/DirectoryClientReader.java
@@ -6,28 +6,28 @@
 import java.util.List;
 
 public interface DirectoryClientReader {
-    GetObjectResponse getObject(String type, String id);
-    GetObjectResponse getObject(String type, String id, boolean withRelations);
-    GetObjectsResponse getObjects(String type);
-    GetObjectsResponse getObjects(String type, int pageSize, String pageToken);
-    GetObjectManyResponse getObjectManyRequest(List<ObjectIdentifier> objectIdentifiers);
+    GetObjectResponse getObject(String type, String id) throws UninitilizedClientException;
+    GetObjectResponse getObject(String type, String id, boolean withRelations) throws UninitilizedClientException;
+    GetObjectsResponse getObjects(String type) throws UninitilizedClientException;
+    GetObjectsResponse getObjects(String type, int pageSize, String pageToken) throws UninitilizedClientException;
+    GetObjectManyResponse getObjectManyRequest(List<ObjectIdentifier> objectIdentifiers) throws UninitilizedClientException;
     GetRelationResponse getRelation(String objectType, String objectId, String relationName,
-                                           String subjectType, String subjectId);
+                                           String subjectType, String subjectId) throws UninitilizedClientException;
     GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType,
-                                           String subjectId, String subjectRelation);
+                                           String subjectId, String subjectRelation) throws UninitilizedClientException;
     GetRelationResponse getRelation(String objectType, String objectId, String relationName, String subjectType,
-                                           String subjectId, String subjectRelation, boolean withObjects);
-    GetRelationsResponse getRelations(GetRelationsRequest relationsRequest);
+                                           String subjectId, String subjectRelation, boolean withObjects) throws UninitilizedClientException;
+    GetRelationsResponse getRelations(GetRelationsRequest relationsRequest) throws UninitilizedClientException;
 
     CheckPermissionResponse checkPermission(String objectType, String objectId, String subjectType,
-                                                   String subjectId, String permissionName);
+                                                   String subjectId, String permissionName) throws UninitilizedClientException;
     CheckPermissionResponse checkPermission(String objectType, String objectId,
-                                                   String subjectType, String subjectId, String permissionName, boolean trace);
-    CheckRelationResponse checkRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId);
+                                                   String subjectType, String subjectId, String permissionName, boolean trace) throws UninitilizedClientException;
+    CheckRelationResponse checkRelation(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException;
     CheckRelationResponse checkRelation(String objectType, String objectId, String relationName,
-                                               String subjectType, String subjectId, boolean trace);
-    CheckResponse check(String objectType, String objectId, String relationName, String subjectType, String subjectId);
+                                               String subjectType, String subjectId, boolean trace) throws UninitilizedClientException;
+    CheckResponse check(String objectType, String objectId, String relationName, String subjectType, String subjectId) throws UninitilizedClientException;
     CheckResponse check(String objectType, String objectId, String relationName,
-                               String subjectType, String subjectId, boolean trace);
+                               String subjectType, String subjectId, boolean trace) throws UninitilizedClientException;
     GetGraphResponse getGraph(GetGraphRequest getGraphRequest);
 }
diff --git a/src/main/java/com/aserto/directory/v3/DirectoryClientWriter.java b/src/main/java/com/aserto/directory/v3/DirectoryClientWriter.java
index b07bebc..c94d8b3 100644
--- a/src/main/java/com/aserto/directory/v3/DirectoryClientWriter.java
+++ b/src/main/java/com/aserto/directory/v3/DirectoryClientWriter.java
@@ -7,18 +7,18 @@
 import com.google.protobuf.Struct;
 
 public interface DirectoryClientWriter {
-    public SetObjectResponse setObject(String type, String id);
-    public SetObjectResponse setObject(String type, String id, String displayName, Struct properties, String hash);
-    public DeleteObjectResponse deleteObject(String type, String id);
-    public DeleteObjectResponse deleteObject(String type, String id, boolean withRelations);
+    public SetObjectResponse setObject(String type, String id) throws UninitilizedClientException;
+    public SetObjectResponse setObject(String type, String id, String displayName, Struct properties, String hash) throws UninitilizedClientException;
+    public DeleteObjectResponse deleteObject(String type, String id) throws UninitilizedClientException;
+    public DeleteObjectResponse deleteObject(String type, String id, boolean withRelations) throws UninitilizedClientException;
     public SetRelationResponse setRelation(String objectType, String objectId, String relationName,
-                                           String subjectType, String subjectId);
+                                           String subjectType, String subjectId) throws UninitilizedClientException;
     public SetRelationResponse setRelation(String objectType, String objectId, String relationName,
-                                           String subjectType, String subjectId, String subjectRelation);
+                                           String subjectType, String subjectId, String subjectRelation) throws UninitilizedClientException;
     public SetRelationResponse setRelation(String objectType, String objectId, String relationName,
-                                           String subjectType, String subjectId, String subjectRelation, String hash);
+                                           String subjectType, String subjectId, String subjectRelation, String hash) throws UninitilizedClientException;
     public DeleteRelationResponse deleteRelation(String objectType, String objectId, String relationName,
-                                                 String subjectType, String subjectId);
+                                                 String subjectType, String subjectId) throws UninitilizedClientException;
     public DeleteRelationResponse deleteRelation(String objectType, String objectId, String relationName,
-                                                 String subjectType, String subjectId, String subjectRelation);
+                                                 String subjectType, String subjectId, String subjectRelation) throws UninitilizedClientException;
 }
diff --git a/src/main/java/com/aserto/directory/v3/UninitilizedClientException.java b/src/main/java/com/aserto/directory/v3/UninitilizedClientException.java
new file mode 100644
index 0000000..16d42e6
--- /dev/null
+++ b/src/main/java/com/aserto/directory/v3/UninitilizedClientException.java
@@ -0,0 +1,7 @@
+package com.aserto.directory.v3;
+
+public class UninitilizedClientException extends Exception {
+    public UninitilizedClientException(String message) {
+        super(message);
+    }
+}
diff --git a/src/test/java/DirectoryClientTest.java b/src/test/java/DirectoryClientTest.java
index 195a9be..a284633 100644
--- a/src/test/java/DirectoryClientTest.java
+++ b/src/test/java/DirectoryClientTest.java
@@ -10,6 +10,7 @@
 import com.aserto.directory.common.v3.ObjectIdentifier;
 import com.aserto.directory.common.v3.Relation;
 import com.aserto.directory.reader.v3.*;
+import com.aserto.directory.v3.UninitilizedClientException;
 import com.aserto.directory.writer.v3.DeleteRelationResponse;
 import com.aserto.directory.writer.v3.SetObjectResponse;
 import com.aserto.directory.writer.v3.SetRelationResponse;
@@ -84,14 +85,14 @@ static void setDirectoryClient() throws SSLException {
     }
 
     @BeforeEach
-    void beforeEach() throws InterruptedException {
+    void beforeEach() throws InterruptedException, UninitilizedClientException {
         directoryClient.setManifest(originalManifest);
         List<ImportElement> list = importCitadelDataList();
         directoryClient.importData(list.stream());
     }
 
     @AfterEach
-    void afterEach() {
+    void afterEach() throws UninitilizedClientException {
         directoryClient.deleteManifest();
     }
 
@@ -104,8 +105,7 @@ static void closeChannel() {
     @Test
     void testDirectoryClientWithReaderCanRead() {
         // Arrange
-        DirectoryClient directoryClient = new DirectoryClient();
-        directoryClient.withReaderChannel(channel);
+        DirectoryClient directoryClient = new DirectoryClient(channel, null, null, null, null);
 
         // Act & Assert
         assertDoesNotThrow(() -> {
@@ -116,18 +116,17 @@ void testDirectoryClientWithReaderCanRead() {
     @Test
     void testDirectoryClientWithReaderCannotWrite() {
         // Arrange
-        DirectoryClient directoryClient = new DirectoryClient();
-        directoryClient.withReaderChannel(channel);
+        DirectoryClient directoryClient = new DirectoryClient(channel, null, null, null, null);
 
 
         // Act & Assert
-        assertThrows(NullPointerException.class, () -> {
+        assertThrows(UninitilizedClientException.class, () -> {
             directoryClient.setObject("test_type", "test_id");
         });
     }
 
     @Test
-    void testGetUserWithNoRelations() {
+    void testGetUserWithNoRelations() throws UninitilizedClientException {
         // Arrange
         Object managerObject = Directory.buildObject("user", "rick@the-citadel.com");
 
@@ -143,7 +142,7 @@ void testGetUserWithNoRelations() {
     }
 
     @Test
-    void testGetUserWithRelations() {
+    void testGetUserWithRelations() throws UninitilizedClientException {
         // Arrange
         Object managerObject = Directory.buildObject("user", "rick@the-citadel.com");
         Relation managerRelation = Directory.buildRelation("user", "rick@the-citadel.com", "manager", "user", "morty@the-citadel.com");
@@ -163,7 +162,7 @@ void testGetUserWithRelations() {
     }
 
     @Test
-    void testGetUsers() {
+    void testGetUsers() throws UninitilizedClientException {
         // Arrange & Act
         GetObjectsResponse getObjectsResponse = directoryClient.getObjects("user");
 
@@ -172,7 +171,7 @@ void testGetUsers() {
     }
 
     @Test
-    void testGetUsersWithLimit() {
+    void testGetUsersWithLimit() throws UninitilizedClientException {
         // Arrange & Act
         GetObjectsResponse getObjectsResponse = directoryClient.getObjects("user", 1, "");
 
@@ -184,7 +183,7 @@ void testGetUsersWithLimit() {
     }
 
     @Test
-    void testGetUserManyRequest() {
+    void testGetUserManyRequest() throws UninitilizedClientException {
         // Arrange
         List<ObjectIdentifier> objects = List.of(
             Directory.buildObjectIdentifier("user", "rick@the-citadel.com"),
@@ -200,7 +199,7 @@ void testGetUserManyRequest() {
     }
 
     @Test
-    void testGetRelation() {
+    void testGetRelation() throws UninitilizedClientException {
         // Arrange
         Relation expectedRelation = Directory.buildRelation("user", "rick@the-citadel.com", "manager", "user", "morty@the-citadel.com");
 
@@ -221,7 +220,7 @@ void testGetRelation() {
     }
 
     @Test
-    void testGetRelations() {
+    void testGetRelations() throws UninitilizedClientException {
         // Arrange
         Relation expectedManagerRelation = Directory.buildRelation("user", "rick@the-citadel.com", "manager", "user", "morty@the-citadel.com");
         Relation expectedFriendRelation = Directory.buildRelation("user", "rick@the-citadel.com", "friend", "user", "morty@the-citadel.com");
@@ -246,7 +245,7 @@ void testGetRelations() {
     }
 
     @Test
-    void testCheckRelationManager() {
+    void testCheckRelationManager() throws UninitilizedClientException {
         // Arrange & Act
         CheckRelationResponse checkRelationResponse = directoryClient.checkRelation(
                 "user",
@@ -260,7 +259,7 @@ void testCheckRelationManager() {
     }
 
     @Test
-    void testCheckRelationFriend() {
+    void testCheckRelationFriend() throws UninitilizedClientException {
         // Arrange & Act
         CheckRelationResponse checkRelationResponse = directoryClient.checkRelation(
                 "user",
@@ -274,7 +273,7 @@ void testCheckRelationFriend() {
     }
 
     @Test
-    void testCheckManager() {
+    void testCheckManager() throws UninitilizedClientException {
         // Arrange & Act
         CheckResponse checkResponse = directoryClient.check(
                 "user",
@@ -317,7 +316,7 @@ void testGetGraph() {
     }
 
     @Test
-    void setObjectTest() {
+    void setObjectTest() throws UninitilizedClientException {
         // Arrange
         Object object = Directory.buildObject("test_type", "test_id");
 
@@ -332,7 +331,7 @@ void setObjectTest() {
     }
 
     @Test
-    void deleteObjectTest() {
+    void deleteObjectTest() throws UninitilizedClientException {
         // Arrange
         directoryClient.setObject("test_type", "test_id");
         assertEquals(1, directoryClient.getObjects("test_type").getResultsList().size());
@@ -345,7 +344,7 @@ void deleteObjectTest() {
     }
 
     @Test
-    void setRelationTest() {
+    void setRelationTest() throws UninitilizedClientException {
         // Arrange
         Relation relation = Directory.buildRelation("user", "morty@the-citadel.com", "friend", "user", "rick@the-citadel.com");
 
@@ -365,7 +364,7 @@ void setRelationTest() {
     }
 
     @Test
-    void deleteRelationTest() {
+    void deleteRelationTest() throws UninitilizedClientException {
         // Arrange & Act
         DeleteRelationResponse deleteRelationResponse = directoryClient.deleteRelation(
                 "user",
@@ -388,7 +387,7 @@ void deleteRelationTest() {
     }
 
     @Test
-    void testGetManifest() {
+    void testGetManifest() throws UninitilizedClientException {
         // Arrange & Act
         GetManifestResponse getManifestResponse = directoryClient.getManifest();
 
@@ -397,7 +396,7 @@ void testGetManifest() {
     }
 
     @Test
-    void testSetManifest() throws InterruptedException {
+    void testSetManifest() throws InterruptedException, UninitilizedClientException {
         // Arrange & Act
         directoryClient.setManifest(modifiedManifest);
         GetManifestResponse getManifestResponse = directoryClient.getManifest();
@@ -407,7 +406,7 @@ void testSetManifest() throws InterruptedException {
     }
 
     @Test
-    void testDeleteManifest() {
+    void testDeleteManifest() throws UninitilizedClientException {
         // Arrange & Act
         directoryClient.deleteManifest();
         GetManifestResponse getManifestResponse = directoryClient.getManifest();
@@ -417,7 +416,7 @@ void testDeleteManifest() {
     }
 
     @Test
-    void importDataTest() throws InterruptedException {
+    void importDataTest() throws InterruptedException, UninitilizedClientException {
         // Arrange
         List<ImportElement> list = importCitadelDataList();
         List<Object> users = list.stream()
@@ -437,7 +436,7 @@ void importDataTest() throws InterruptedException {
     }
 
     @Test
-    void exportDataTest() {
+    void exportDataTest() throws UninitilizedClientException {
         // Arrange & Act
         Iterator<ExportResponse> exportedData = directoryClient.exportData(Option.OPTION_DATA);