Skip to content

Commit

Permalink
Wrap Tables implementation Exception with a public type. (#20275)
Browse files Browse the repository at this point in the history
* Added TableServiceErrorException and TableServiceError to the public models package.

* Added utility methods to map the implementation exception to the public one.

* Updated all public types to reference the public TableServiceErrorException instead of the one in the implementation package.

* Updated and reformatted Javadoc of clients and batch classes. Reformatted some code as well.

* Updated client builder to throw IllegalArgumentException instead of NullPointerException when given arguments are incorrect or null. Also changed log level of when the httpClient or pipeline are set to null from INFO to WARNING.

* Updated CHANGELOG.

* Fixed implementation exception handling and conversion to public type.

* Updated `nullCredentialThrowsNullPointerException()` test in TablesClientBuilderTest.

* Applied PR feedback.

* Fixed CheckStyle issues.

* Fixed test issues.

* Fixed more CheckStyle issues.

* Fixed SpotBugs issue.

* Applied more PR feedback about handling a null `connectionString` and `endpoint`.
  • Loading branch information
vcolin7 committed Apr 2, 2021
1 parent fb04ed2 commit eb82cb4
Show file tree
Hide file tree
Showing 17 changed files with 1,072 additions and 503 deletions.
4 changes: 4 additions & 0 deletions sdk/tables/azure-data-tables/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 12.0.0-beta.6 (Unreleased)

### Breaking Changes

- All clients and batch classes now throw a public TableServiceErrorException instead of the one in the implementation package.
- `TableClientBuilder` fluent setters now throw an `IllegalArgumentException` instead of `NullPointerException` when given invalid arguments.

## 12.0.0-beta.5 (2021-03-10)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import com.azure.data.tables.implementation.models.BatchRequestBody;
import com.azure.data.tables.implementation.models.BatchSubRequest;
import com.azure.data.tables.implementation.models.TableServiceError;
import com.azure.data.tables.implementation.models.TableServiceErrorException;
import com.azure.data.tables.models.TableEntity;
import com.azure.data.tables.models.TableServiceErrorException;
import com.azure.data.tables.models.UpdateMode;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand All @@ -34,6 +34,7 @@

import static com.azure.core.util.FluxUtil.monoError;
import static com.azure.core.util.FluxUtil.withContext;
import static com.azure.data.tables.implementation.TableUtils.toTableServiceError;

/**
* Provides a batch object for asynchronously executing a transaction containing one or more operations on entities
Expand Down Expand Up @@ -78,30 +79,33 @@ public final class TableAsyncBatch {
* @param entity The entity to insert.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the entity's partition key does not match the partition key provided when
*
* @throws IllegalArgumentException If the entity's partition key does not match the partition key provided when
* creating this {@link TableAsyncBatch} object, if the entity's row key is {@code null} or empty, or if another
* operation with the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch createEntity(TableEntity entity) {
validate(entity);
addOperation(new BatchOperation.CreateEntity(entity));

return this;
}

/**
* Inserts an entity into the table if it does not exist, or merges the entity with the existing entity otherwise.
*
* If no entity exists within the table having the same partition key and row key as the provided entity, it will
* be inserted. Otherwise, the provided entity's properties will be merged into the existing entity.
* If no entity exists within the table having the same partition key and row key as the provided entity, it will be
* inserted. Otherwise, the provided entity's properties will be merged into the existing entity.
*
* @param entity The entity to upsert.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the entity's partition key does not match the partition key provided when
*
* @throws IllegalArgumentException If the entity's partition key does not match the partition key provided when
* creating this {@link TableAsyncBatch} object, if the entity's row key is {@code null} or empty, or if another
* operation with the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch upsertEntity(TableEntity entity) {
return upsertEntity(entity, UpdateMode.MERGE);
Expand All @@ -111,8 +115,8 @@ public TableAsyncBatch upsertEntity(TableEntity entity) {
* Inserts an entity into the table if it does not exist, or updates the existing entity using the specified update
* mode otherwise.
*
* If no entity exists within the table having the same partition key and row key as the provided entity, it will
* be inserted. Otherwise, the existing entity will be updated according to the specified update mode.
* If no entity exists within the table having the same partition key and row key as the provided entity, it will be
* inserted. Otherwise, the existing entity will be updated according to the specified update mode.
*
* When the update mode is 'MERGE', the provided entity's properties will be merged into the existing entity. When
* the update mode is 'REPLACE', the provided entity's properties will completely replace those in the existing
Expand All @@ -122,14 +126,16 @@ public TableAsyncBatch upsertEntity(TableEntity entity) {
* @param updateMode The type of update to perform if the entity already exits.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the entity's partition key does not match the partition key provided when
*
* @throws IllegalArgumentException If the entity's partition key does not match the partition key provided when
* creating this {@link TableAsyncBatch} object, if the entity's row key is {@code null} or empty, or if another
* operation with the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch upsertEntity(TableEntity entity, UpdateMode updateMode) {
validate(entity);
addOperation(new BatchOperation.UpsertEntity(entity, updateMode));

return this;
}

Expand All @@ -139,10 +145,11 @@ public TableAsyncBatch upsertEntity(TableEntity entity, UpdateMode updateMode) {
* @param entity The entity to update.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the entity's partition key does not match the partition key provided when
*
* @throws IllegalArgumentException If the entity's partition key does not match the partition key provided when
* creating this {@link TableAsyncBatch} object, if the entity's row key is {@code null} or empty, or if another
* operation with the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch updateEntity(TableEntity entity) {
return updateEntity(entity, UpdateMode.MERGE);
Expand All @@ -159,10 +166,11 @@ public TableAsyncBatch updateEntity(TableEntity entity) {
* @param updateMode The type of update to perform.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the entity's partition key does not match the partition key provided when
*
* @throws IllegalArgumentException If the entity's partition key does not match the partition key provided when
* creating this {@link TableAsyncBatch} object, if the entity's row key is {@code null} or empty, or if another
* operation with the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch updateEntity(TableEntity entity, UpdateMode updateMode) {
return updateEntity(entity, updateMode, false);
Expand All @@ -181,14 +189,16 @@ public TableAsyncBatch updateEntity(TableEntity entity, UpdateMode updateMode) {
* service. If the values do not match, the update will not occur and an exception will be thrown.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the entity's partition key does not match the partition key provided when
*
* @throws IllegalArgumentException If the entity's partition key does not match the partition key provided when
* creating this {@link TableAsyncBatch} object, if the entity's row key is {@code null} or empty, or if another
* operation with the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch updateEntity(TableEntity entity, UpdateMode updateMode, boolean ifUnchanged) {
validate(entity);
addOperation(new BatchOperation.UpdateEntity(entity, updateMode, ifUnchanged));

return this;
}

Expand All @@ -198,9 +208,10 @@ public TableAsyncBatch updateEntity(TableEntity entity, UpdateMode updateMode, b
* @param rowKey The row key of the entity.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the provided row key is {@code null} or empty, or if another operation with
*
* @throws IllegalArgumentException If the provided row key is {@code null} or empty, or if another operation with
* the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch deleteEntity(String rowKey) {
return deleteEntity(rowKey, "*");
Expand All @@ -214,13 +225,15 @@ public TableAsyncBatch deleteEntity(String rowKey) {
* the delete will not occur and an exception will be thrown.
*
* @return The updated {@link TableAsyncBatch}.
* @throws IllegalArgumentException if the provided row key is {@code null} or empty, or if another operation with
*
* @throws IllegalArgumentException If the provided row key is {@code null} or empty, or if another operation with
* the same row key has already been added to the batch.
* @throws IllegalStateException if this method is called after the batch has been submitted.
* @throws IllegalStateException If this method is called after the batch has been submitted.
*/
public TableAsyncBatch deleteEntity(String rowKey, String eTag) {
validate(partitionKey, rowKey);
addOperation(new BatchOperation.DeleteEntity(partitionKey, rowKey, eTag));

return this;
}

Expand All @@ -238,9 +251,10 @@ public synchronized List<BatchOperation> getOperations() {
* the batch will succeed, or if a failure occurs, all operations in the batch will be rolled back.
*
* @return A reactive result containing a list of sub-responses for each operation in the batch.
*
* @throws IllegalStateException If no operations have been added to the batch.
* @throws TableServiceErrorException if any operation within the batch fails. See the documentation for the client
* methods in {@link TableAsyncClient} to understand the conditions that may cause a given operation to fail.
* @throws IllegalStateException if no operations have been added to the batch.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public synchronized Mono<List<BatchOperationResponse>> submitTransaction() {
Expand All @@ -253,9 +267,10 @@ public synchronized Mono<List<BatchOperationResponse>> submitTransaction() {
*
* @return A reactive result containing the HTTP response produced for the batch itself. The response's value will
* contain a list of sub-responses for each operation in the batch.
*
* @throws IllegalStateException If no operations have been added to the batch.
* @throws TableServiceErrorException if any operation within the batch fails. See the documentation for the client
* methods in {@link TableAsyncClient} to understand the conditions that may cause a given operation to fail.
* @throws IllegalStateException if no operations have been added to the batch.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public synchronized Mono<Response<List<BatchOperationResponse>>> submitTransactionWithResponse() {
Expand Down Expand Up @@ -310,6 +325,7 @@ private Mono<Response<List<BatchOperationResponse>>> parseResponse(BatchRequestB
&& error.getOdataError().getMessage().getValue() != null) {

String message = error.getOdataError().getMessage().getValue();

try {
int failedIndex = Integer.parseInt(message.substring(0, message.indexOf(":")));
failedOperation = changes.getContents().get(failedIndex).getOperation();
Expand All @@ -332,12 +348,14 @@ private Mono<Response<List<BatchOperationResponse>>> parseResponse(BatchRequestB

if (error != null || errorMessage != null) {
String message = "An operation within the batch failed, the transaction has been rolled back.";

if (failedOperation != null) {
message += " The failed operation was: " + failedOperation.toString();
} else if (errorMessage != null) {
message += " " + errorMessage;
}
return monoError(logger, new TableServiceErrorException(message, null, error));

return monoError(logger, new TableServiceErrorException(message, null, toTableServiceError(error)));
} else {
return Mono.just(new SimpleResponse<>(response, Arrays.asList(response.getValue())));
}
Expand Down

0 comments on commit eb82cb4

Please sign in to comment.