diff --git a/sdk/batch/azure-compute-batch/README.md b/sdk/batch/azure-compute-batch/README.md
index a133e740d3d6..36e5c41ed2b1 100644
--- a/sdk/batch/azure-compute-batch/README.md
+++ b/sdk/batch/azure-compute-batch/README.md
@@ -159,6 +159,22 @@ BatchTaskCreateContent taskToCreate = new BatchTaskCreateContent(taskId, "echo h
batchClient.createTask(jobId, taskToCreate);
```
+Error handling
+
+When a call to the batch service fails the response from that call will contain a BatchError object in the body of the response. In the AZURE-COMPUTE-BATCH SDK when an api method is called and a failure from the server occurs the sdk will throw a HttpResponseException exception. You can use the helper method BatchError.fromException() to extract out the BatchError object.
+
+```java
+try(
+
+ BatchPool pool = batchClient.getPool("poolthatdoesnotexist");
+
+} catch (HttpResponseException err) {
+
+ BatchError batchError = BatchError.fromException(err);
+ Assertions.assertEquals("PoolNotFound", error.getCode());
+}
+```
+
## Help
If you encounter any bugs with these libraries, please file issues via [Issues](https://github.com/Azure/azure-sdk-for-java) or check out [StackOverflow for Azure Java SDK](https://stackoverflow.com/questions/tagged/azure-java-sdk).
diff --git a/sdk/batch/azure-compute-batch/assets.json b/sdk/batch/azure-compute-batch/assets.json
index 76cb7f078d74..4ae049c54fcd 100644
--- a/sdk/batch/azure-compute-batch/assets.json
+++ b/sdk/batch/azure-compute-batch/assets.json
@@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/batch/azure-compute-batch",
- "Tag": "java/batch/azure-compute-batch_ead064573c"
+ "Tag": "java/batch/azure-compute-batch_36edb7c93c"
}
diff --git a/sdk/batch/azure-compute-batch/pom.xml b/sdk/batch/azure-compute-batch/pom.xml
index 1d8b37b65a72..b1a6a8984df9 100644
--- a/sdk/batch/azure-compute-batch/pom.xml
+++ b/sdk/batch/azure-compute-batch/pom.xml
@@ -96,5 +96,11 @@
12.29.0
test
+
+ org.mockito
+ mockito-core
+ 4.11.0
+ test
+
diff --git a/sdk/batch/azure-compute-batch/src/main/java/com/azure/compute/batch/models/BatchError.java b/sdk/batch/azure-compute-batch/src/main/java/com/azure/compute/batch/models/BatchError.java
index 3a57a89f1f62..4c54630fc0cd 100644
--- a/sdk/batch/azure-compute-batch/src/main/java/com/azure/compute/batch/models/BatchError.java
+++ b/sdk/batch/azure-compute-batch/src/main/java/com/azure/compute/batch/models/BatchError.java
@@ -5,11 +5,15 @@
import com.azure.core.annotation.Generated;
import com.azure.core.annotation.Immutable;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.HttpResponse;
+import com.azure.json.JsonProviders;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
+import java.io.StringReader;
import java.util.List;
/**
@@ -125,4 +129,35 @@ public static BatchError fromJson(JsonReader jsonReader) throws IOException {
return deserializedBatchError;
});
}
+
+ /**
+ * Reads an instance of BatchError from an HttpResponseException.
+ *
+ * @param err The HttpResponseException based exception returned from an api
+ * call.
+ * @return An instance of BatchError if the HttpResponseException containted an
+ * instance of it, or null if it was pointing
+ * to an HttpResponseException with no BatchError.
+ */
+ public static BatchError fromException(HttpResponseException err) {
+ if (err == null) {
+ return null;
+ }
+ HttpResponse response = err.getResponse();
+ if (response == null) {
+ return null;
+ }
+ String bodyastring = response.getBodyAsString().block();
+ if (bodyastring == null) {
+ return null;
+ }
+ JsonReader jsonReader;
+ try {
+ jsonReader = JsonProviders.createReader(new StringReader(bodyastring));
+ return BatchError.fromJson(jsonReader);
+ } catch (IOException e) {
+ // If the body of the response is not a valid json, return null
+ return null;
+ }
+ }
}
diff --git a/sdk/batch/azure-compute-batch/src/test/java/com/azure/compute/batch/BatchErrorTests.java b/sdk/batch/azure-compute-batch/src/test/java/com/azure/compute/batch/BatchErrorTests.java
new file mode 100644
index 000000000000..e6cfedca9b6e
--- /dev/null
+++ b/sdk/batch/azure-compute-batch/src/test/java/com/azure/compute/batch/BatchErrorTests.java
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.compute.batch;
+
+import com.azure.compute.batch.models.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import com.azure.core.exception.HttpResponseException;
+
+public class BatchErrorTests extends BatchClientTestBase {
+
+ @Test
+ public void testResizeErrorCases() {
+ try {
+
+ BatchPoolResizeContent resizeContent = new BatchPoolResizeContent();
+ batchClient.resizePool("fakepool", resizeContent);
+ } catch (HttpResponseException err) {
+
+ BatchError error = BatchError.fromException(err);
+ Assertions.assertNotNull(error);
+ Assertions.assertEquals("MissingRequiredProperty", error.getCode());
+ Assertions.assertTrue(
+ error.getMessage().getValue().contains("A required property was not specified in the request body."));
+ Assertions.assertEquals("targetDedicatedNodes and/or targetLowPriorityNodes",
+ error.getValues().get(0).getValue());
+ }
+
+ try {
+
+ batchClient.resizePool("fakepool",
+ new BatchPoolResizeContent().setTargetDedicatedNodes(1).setTargetLowPriorityNodes(1));
+ } catch (HttpResponseException err) {
+
+ BatchError error = BatchError.fromException(err);
+ Assertions.assertNotNull(error);
+ Assertions.assertEquals("PoolNotFound", error.getCode());
+ Assertions.assertTrue(error.getMessage().getValue().contains("The specified pool does not exist."));
+ Assertions.assertNull(error.getValues());
+ }
+ }
+}
diff --git a/sdk/batch/azure-compute-batch/src/test/java/com/azure/compute/batch/models/BatchErrorUnitTest.java b/sdk/batch/azure-compute-batch/src/test/java/com/azure/compute/batch/models/BatchErrorUnitTest.java
new file mode 100644
index 000000000000..90230ee2318b
--- /dev/null
+++ b/sdk/batch/azure-compute-batch/src/test/java/com/azure/compute/batch/models/BatchErrorUnitTest.java
@@ -0,0 +1,86 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.compute.batch.models;
+
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.HttpResponse;
+import org.junit.jupiter.api.Test;
+import reactor.core.publisher.Mono;
+import java.io.IOException;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+public class BatchErrorUnitTest {
+
+ @Test
+ public void testFromExceptionWithValidJson() throws IOException {
+ // Arrange
+ String json = "{\"code\":\"InvalidRequest\",\"message\":{\"value\":\"Invalid request\"},\"values\":[]}";
+ HttpResponse response = mock(HttpResponse.class);
+ when(response.getBodyAsString()).thenReturn(Mono.just(json));
+ HttpResponseException exception = new HttpResponseException("Error", response);
+
+ // Act
+ BatchError batchError = BatchError.fromException(exception);
+
+ // Assert
+ assertNotNull(batchError);
+ assertEquals("InvalidRequest", batchError.getCode());
+ assertNotNull(batchError.getMessage());
+ assertEquals("Invalid request", batchError.getMessage().getValue());
+ assertTrue(batchError.getValues().isEmpty());
+ }
+
+ @Test
+ public void testFromExceptionWithValidJsonMultiValues() throws IOException {
+ // Arrange
+ String json
+ = "{\"code\":\"InvalidRequest\",\"message\":{\"value\":\"Error message\"},\"values\":[{\"key\": \"key1\",\"value\":\"value1\"},{\"key\": \"key2\",\"value\":\"value2\"}]}";
+ HttpResponse response = mock(HttpResponse.class);
+ when(response.getBodyAsString()).thenReturn(Mono.just(json));
+ HttpResponseException exception = new HttpResponseException("Error", response);
+
+ // Act
+ BatchError batchError = BatchError.fromException(exception);
+
+ // Assert
+ assertNotNull(batchError);
+ assertEquals("InvalidRequest", batchError.getCode());
+ assertNotNull(batchError.getMessage());
+ assertEquals("Error message", batchError.getMessage().getValue());
+ assertNotNull(batchError.getValues());
+ assertEquals("key1", batchError.getValues().get(0).getKey());
+ assertEquals("value1", batchError.getValues().get(0).getValue());
+ assertEquals("key2", batchError.getValues().get(1).getKey());
+ assertEquals("value2", batchError.getValues().get(1).getValue());
+ }
+
+ @Test
+ public void testFromExceptionWithInvalidJson() {
+ // Arrange
+ String invalidJson = "Invalid JSON";
+ HttpResponse response = mock(HttpResponse.class);
+ when(response.getBodyAsString()).thenReturn(Mono.just(invalidJson));
+ HttpResponseException exception = new HttpResponseException("Error", response);
+
+ // Act
+ BatchError batchError = BatchError.fromException(exception);
+
+ // Assert
+ assertNull(batchError);
+ }
+
+ @Test
+ public void testFromExceptionWithNullResponse() {
+ // Arrange
+ HttpResponse response = mock(HttpResponse.class);
+ when(response.getBodyAsString()).thenReturn(Mono.empty());
+ HttpResponseException exception = new HttpResponseException("Error", response);
+
+ // Act
+ BatchError batchError = BatchError.fromException(exception);
+
+ // Assert
+ assertNull(batchError);
+ }
+}