Skip to content

Commit

Permalink
Merge pull request #3 from openstandia/dev
Browse files Browse the repository at this point in the history
fix: error handling for GET request
  • Loading branch information
wadahiro authored Aug 15, 2024
2 parents 22ecf28 + dad6cae commit bfa57a2
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 51 deletions.
78 changes: 38 additions & 40 deletions src/main/java/jp/openstandia/connector/notion/NotionRESTClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,33 +137,32 @@ public Uid createUser(NotionUserModel newUser) throws AlreadyExistsException {
}

public NotionUserModel getUser(Uid uid, OperationOptions options, Set<String> fetchFieldsSet) throws UnknownUidException {
try (Response response = get(userEndpoint + "/" + uid.getUidValue(), null)) {
try {
NotionUserModel user = MAPPER.readValue(response.body().byteStream(), NotionUserModel.class);
return user;

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
try (Response response = callRead(USER_OBJECT_CLASS, userEndpoint, uid)) {
if (response == null) {
return null;
}
NotionUserModel user = MAPPER.readValue(response.body().byteStream(), NotionUserModel.class);
return user;

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
}
}

public NotionUserModel getUser(Name name, OperationOptions options, Set<String> fetchFieldsSet) throws UnknownUidException {
Map<String, String> params = new HashMap<>();
params.put("filter", formatFilter("userName eq \"%s\"", name.getNameValue()));

try (Response response = get(userEndpoint, params)) {
try {
UserListBody list = MAPPER.readValue(response.body().byteStream(), UserListBody.class);
if (list.resources == null || list.resources.size() != 1) {
LOG.info("The user is not found. userName={0}", name.getNameValue());
return null;
}
return list.resources.get(0);

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
try (Response response = callSearch(USER_OBJECT_CLASS, userEndpoint, params)) {
UserListBody list = MAPPER.readValue(response.body().byteStream(), UserListBody.class);
if (list.resources == null || list.resources.size() != 1) {
LOG.info("The {0} user is not found. userName={1}", instanceName, name.getNameValue());
return null;
}
return list.resources.get(0);

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
}
}

Expand All @@ -190,7 +189,7 @@ public int getUsers(QueryHandler<NotionUserModel> handler, OperationOptions opti
params.put(offsetKey, String.valueOf(start));
params.put(countKey, String.valueOf(size));

try (Response response = get(userEndpoint, params)) {
try (Response response = callSearch(USER_OBJECT_CLASS, userEndpoint, params)) {
UserListBody list = MAPPER.readValue(response.body().byteStream(), UserListBody.class);
return list.resources;

Expand All @@ -208,7 +207,7 @@ public int getUsers(QueryHandler<NotionUserModel> handler, OperationOptions opti
params.put(offsetKey, String.valueOf(start));
params.put(countKey, String.valueOf(pageSize));

try (Response response = get(userEndpoint, params)) {
try (Response response = callSearch(USER_OBJECT_CLASS, userEndpoint, params)) {
UserListBody list = MAPPER.readValue(response.body().byteStream(), UserListBody.class);
for (NotionUserModel user : list.resources) {
if (!handler.handle(user)) {
Expand Down Expand Up @@ -241,33 +240,32 @@ public void patchGroup(Uid uid, PatchOperationsModel operations) {
}

public NotionGroupModel getGroup(Uid uid, OperationOptions options, Set<String> fetchFieldsSet) throws UnknownUidException {
try (Response response = get(groupEndpoint + "/" + uid.getUidValue(), null)) {
try {
NotionGroupModel group = MAPPER.readValue(response.body().byteStream(), NotionGroupModel.class);
return group;

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
try (Response response = callRead(GROUP_OBJECT_CLASS, groupEndpoint, uid)) {
if (response == null) {
return null;
}
NotionGroupModel group = MAPPER.readValue(response.body().byteStream(), NotionGroupModel.class);
return group;

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
}
}

public NotionGroupModel getGroup(Name name, OperationOptions options, Set<String> fetchFieldsSet) {
Map<String, String> params = new HashMap<>();
params.put("filter", formatFilter("displayName eq \"%s\"", name.getNameValue()));

try (Response response = get(groupEndpoint, params)) {
try {
GroupListBody list = MAPPER.readValue(response.body().byteStream(), GroupListBody.class);
if (list.resources == null || list.resources.size() != 1) {
LOG.info("The group is not found. displayName={0}", name.getNameValue());
return null;
}
return list.resources.get(0);

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
try (Response response = callSearch(GROUP_OBJECT_CLASS, groupEndpoint, params)) {
GroupListBody list = MAPPER.readValue(response.body().byteStream(), GroupListBody.class);
if (list.resources == null || list.resources.size() != 1) {
LOG.info("The {0} group is not found. displayName={1}", instanceName, name.getNameValue());
return null;
}
return list.resources.get(0);

} catch (IOException e) {
throw new ConnectorIOException(String.format("Cannot parse %s REST API Response", instanceName), e);
}
}

Expand All @@ -279,7 +277,7 @@ public int getGroups(QueryHandler<NotionGroupModel> handler, OperationOptions op
params.put(offsetKey, String.valueOf(start));
params.put(countKey, String.valueOf(size));

try (Response response = get(groupEndpoint, params)) {
try (Response response = callSearch(GROUP_OBJECT_CLASS, groupEndpoint, params)) {
GroupListBody list = MAPPER.readValue(response.body().byteStream(), GroupListBody.class);
return list.resources;

Expand All @@ -296,7 +294,7 @@ public int getGroups(QueryHandler<NotionGroupModel> handler, OperationOptions op
params.put(offsetKey, String.valueOf(start));
params.put(countKey, String.valueOf(pageSize));

try (Response response = get(groupEndpoint, params)) {
try (Response response = callSearch(GROUP_OBJECT_CLASS, groupEndpoint, params)) {
GroupListBody list = MAPPER.readValue(response.body().byteStream(), GroupListBody.class);
for (NotionGroupModel group : list.resources) {
if (!handler.handle(group)) {
Expand Down
67 changes: 56 additions & 11 deletions src/main/java/jp/openstandia/connector/util/AbstractRESTClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected <T> T callCreate(ObjectClass objectClass, String url, Object target, S
throw new AlreadyExistsException(String.format("%s %s '%s' already exists.", instanceName, objectClass.getObjectClassValue(), name));
}
if (errorHandler.isInvalidRequest(response)) {
throw new InvalidAttributeValueException(String.format("Bad request when creating %s %s '%s': %s", instanceName, objectClass.getObjectClassValue(), name, toBody(response)));
throw new InvalidAttributeValueException(String.format("Bad request in create operation %s %s '%s': %s", instanceName, objectClass.getObjectClassValue(), name, toBody(response)));
}

if (!this.errorHandler.isOk(response)) {
Expand All @@ -121,7 +121,7 @@ protected void callPatch(ObjectClass objectClass, String url, Uid uid, Object ta
}

if (this.errorHandler.isInvalidRequest(response)) {
throw new InvalidAttributeValueException(String.format("Bad request when updating %s %s: %s, response: %s",
throw new InvalidAttributeValueException(String.format("Bad request in update operation %s %s: %s, response: %s",
this.instanceName, objectClass.getObjectClassValue(), uid.getUidValue(), toBody(response)));
}

Expand All @@ -145,7 +145,7 @@ protected void callUpdate(ObjectClass objectClass, String url, Uid uid, Object t
}

if (this.errorHandler.isInvalidRequest(response)) {
throw new InvalidAttributeValueException(String.format("Bad request when updating %s %s: %s, response: %s",
throw new InvalidAttributeValueException(String.format("Bad request in replace operation %s %s: %s, response: %s",
this.instanceName, objectClass.getObjectClassValue(), uid.getUidValue(), toBody(response)));
}

Expand Down Expand Up @@ -192,7 +192,7 @@ protected void callDelete(ObjectClass objectClass, String url, Uid uid, Object b
}

if (this.errorHandler.isInvalidRequest(response)) {
throw new InvalidAttributeValueException(String.format("Bad request when deleting %s %s: %s, response: %s",
throw new InvalidAttributeValueException(String.format("Bad request in delete operation %s %s: %s, response: %s",
this.instanceName, objectClass.getObjectClassValue(), uid.getUidValue(), toBody(response)));
}

Expand All @@ -209,6 +209,55 @@ protected void callDelete(ObjectClass objectClass, String url, Uid uid, Object b
}
}

protected Response callRead(ObjectClass objectClass, String url, Uid uid) {
try {
Response response = get(url + "/" + uid.getUidValue());
if (this.errorHandler.isNotFound(response)) {
// Don't return UnknownUidException in the Search (executeQuery) operations
return null;
}

if (this.errorHandler.isInvalidRequest(response)) {
throw new InvalidAttributeValueException(String.format("Bad request in read operation for %s %s: %s, response: %s",
this.instanceName, objectClass.getObjectClassValue(), uid.getUidValue(), toBody(response)));
}

if (!this.errorHandler.isOk(response)) {
throw new ConnectorIOException(String.format("Failed to read %s %s: %s, statusCode: %d, response: %s",
this.instanceName, objectClass.getObjectClassValue(), uid.getUidValue(), response.code(), toBody(response)));
}

// Success
return response;

} catch (IOException e) {
throw new ConnectorIOException(String.format("Failed to read %s %s: %s",
this.instanceName, objectClass.getObjectClassValue(), uid.getUidValue()), e);
}
}

protected Response callSearch(ObjectClass objectClass, String url, Map<String, String> params) {
try {
Response response = get(url, params);
if (this.errorHandler.isInvalidRequest(response)) {
throw new InvalidAttributeValueException(String.format("Bad request in search operation for %s %s: %s, response: %s",
this.instanceName, objectClass.getObjectClassValue(), params, toBody(response)));
}

if (!this.errorHandler.isOk(response)) {
throw new ConnectorIOException(String.format("Failed to search %s %s: %s, statusCode: %d, response: %s",
this.instanceName, objectClass.getObjectClassValue(), params, response.code(), toBody(response)));
}

// Success
return response;

} catch (IOException e) {
throw new ConnectorIOException(String.format("Failed to search %s %s: %s",
this.instanceName, objectClass.getObjectClassValue(), params), e);
}
}

private RequestBody createJsonRequestBody(Object body) {
String bodyString;
try {
Expand Down Expand Up @@ -238,11 +287,11 @@ private void throwExceptionIfServerError(Response response) throws ConnectorIOEx
}
}

protected Response get(String url) throws ConnectorIOException {
protected Response get(String url) throws IOException {
return get(url, null);
}

protected Response get(String url, Map<String, String> params) throws ConnectorIOException {
protected Response get(String url, Map<String, String> params) throws IOException {
HttpUrl.Builder httpBuilder = HttpUrl.parse(url).newBuilder();

if (params != null) {
Expand All @@ -255,11 +304,7 @@ protected Response get(String url, Map<String, String> params) throws ConnectorI
.build();

final Response response;
try {
response = httpClient.newCall(request).execute();
} catch (IOException e) {
throw new ConnectorIOException(this.instanceName + " server error", e);
}
response = httpClient.newCall(request).execute();

throwExceptionIfUnauthorized(response);
throwExceptionIfServerError(response);
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/jp/openstandia/connector/notion/UserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,28 @@ void getUserByUidWithEmpty() {
assertNull(result.getAttributeByName("name.givenName"));
}

@Test
void getUserByUidWithNotFound() {
ConnectorFacade connector = newFacade(configuration);

// Given
String userId = "12345";
String userName = "foo";

AtomicReference<Uid> targetUid = new AtomicReference<>();
mockClient.getUserByUid = ((u) -> {
targetUid.set(u);
return null;
});

// When
ConnectorObject result = connector.getObject(USER_OBJECT_CLASS, new Uid(userId, new Name(userName)), defaultGetOperation());

// Then
assertNull(result);
assertNotNull(targetUid.get());
}

@Test
void getUserByName() {
// Given
Expand Down

0 comments on commit bfa57a2

Please sign in to comment.