Skip to content

Commit

Permalink
error propagation for API calls
Browse files Browse the repository at this point in the history
  • Loading branch information
harshdeeppruthi committed Jul 3, 2024
1 parent ab865c5 commit 2ca4aba
Show file tree
Hide file tree
Showing 23 changed files with 357 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void validateTable(String tableName, SourceValueType valueType, FailureCo
// Get the response JSON and fetch the header X-Total-Count. Set the value to recordCount
requestBuilder.setResponseHeaders(ServiceNowConstants.HEADER_NAME_TOTAL_COUNT);

apiResponse = serviceNowTableAPIClient.executeGet(requestBuilder.build());
apiResponse = serviceNowTableAPIClient.executeGetWithRetries(requestBuilder.build());
if (serviceNowTableAPIClient.parseResponseToResultListOfMap(apiResponse.getResponseBody()).isEmpty()) {
// Removed config property as in case of MultiSource, only first table error was populating.
collector.addFailure("Table: " + tableName + " is empty.", "");
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.cdap.plugin.servicenow.apiclient;

import org.apache.http.HttpResponse;

import javax.annotation.Nullable;

/**
* Custom Exception class for propagating API errors/exceptions back to caller.
*/
public class ServiceNowAPIException extends Exception {

@Nullable private final HttpResponse httpResponse;
private final boolean isErrorRetryable;

public ServiceNowAPIException(
Throwable t, @Nullable HttpResponse httpResponse, boolean isErrorRetryable) {
super(t);
this.httpResponse = httpResponse;
this.isErrorRetryable = isErrorRetryable;
}

public ServiceNowAPIException(
String message, @Nullable HttpResponse httpResponse, boolean isErrorRetryable) {
super(message);
this.httpResponse = httpResponse;
this.isErrorRetryable = isErrorRetryable;
}

public HttpResponse getHttpResponse() {
return httpResponse;
}

public boolean isErrorRetryable() {
return isErrorRetryable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
Expand Down Expand Up @@ -109,8 +110,14 @@ public String getAccessTokenRetryableMode() throws ExecutionException, RetryExce
* @param limit The number of records to be fetched
* @return The list of Map; each Map representing a table row
*/
public List<Map<String, String>> fetchTableRecords(String tableName, SourceValueType valueType, String startDate,
String endDate, int offset, int limit) throws IOException {
public List<Map<String, String>> fetchTableRecords(
String tableName,
SourceValueType valueType,
String startDate,
String endDate,
int offset,
int limit)
throws IOException, ServiceNowAPIException {
ServiceNowTableAPIRequestBuilder requestBuilder = new ServiceNowTableAPIRequestBuilder(
this.conf.getRestApiEndpoint(), tableName, false)
.setExcludeReferenceLink(true)
Expand All @@ -126,10 +133,10 @@ public List<Map<String, String>> fetchTableRecords(String tableName, SourceValue
try {
String accessToken = getAccessToken();
requestBuilder.setAuthHeader(accessToken);
RestAPIResponse apiResponse = executeGet(requestBuilder.build());
RestAPIResponse apiResponse = executeGetWithRetries(requestBuilder.build());
return parseResponseToResultListOfMap(apiResponse.getResponseBody());
} catch (OAuthSystemException e) {
throw new RetryableException("Authentication error occurred", e);
throw new ServiceNowAPIException(e, null, true);
} catch (OAuthProblemException e) {
throw new IOException("Problem occurred while authenticating", e);
}
Expand Down Expand Up @@ -219,8 +226,11 @@ public List<Map<String, String>> fetchTableRecordsRetryableMode(String tableName
return true;
};

Predicate<Throwable> retryableServiceNowExceptionPredicate = t -> (t instanceof ServiceNowAPIException
&& ((ServiceNowAPIException) t).isErrorRetryable());

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
.retryIfExceptionOfType(RetryableException.class)
.retryIfException(retryableServiceNowExceptionPredicate::test)
.withWaitStrategy(WaitStrategies.exponentialWait(ServiceNowConstants.WAIT_TIME, TimeUnit.MILLISECONDS))
.withStopStrategy(StopStrategies.stopAfterAttempt(ServiceNowConstants.MAX_NUMBER_OF_RETRY_ATTEMPTS))
.build();
Expand Down Expand Up @@ -266,7 +276,7 @@ public SchemaResponse parseSchemaResponse(String responseBody) {
* @throws OAuthSystemException
*/
public Schema fetchTableSchema(String tableName)
throws OAuthProblemException, OAuthSystemException, IOException {
throws OAuthProblemException, OAuthSystemException, IOException, ServiceNowAPIException {
return fetchTableSchema(tableName, getAccessToken());
}

Expand All @@ -277,14 +287,15 @@ public Schema fetchTableSchema(String tableName)
* @param accessToken Access Token to use
* @return schema for given ServiceNow table
*/
public Schema fetchTableSchema(String tableName, String accessToken) throws IOException {
public Schema fetchTableSchema(String tableName, String accessToken)
throws IOException, ServiceNowAPIException {
ServiceNowTableAPIRequestBuilder requestBuilder = new ServiceNowTableAPIRequestBuilder(
this.conf.getRestApiEndpoint(), tableName, true)
.setExcludeReferenceLink(true);

RestAPIResponse apiResponse;
requestBuilder.setAuthHeader(accessToken);
apiResponse = executeGet(requestBuilder.build());
apiResponse = executeGetWithRetries(requestBuilder.build());
SchemaResponse response = parseSchemaResponse(apiResponse.getResponseBody());
List<ServiceNowColumn> columns = new ArrayList<>();

Expand All @@ -306,7 +317,7 @@ public Schema fetchTableSchema(String tableName, String accessToken) throws IOEx
* @throws OAuthSystemException
*/
public int getTableRecordCount(String tableName)
throws OAuthProblemException, OAuthSystemException, IOException {
throws OAuthProblemException, OAuthSystemException, IOException, ServiceNowAPIException {
return getTableRecordCount(tableName, getAccessToken());
}

Expand All @@ -318,7 +329,7 @@ public int getTableRecordCount(String tableName)
* @return the table record count
* @throws IOException
*/
public int getTableRecordCount(String tableName, String accessToken) throws IOException {
public int getTableRecordCount(String tableName, String accessToken) throws ServiceNowAPIException {
ServiceNowTableAPIRequestBuilder requestBuilder = new ServiceNowTableAPIRequestBuilder(
this.conf.getRestApiEndpoint(), tableName, false)
.setExcludeReferenceLink(true)
Expand All @@ -327,7 +338,7 @@ public int getTableRecordCount(String tableName, String accessToken) throws IOEx
RestAPIResponse apiResponse = null;
requestBuilder.setResponseHeaders(ServiceNowConstants.HEADER_NAME_TOTAL_COUNT);
requestBuilder.setAuthHeader(accessToken);
apiResponse = executeGet(requestBuilder.build());
apiResponse = executeGetWithRetries(requestBuilder.build());
return getRecordCountFromHeader(apiResponse);
}

Expand Down Expand Up @@ -372,7 +383,7 @@ private String getSystemId(RestAPIResponse restAPIResponse) {
* @param query The query
*/
public Map<String, String> getRecordFromServiceNowTable(String tableName, String query)
throws OAuthProblemException, OAuthSystemException, IOException {
throws OAuthProblemException, OAuthSystemException, IOException, ServiceNowAPIException {

ServiceNowTableAPIRequestBuilder requestBuilder = new ServiceNowTableAPIRequestBuilder(
this.conf.getRestApiEndpoint(), tableName, false)
Expand All @@ -381,7 +392,7 @@ public Map<String, String> getRecordFromServiceNowTable(String tableName, String
RestAPIResponse restAPIResponse;
String accessToken = getAccessToken();
requestBuilder.setAuthHeader(accessToken);
restAPIResponse = executeGet(requestBuilder.build());
restAPIResponse = executeGetWithRetries(requestBuilder.build());

APIResponse apiResponse = GSON.fromJson(restAPIResponse.getResponseBody(), APIResponse.class);
return apiResponse.getResult().get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import io.cdap.plugin.common.ConfigUtil;
import io.cdap.plugin.common.Constants;
import io.cdap.plugin.common.ReferenceNames;
import io.cdap.plugin.servicenow.apiclient.ServiceNowAPIException;
import io.cdap.plugin.servicenow.apiclient.ServiceNowTableAPIClientImpl;
import io.cdap.plugin.servicenow.apiclient.ServiceNowTableAPIRequestBuilder;
import io.cdap.plugin.servicenow.restapi.RestAPIResponse;
Expand Down Expand Up @@ -93,7 +94,7 @@ public BrowseDetail browse(ConnectorContext connectorContext, BrowseRequest brow
try {
String accessToken = serviceNowTableAPIClient.getAccessToken();
return browse(connectorContext, accessToken);
} catch (OAuthSystemException | OAuthProblemException e) {
} catch (OAuthSystemException | OAuthProblemException | ServiceNowAPIException e) {
throw new IOException(e);
}
}
Expand All @@ -102,7 +103,7 @@ public BrowseDetail browse(ConnectorContext connectorContext, BrowseRequest brow
* Browse Details for the given AccessToken.
*/
public BrowseDetail browse(ConnectorContext connectorContext,
String accessToken) throws IOException {
String accessToken) throws ServiceNowAPIException {
int count = 0;
FailureCollector collector = connectorContext.getFailureCollector();
config.validateCredentialsFields(collector);
Expand All @@ -125,14 +126,15 @@ public BrowseDetail browse(ConnectorContext connectorContext,
/**
* @return the list of tables.
*/
private TableList listTables(String accessToken) throws IOException {
private TableList listTables(String accessToken) throws ServiceNowAPIException {
ServiceNowTableAPIRequestBuilder requestBuilder = new ServiceNowTableAPIRequestBuilder(
config.getRestApiEndpoint(), OBJECT_TABLE_LIST, false);
requestBuilder.setAuthHeader(accessToken);
requestBuilder.setAcceptHeader(MediaType.APPLICATION_JSON);
requestBuilder.setContentTypeHeader(MediaType.APPLICATION_JSON);
ServiceNowTableAPIClientImpl serviceNowTableAPIClient = new ServiceNowTableAPIClientImpl(config);
RestAPIResponse apiResponse = serviceNowTableAPIClient.executeGet(requestBuilder.build());
RestAPIResponse apiResponse =
serviceNowTableAPIClient.executeGetWithRetries(requestBuilder.build());
return GSON.fromJson(apiResponse.getResponseBody(), TableList.class);
}

Expand Down Expand Up @@ -164,13 +166,13 @@ public List<StructuredRecord> sample(ConnectorContext connectorContext, SampleRe
}
try {
return getTableData(table, sampleRequest.getLimit());
} catch (OAuthProblemException | OAuthSystemException e) {
throw new IOException("Unable to fetch the data.");
} catch (OAuthProblemException | OAuthSystemException | ServiceNowAPIException e) {
throw new IOException("Unable to fetch the data.", e);
}
}

private List<StructuredRecord> getTableData(String tableName, int limit)
throws OAuthProblemException, OAuthSystemException, IOException {
throws OAuthProblemException, OAuthSystemException, ServiceNowAPIException {
ServiceNowTableAPIRequestBuilder requestBuilder = new ServiceNowTableAPIRequestBuilder(
config.getRestApiEndpoint(), tableName, false)
.setExcludeReferenceLink(true)
Expand All @@ -180,7 +182,7 @@ private List<StructuredRecord> getTableData(String tableName, int limit)
String accessToken = serviceNowTableAPIClient.getAccessToken();
requestBuilder.setAuthHeader(accessToken);
requestBuilder.setResponseHeaders(ServiceNowConstants.HEADER_NAME_TOTAL_COUNT);
RestAPIResponse apiResponse = serviceNowTableAPIClient.executeGet(requestBuilder.build());
RestAPIResponse apiResponse = serviceNowTableAPIClient.executeGetWithRetries(requestBuilder.build());
List<Map<String, String>> result = serviceNowTableAPIClient.parseResponseToResultListOfMap
(apiResponse.getResponseBody());
List<StructuredRecord> recordList = new ArrayList<>();
Expand Down
Loading

0 comments on commit 2ca4aba

Please sign in to comment.