Skip to content
This repository was archived by the owner on Aug 29, 2024. It is now read-only.

Commit 8c240ab

Browse files
Exception Handling (#467)
* Added consistent and better exception handling, Added reactive repository integration test. Fixed few API bugs * Updated innerException to CosmosClientException
1 parent 6ea8892 commit 8c240ab

File tree

12 files changed

+567
-284
lines changed

12 files changed

+567
-284
lines changed

src/main/java/com/microsoft/azure/spring/data/cosmosdb/common/CosmosdbUtils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.azure.data.cosmos.CosmosResponseDiagnostics;
1010
import com.azure.data.cosmos.FeedResponse;
1111
import com.azure.data.cosmos.FeedResponseDiagnostics;
12+
import com.azure.data.cosmos.Resource;
1213
import com.fasterxml.jackson.databind.ObjectMapper;
1314
import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnostics;
1415
import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnosticsProcessor;
@@ -34,8 +35,9 @@ public static <T> T getCopyFrom(@NonNull T instance) {
3435
}
3536
}
3637

37-
public static void fillAndProcessResponseDiagnostics(ResponseDiagnosticsProcessor responseDiagnosticsProcessor,
38-
CosmosResponse cosmosResponse, FeedResponse feedResponse) {
38+
public static <T extends Resource> void fillAndProcessResponseDiagnostics(
39+
ResponseDiagnosticsProcessor responseDiagnosticsProcessor,
40+
CosmosResponse<T> cosmosResponse, FeedResponse<T> feedResponse) {
3941
if (responseDiagnosticsProcessor == null) {
4042
return;
4143
}

src/main/java/com/microsoft/azure/spring/data/cosmosdb/core/CosmosTemplate.java

Lines changed: 143 additions & 193 deletions
Large diffs are not rendered by default.

src/main/java/com/microsoft/azure/spring/data/cosmosdb/core/ReactiveCosmosTemplate.java

Lines changed: 105 additions & 85 deletions
Large diffs are not rendered by default.

src/main/java/com/microsoft/azure/spring/data/cosmosdb/exception/CosmosDBAccessException.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,45 @@
55
*/
66
package com.microsoft.azure.spring.data.cosmosdb.exception;
77

8+
import com.azure.data.cosmos.CosmosClientException;
89
import org.springframework.dao.DataAccessException;
910
import org.springframework.lang.Nullable;
1011

12+
/**
13+
* Public class extending DataAccessException, exposes innerException.
14+
* Every API in {@link com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository}
15+
* and {@link com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository}
16+
* should throw {@link CosmosDBAccessException}.
17+
* innerException refers to the exception thrown by CosmosDB SDK. Callers of repository APIs can
18+
* rely on innerException for any retriable logic, or for more details on the failure of
19+
* the operation.
20+
*/
1121
public class CosmosDBAccessException extends DataAccessException {
22+
23+
protected final CosmosClientException cosmosClientException;
24+
1225
public CosmosDBAccessException(String msg) {
1326
super(msg);
27+
this.cosmosClientException = null;
1428
}
1529

1630
public CosmosDBAccessException(@Nullable String msg, @Nullable Throwable cause) {
1731
super(msg, cause);
32+
if (cause instanceof CosmosClientException) {
33+
this.cosmosClientException = (CosmosClientException) cause;
34+
} else {
35+
this.cosmosClientException = null;
36+
}
37+
}
38+
39+
public CosmosDBAccessException(@Nullable String msg, @Nullable Exception cause) {
40+
super(msg, cause);
41+
this.cosmosClientException = cause instanceof CosmosClientException
42+
? (CosmosClientException) cause
43+
: null;
44+
}
45+
46+
public CosmosClientException getCosmosClientException() {
47+
return cosmosClientException;
1848
}
1949
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE in the project root for
4+
* license information.
5+
*/
6+
package com.microsoft.azure.spring.data.cosmosdb.exception;
7+
8+
import com.azure.data.cosmos.CosmosClientException;
9+
import com.azure.data.cosmos.internal.HttpConstants;
10+
import org.springframework.util.StringUtils;
11+
import reactor.core.Exceptions;
12+
import reactor.core.publisher.Mono;
13+
14+
public class CosmosDBExceptionUtils {
15+
16+
public static <T> Mono<T> exceptionHandler(String message, Throwable throwable) {
17+
if (StringUtils.isEmpty(message)) {
18+
message = "Failed to access cosmosdb database";
19+
}
20+
// Unwrap the exception in case if it is a reactive exception
21+
final Throwable unwrappedThrowable = Exceptions.unwrap(throwable);
22+
throw new CosmosDBAccessException(message, unwrappedThrowable);
23+
}
24+
25+
public static <T> Mono<T> findAPIExceptionHandler(String message, Throwable throwable) {
26+
// Unwrap the exception in case if it is a reactive exception
27+
final Throwable unwrappedThrowable = Exceptions.unwrap(throwable);
28+
if (unwrappedThrowable instanceof CosmosClientException) {
29+
final CosmosClientException cosmosClientException = (CosmosClientException) unwrappedThrowable;
30+
if (cosmosClientException.statusCode() == HttpConstants.StatusCodes.NOTFOUND) {
31+
return Mono.empty();
32+
}
33+
}
34+
return exceptionHandler(message, unwrappedThrowable);
35+
}
36+
}

src/test/java/com/microsoft/azure/spring/data/cosmosdb/core/CosmosTemplateIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ public void testOptimisticLockWhenUpdatingWithWrongEtag() {
223223
try {
224224
cosmosTemplate.upsert(Person.class.getSimpleName(), updated, null);
225225
} catch (CosmosDBAccessException e) {
226-
assertThat(e.getCause()).isNotNull();
227-
final Throwable cosmosClientException = e.getCause().getCause();
226+
assertThat(e.getCosmosClientException()).isNotNull();
227+
final Throwable cosmosClientException = e.getCosmosClientException();
228228
assertThat(cosmosClientException).isInstanceOf(CosmosClientException.class);
229229
assertThat(cosmosClientException.getMessage()).contains(PRECONDITION_IS_NOT_MET);
230230

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE in the project root for
4+
* license information.
5+
*/
6+
package com.microsoft.azure.spring.data.cosmosdb.domain;
7+
8+
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
9+
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
10+
import lombok.AllArgsConstructor;
11+
import lombok.Data;
12+
import lombok.Getter;
13+
import lombok.NoArgsConstructor;
14+
import lombok.Setter;
15+
import org.springframework.data.annotation.Id;
16+
17+
@Data
18+
@Document
19+
@AllArgsConstructor
20+
@NoArgsConstructor
21+
@Getter
22+
@Setter
23+
public class Course {
24+
25+
@Id
26+
private String courseId;
27+
private String name;
28+
@PartitionKey
29+
private String department;
30+
}

src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/TestRepositoryConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration;
1212
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
1313
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableCosmosRepositories;
14+
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableReactiveCosmosRepositories;
1415
import org.springframework.beans.factory.annotation.Value;
1516
import org.springframework.context.annotation.Bean;
1617
import org.springframework.context.annotation.Configuration;
@@ -20,6 +21,7 @@
2021
@Configuration
2122
@PropertySource(value = {"classpath:application.properties"})
2223
@EnableCosmosRepositories
24+
@EnableReactiveCosmosRepositories
2325
public class TestRepositoryConfig extends AbstractCosmosConfiguration {
2426
@Value("${cosmosdb.uri:}")
2527
private String cosmosDbUri;

src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/integration/AddressRepositoryIT.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils;
1111
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate;
1212
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
13-
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
1413
import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig;
1514
import com.microsoft.azure.spring.data.cosmosdb.repository.repository.AddressRepository;
1615
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;

src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/integration/ProjectRepositorySortIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public void testFindAllSortMoreThanOneOrderException() {
136136
this.repository.findAll(sort);
137137
}
138138

139-
@Test(expected = CosmosDBAccessException.class)
139+
@Test(expected = IllegalArgumentException.class)
140140
public void testFindAllSortIgnoreCaseException() {
141141
final Sort.Order order = Sort.Order.by("name").ignoreCase();
142142
final Sort sort = Sort.by(order);

0 commit comments

Comments
 (0)