From 71154c677556c6ec78e88bf398364f1b6da3a34c Mon Sep 17 00:00:00 2001 From: shafang Date: Wed, 13 May 2020 15:31:28 -0700 Subject: [PATCH 01/10] added AAD support --- .../azure-ai-formrecognizer/CHANGELOG.md | 2 +- .../azure-ai-formrecognizer/README.md | 73 ++++++++++++++----- .../azure-ai-formrecognizer/pom.xml | 6 ++ .../FormRecognizerClientBuilder.java | 23 +++++- .../ai/formrecognizer/ReadmeSamples.java | 14 ++++ .../formrecognizer/AadAuthenticationTest.java | 65 +++++++++++++++++ .../FormRecognizerClientBuilderUnitTest.java | 16 +++- .../aadAuthenticationTest.json | 24 ++++++ 8 files changed, 202 insertions(+), 21 deletions(-) create mode 100644 sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java create mode 100644 sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md b/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md index ab7df47266ef..f54edca783ed 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md @@ -1,7 +1,7 @@ # Release History ## 1.0.0-beta.3 (Unreleased) - +- Added AAD authentication support ## 1.0.0-beta.2 (2020-05-06) - Fixed Receipt type bug to select the valueString field via fieldValue. diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/README.md index f64bb4085578..ed81492cc8ca 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/README.md @@ -58,23 +58,25 @@ az cognitiveservices account create \ --yes ``` ### Authenticate the client -In order to interact with the Form Recognizer service, you will need to create an instance of the `FormRecognizerClient` -class. You will need an **endpoint** and an **key** to instantiate a client object, +In order to interact with the Form Recognizer service, you will need to create an instance of the Form Recognizer client, +both the asynchronous and synchronous clients can be created by using `FormRecognizerClientBuilder` invoking `buildClient()` +creates a synchronous client while `buildAsyncClient` creates its asynchronous counterpart. + +You will need an **endpoint** and a **key** to instantiate a client object, they can be found in the [Azure Portal][azure_portal] under the "Quickstart" in your created Form Recognizer resource. See the full details regarding [authentication][authentication] of Cognitive Services. -#### Get credentials -The `credential` parameter may be provided as a [`AzureKeyCredential`][azure_key_credential] from [azure-core][azure_core]. - -##### Create FormRecognizerClient with AzureKeyCredential -To use AzureKeyCredential authentication, provide the [key][key] as a string to the [AzureKeyCredential][azure_key_credential]. This can be found in the [Azure Portal][azure_portal] - under the "Quickstart" section or by running the following Azure CLI command: +#### Create a Form Recognizer client using AzureKeyCredential +To use `AzureKeyCredential` authentication, provide the [key][key] as a string to the [AzureKeyCredential][azure_key_credential]. +This key can be found in the [Azure Portal][azure_portal] under the "Quickstart" section in your created Form Recognizer +resource, or by running the following Azure CLI command to get the key from the Form Recognizer resource: ```bash az cognitiveservices account keys list --resource-group --name ``` -Use the API key as the credential parameter to authenticate the client: - + +Use the key as the credential parameter to authenticate the client: + ```java FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() .credential(new AzureKeyCredential("{key}")) @@ -83,7 +85,7 @@ FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() ``` The Azure Form Recognizer client library provides a way to **rotate the existing API key**. - + ```java AzureKeyCredential credential = new AzureKeyCredential("{key}"); FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() @@ -94,6 +96,41 @@ FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() credential.update("{new_key}"); ``` +#### Create a Form Recognizer client using Microsoft identity platform (formerly Azure Active Directory) + +Azure SDK for Java supports an Azure Identity package, making it easy to get credentials from Microsoft identity +platform. First, add the package: + +[//]: # ({x-version-update-start;com.azure:azure-identity;current}) +```xml + + com.azure + azure-identity + 1.0.3 + +``` +[//]: # ({x-version-update-end}) + +All the implemented ways to request a credential can be found under the `com.azure.identity.credential` package. The +sample below shows how to use an Azure Active Directory (AAD) application client secret to authorize with Azure Form +Recognizer. + +##### Authorizing with DefaultAzureCredential + +Authorization is easiest using [DefaultAzureCredential][wiki_identity]. It finds the best credential to use in its +running environment. For more information about using Azure Active Directory authorization with Form Recognizer, please +refer to [the associated documentation][aad_authorization]. + + +```java +TokenCredential credential = new DefaultAzureCredentialBuilder() + .build(); +FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() + .endpoint("{endpoint}") + .credential(credential) + .buildClient(); +``` + ## Key concepts ### FormRecognizerClient The [FormRecognizerClient][form_recognizer_sync_client] and [FormRecognizerAsyncClient][form_recognizer_async_client] @@ -143,7 +180,7 @@ The following section provides several code snippets covering some of the most c ### Recognize Forms Using a Custom Model Recognize name/value pairs and table data from forms. These models are trained with your own data, so they're tailored to your forms. You should only recognize forms of the same form type that the custom model was trained on. - + ```java String analyzeFilePath = "{file_source_url}"; String modelId = "{custom_trained_model_id}"; @@ -166,7 +203,7 @@ recognizedForms.forEach(form -> { ### Recognize Content Recognize text and table structures, along with their bounding box coordinates, from documents. - + ```java String analyzeFilePath = "{file_source_url}"; SyncPoller> recognizeLayoutPoller = @@ -193,7 +230,7 @@ layoutPageResults.forEach(formPage -> { ### Recognize receipts Recognize data from a USA sales receipts using a prebuilt model. - + ```java String receiptSourceUrl = "https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/media" + "/contoso-allinone.jpg"; @@ -219,7 +256,7 @@ receiptPageResults.forEach(recognizedReceipt -> { Train a machine-learned model on your own form type. The resulting model will be able to recognize values from the types of forms it was trained on. Provide a container SAS url to your Azure Storage Blob container where you're storing the training documents. See details on setting this up in the [service quickstart documentation][quickstart_training]. - + ```java String trainingSetSource = "{unlabeled_training_set_SAS_URL}"; SyncPoller trainingPoller = @@ -246,7 +283,7 @@ customFormModel.getSubModels().forEach(customFormSubModel -> { ### Manage your models Manage the custom models attached to your account. - + ```java AtomicReference modelId = new AtomicReference<>(); // First, we see how many custom models we have, and what our limit is @@ -288,7 +325,7 @@ to provide an invalid file source URL an `ErrorResponseException` would be raise In the following code snippet, the error is handled gracefully by catching the exception and display the additional information about the error. - + ```java try { formRecognizerClient.beginRecognizeContentFromUrl("invalidSourceUrl"); @@ -336,6 +373,7 @@ When you submit a pull request, a CLA-bot will automatically determine whether y This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For more information see the [Code of Conduct FAQ][coc_faq] or contact [opencode@microsoft.com][coc_contact] with any additional questions or comments. +[aad_authorization]: https://docs.microsoft.com/en-us/azure/cognitive-services/authentication#authenticate-with-azure-active-directory [azure_key_credential]: https://github.com/Azure/azure-sdk-for-java/blob/master/sdk/core/azure-core/src/main/java/com/azure/core/credential/AzureKeyCredential.java [key]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account?tabs=multiservice%2Cwindows#get-the-keys-for-your-resource [api_reference_doc]: https://aka.ms/azsdk-java-formrecognizer-ref-docs @@ -385,5 +423,6 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m [service_doc_train_labeled]: https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/overview#train-with-labels [source_code]: src [quickstart_training]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/quickstarts/curl-train-extract#train-a-form-recognizer-model +[wiki_identity]: https://github.com/Azure/azure-sdk-for-java/wiki/Identity-and-Authentication ![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-java%2Fsdk%2Fformrecognizer%2Fazure-ai-formrecognizer%2FREADME.png) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/pom.xml b/sdk/formrecognizer/azure-ai-formrecognizer/pom.xml index 17ea0e2bafbd..d133f79d1783 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/pom.xml +++ b/sdk/formrecognizer/azure-ai-formrecognizer/pom.xml @@ -75,5 +75,11 @@ 5.4.2 test + + com.azure + azure-identity + 1.0.6 + test + diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java index 5200eb9e3bd0..cd726056a9cd 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java @@ -7,6 +7,7 @@ import com.azure.ai.formrecognizer.implementation.FormRecognizerClientImplBuilder; import com.azure.core.annotation.ServiceClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; import com.azure.core.http.ContentType; import com.azure.core.http.HttpClient; import com.azure.core.http.HttpHeaders; @@ -15,6 +16,7 @@ import com.azure.core.http.policy.AddDatePolicy; import com.azure.core.http.policy.AddHeadersPolicy; import com.azure.core.http.policy.AzureKeyCredentialPolicy; +import com.azure.core.http.policy.BearerTokenAuthenticationPolicy; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.http.policy.HttpLoggingPolicy; @@ -43,7 +45,7 @@ * *

* The client needs the service endpoint of the Azure Form Recognizer to access the resource service. - * {@link #credential(AzureKeyCredential)} gives + * {@link #credential(AzureKeyCredential)} or {@link #credential(TokenCredential) credential(TokenCredential)} gives * the builder access credential. *

* @@ -68,6 +70,7 @@ public final class FormRecognizerClientBuilder { private static final String NAME = "name"; private static final String VERSION = "version"; private static final RetryPolicy DEFAULT_RETRY_POLICY = new RetryPolicy("retry-after-ms", ChronoUnit.MILLIS); + private static final String DEFAULT_SCOPE = "https://cognitiveservices.azure.com/.default"; private final ClientLogger logger = new ClientLogger(FormRecognizerClientBuilder.class); private final List policies; @@ -82,6 +85,7 @@ public final class FormRecognizerClientBuilder { private HttpPipeline httpPipeline; private Configuration configuration; private RetryPolicy retryPolicy; + private TokenCredential tokenCredential; private FormRecognizerServiceVersion version; static final String OCP_APIM_SUBSCRIPTION_KEY = "Ocp-Apim-Subscription-Key"; @@ -173,7 +177,9 @@ private HttpPipeline getDefaultHttpPipeline(Configuration buildConfiguration) { policies.add(retryPolicy == null ? DEFAULT_RETRY_POLICY : retryPolicy); policies.add(new AddDatePolicy()); // Authentications - if (credential != null) { + if (tokenCredential != null) { + policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, DEFAULT_SCOPE)); + } else if (credential != null) { policies.add(new AzureKeyCredentialPolicy(OCP_APIM_SUBSCRIPTION_KEY, credential)); } else { // Throw exception that credential and tokenCredential cannot be null @@ -232,6 +238,19 @@ public FormRecognizerClientBuilder credential(AzureKeyCredential apiKeyCredentia return this; } + /** + * Sets the {@link TokenCredential} used to authenticate HTTP requests. + * + * @param tokenCredential {@link TokenCredential} used to authenticate HTTP requests. + * @return The updated {@link FormRecognizerClientBuilder} object. + * @throws NullPointerException If {@code tokenCredential} is {@code null}. + */ + public FormRecognizerClientBuilder credential(TokenCredential tokenCredential) { + Objects.requireNonNull(tokenCredential, "'tokenCredential' cannot be null."); + this.tokenCredential = tokenCredential; + return this; + } + /** * Sets the logging configuration for HTTP requests and responses. * diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java index 74e21002bbf4..9cd5baecd587 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java @@ -13,9 +13,11 @@ import com.azure.ai.formrecognizer.models.RecognizedReceipt; import com.azure.ai.formrecognizer.models.USReceipt; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; import com.azure.core.http.rest.PagedIterable; import com.azure.core.util.IterableStream; import com.azure.core.util.polling.SyncPoller; +import com.azure.identity.DefaultAzureCredentialBuilder; import java.util.concurrent.atomic.AtomicReference; @@ -40,6 +42,18 @@ public void useAzureKeyCredentialSyncClient() { .buildClient(); } + /** + * Code snippet for getting async client using AAD authentication. + */ + public void useAadAsyncClient() { + TokenCredential credential = new DefaultAzureCredentialBuilder() + .build(); + FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() + .endpoint("{endpoint}") + .credential(credential) + .buildClient(); + } + /** * Code snippet for rotating AzureKeyCredential of the client */ diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java new file mode 100644 index 000000000000..aa43cbc26317 --- /dev/null +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.formrecognizer; + +import com.azure.ai.formrecognizer.models.CustomFormModelInfo; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.http.HttpClient; +import com.azure.core.test.TestBase; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.AZURE_FORM_RECOGNIZER_API_KEY; +import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.AZURE_FORM_RECOGNIZER_ENDPOINT; +import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test for using Azure Active Directory token credential. + */ +public class AadAuthenticationTest extends TestBase { + private static FormTrainingClient client; + + private void setup(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { + final String endpoint = getEndpoint(); + if (interceptorManager.isPlaybackMode()) { + // In playback mode use connection string because CI environment doesn't set up to support AAD + client = new FormRecognizerClientBuilder() + .credential(new AzureKeyCredential(getApiKey())) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .buildClient().getFormTrainingClient(); + } else { + client = new FormRecognizerClientBuilder() + .httpClient(httpClient) + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint) + .addPolicy(interceptorManager.getRecordPolicy()) // Record + .serviceVersion(serviceVersion) + .buildClient().getFormTrainingClient(); + } + } + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") + public void aadAuthenticationTest(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { + setup(httpClient, serviceVersion); + for (CustomFormModelInfo modelInfo : client.getModelInfos()) { + assertTrue(modelInfo.getModelId() != null && modelInfo.getCreatedOn() != null + && modelInfo.getLastUpdatedOn() != null && modelInfo.getStatus() != null); + } + } + + private String getApiKey() { + return interceptorManager.isPlaybackMode() ? "apiKeyInPlayback" + : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_API_KEY); + } + + private String getEndpoint() { + return interceptorManager.isPlaybackMode() ? "https://localhost:8080" + : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_ENDPOINT); + } +} diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilderUnitTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilderUnitTest.java index b6e41332f82f..c1cd3971515e 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilderUnitTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilderUnitTest.java @@ -4,6 +4,7 @@ package com.azure.ai.formrecognizer; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; import org.junit.jupiter.api.Test; import static com.azure.ai.formrecognizer.TestUtils.VALID_HTTPS_LOCALHOST; @@ -52,9 +53,22 @@ public void invalidProtocol() { */ @Test public void nullAzureKeyCredential() { + AzureKeyCredential azureKeyCredential = null; assertThrows(NullPointerException.class, () -> { final FormRecognizerClientBuilder builder = new FormRecognizerClientBuilder(); - builder.endpoint(VALID_HTTPS_LOCALHOST).credential(null); + builder.endpoint(VALID_HTTPS_LOCALHOST).credential(azureKeyCredential); + }); + } + + /** + * Test for null AAD credential + */ + @Test + public void nullAADCredential() { + TokenCredential tokenCredential = null; + assertThrows(NullPointerException.class, () -> { + final FormRecognizerClientBuilder builder = new FormRecognizerClientBuilder(); + builder.endpoint(VALID_HTTPS_LOCALHOST).credential(tokenCredential); }); } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json new file mode 100644 index 000000000000..d436a7a02fc3 --- /dev/null +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json @@ -0,0 +1,24 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models?op=full", + "Headers" : { + "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.4; Windows 10 10.0)", + "x-ms-client-request-id" : "ef2ef0bf-ef69-4daa-acd3-cc035a5d1726" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-envoy-upstream-service-time" : "177", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-content-type-options" : "nosniff", + "apim-request-id" : "8e597a63-c9cd-40f1-a466-f1bf81246050", + "retry-after" : "0", + "StatusCode" : "200", + "Body" : "{\"modelList\":[{\"modelId\":\"117464da-390b-47b6-9d38-93e1d76e7636\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T20:51:26Z\",\"lastUpdatedDateTime\":\"2020-05-13T20:51:26Z\"},{\"modelId\":\"1d61a182-955b-4ebc-b5ec-235bc14adb19\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T20:51:54Z\",\"lastUpdatedDateTime\":\"2020-05-13T20:51:54Z\"},{\"modelId\":\"67bd8405-2c52-4514-9a2d-fe573561a240\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T18:07:38Z\",\"lastUpdatedDateTime\":\"2020-05-13T18:07:44Z\"},{\"modelId\":\"90dfe0d0-a397-496c-869b-9dbca9bb7300\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T18:01:18Z\",\"lastUpdatedDateTime\":\"2020-05-13T18:01:19Z\"},{\"modelId\":\"af4cb9e1-216f-4b2f-b1d4-809cd2b582c2\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T18:00:47Z\",\"lastUpdatedDateTime\":\"2020-05-13T18:00:48Z\"}],\"nextLink\":\"\"}", + "Date" : "Wed, 13 May 2020 21:06:08 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file From 1f744ab1d7517382cac245f936d8ad4a9c0c1cb8 Mon Sep 17 00:00:00 2001 From: shafang Date: Thu, 28 May 2020 21:44:22 -0700 Subject: [PATCH 02/10] address feedbacks --- .../azure-ai-formrecognizer/CHANGELOG.md | 2 +- .../azure-ai-formrecognizer/README.md | 81 ++++++++++--------- .../FormRecognizerClientBuilder.java | 5 +- .../training/FormTrainingClientBuilder.java | 14 ++++ .../ai/formrecognizer/ReadmeSamples.java | 3 +- .../formrecognizer/AadAuthenticationTest.java | 65 --------------- .../FormRecognizerAsyncClientTest.java | 10 +-- .../FormRecognizerClientTest.java | 11 +-- .../FormRecognizerClientTestBase.java | 23 ++++++ .../FormTrainingAsyncClientTest.java | 17 +--- .../FormTrainingClientBuilderUnitTest.java | 16 +++- .../FormTrainingClientTest.java | 17 +--- .../FormTrainingClientTestBase.java | 24 ++++++ sdk/formrecognizer/test-resources.json | 40 +++++++-- 14 files changed, 164 insertions(+), 164 deletions(-) delete mode 100644 sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md b/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md index 40cc70fae342..3e10c63be5d3 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md @@ -9,7 +9,7 @@ - Rename parameter `useLabelFile` to `useTrainingLabels` on `beginTraining` method in FormTrainingClients - Replace parameters `filePrefix` and `includeSubFolders` with `TrainModelOptions` model - Rename AccountProperties `count` and `limit` to `customModelCount` and `customModelLimit` -- Added AAD authentication support +- Added support for AAD Authentication. ## 1.0.0-beta.2 (2020-05-06) - Fixed Receipt type bug to select the valueString field via fieldValue. diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/README.md index 4ec04c319085..260fc8061739 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/README.md @@ -58,33 +58,39 @@ az cognitiveservices account create \ --yes ``` ### Authenticate the client -In order to interact with the Form Recognizer service, you will need to create an instance of the Form Recognizer client, -both the asynchronous and synchronous clients can be created by using `FormRecognizerClientBuilder` invoking `buildClient()` -creates a synchronous client while `buildAsyncClient` creates its asynchronous counterpart. +In order to interact with the Form Recognizer service, you will need to create an instance of the Form Recognizer client. +Both the asynchronous and synchronous clients can be created by using `FormRecognizerClientBuilder`. Invoking `buildClient()` +will create the synchronous client, while invoking `buildAsyncClient` will create its asynchronous counterpart. -You will need an **endpoint** and a **key** to instantiate a client object, -they can be found in the [Azure Portal][azure_portal] under the "Quickstart" in your created -Form Recognizer resource. See the full details regarding [authentication][authentication] of Cognitive Services. +You will need an **endpoint** and a **key** to instantiate a client object. + +##### Looking up the endpoint +You can find the **endpoint** for your Form Recognizer resource in the [Azure Portal][azure_portal] under the "Keys and Endpoint", +or [Azure CLI][azure_cli_endpoint]. +```bash +# Get the endpoint for the resource +az cognitiveservices account show --name "resource-name" --resource-group "resource-group-name" --query "endpoint" +``` #### Create a Form Recognizer client using AzureKeyCredential To use `AzureKeyCredential` authentication, provide the [key][key] as a string to the [AzureKeyCredential][azure_key_credential]. -This key can be found in the [Azure Portal][azure_portal] under the "Quickstart" section in your created Form Recognizer +This key can be found in the [Azure Portal][azure_portal] under the "Keys and Endpoint" section in your created Form Recognizer resource, or by running the following Azure CLI command to get the key from the Form Recognizer resource: ```bash az cognitiveservices account keys list --resource-group --name ``` Use the API key as the credential parameter to authenticate the client: - + ```java FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() .credential(new AzureKeyCredential("{key}")) .endpoint("{endpoint}") .buildClient(); ``` -The Azure Form Recognizer client library provides a way to **rotate the existing API key**. +The Azure Form Recognizer client library provides a way to **rotate the existing key**. - + ```java AzureKeyCredential credential = new AzureKeyCredential("{key}"); FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() @@ -95,35 +101,37 @@ FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() credential.update("{new_key}"); ``` -#### Create a Form Recognizer client using Microsoft identity platform (formerly Azure Active Directory) - +#### Create a Form Recognizer client with Azure Active Directory credential Azure SDK for Java supports an Azure Identity package, making it easy to get credentials from Microsoft identity -platform. First, add the package: +platform. -[//]: # ({x-version-update-start;com.azure:azure-identity;current}) +Authentication with AAD requires some initial setup: +* Add the Azure Identity package + +[//]: # ({x-version-update-start;com.azure:azure-identity;dependency}) ```xml com.azure azure-identity - 1.0.3 + 1.0.6 ``` [//]: # ({x-version-update-end}) +* [Register a new Azure Active Directory application][register_AAD_application] +* [Grant access][grant_access] to Form Recognizer by assigning the `"Cognitive Services User"` role to your service principal. -All the implemented ways to request a credential can be found under the `com.azure.identity.credential` package. The -sample below shows how to use an Azure Active Directory (AAD) application client secret to authorize with Azure Form -Recognizer. - -##### Authorizing with DefaultAzureCredential +After setup, you can choose which type of [credential][azure_identity_credential_type] from azure.identity to use. +As an example, [DefaultAzureCredential][wiki_identity] can be used to authenticate the client: +Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: +AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET. Authorization is easiest using [DefaultAzureCredential][wiki_identity]. It finds the best credential to use in its running environment. For more information about using Azure Active Directory authorization with Form Recognizer, please refer to [the associated documentation][aad_authorization]. - + ```java -TokenCredential credential = new DefaultAzureCredentialBuilder() - .build(); +TokenCredential credential = new DefaultAzureCredentialBuilder().build(); FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() .endpoint("{endpoint}") .credential(credential) @@ -175,11 +183,10 @@ The following section provides several code snippets covering some of the most c * [Train a Model](#train-a-model "Train a model") * [Manage Your Models](#manage-your-models "Manage Your Models") - ### Recognize Forms Using a Custom Model Recognize name/value pairs and table data from forms. These models are trained with your own data, so they're tailored to your forms. You should only recognize forms of the same form type that the custom model was trained on. - + ```java String analyzeFilePath = "{file_source_url}"; String modelId = "{custom_trained_model_id}"; @@ -202,7 +209,7 @@ recognizedForms.forEach(form -> { ### Recognize Content Recognize text and table structures, along with their bounding box coordinates, from documents. - + ```java String analyzeFilePath = "{file_source_url}"; SyncPoller> recognizeLayoutPoller = @@ -229,7 +236,7 @@ layoutPageResults.forEach(formPage -> { ### Recognize receipts Recognize data from a USA sales receipts using a prebuilt model. - + ```java String receiptSourceUrl = "https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/media" + "/contoso-allinone.jpg"; @@ -255,7 +262,7 @@ receiptPageResults.forEach(recognizedReceipt -> { Train a machine-learned model on your own form type. The resulting model will be able to recognize values from the types of forms it was trained on. Provide a container SAS url to your Azure Storage Blob container where you're storing the training documents. See details on setting this up in the [service quickstart documentation][quickstart_training]. - + ```java String trainingFilesUrl = "{training_set_SAS_URL}"; SyncPoller trainingPoller = @@ -282,7 +289,7 @@ customFormModel.getSubModels().forEach(customFormSubModel -> { ### Manage your models Manage the custom models attached to your account. - + ```java AtomicReference modelId = new AtomicReference<>(); // First, we see how many custom models we have, and what our limit is @@ -324,7 +331,7 @@ to provide an invalid file source URL an `ErrorResponseException` would be raise In the following code snippet, the error is handled gracefully by catching the exception and display the additional information about the error. - + ```java try { formRecognizerClient.beginRecognizeContentFromUrl("invalidSourceUrl"); @@ -372,7 +379,7 @@ When you submit a pull request, a CLA-bot will automatically determine whether y This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For more information see the [Code of Conduct FAQ][coc_faq] or contact [opencode@microsoft.com][coc_contact] with any additional questions or comments. -[aad_authorization]: https://docs.microsoft.com/en-us/azure/cognitive-services/authentication#authenticate-with-azure-active-directory +[aad_authorization]: https://docs.microsoft.com/azure/cognitive-services/authentication#authenticate-with-azure-active-directory [azure_key_credential]: https://github.com/Azure/azure-sdk-for-java/blob/master/sdk/core/azure-core/src/main/java/com/azure/core/credential/AzureKeyCredential.java [key]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account?tabs=multiservice%2Cwindows#get-the-keys-for-your-resource [api_reference_doc]: https://aka.ms/azsdk-java-formrecognizer-ref-docs @@ -393,10 +400,11 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m [form_recognizer_sync_client]: src/main/java/com/azure/ai/formrecognizer/FormRecognizerClient.java [form_training_async_client]: src/main/java/com/azure/ai/formrecognizer/training/FormTrainingAsyncClient.java [form_training_sync_client]: src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClient.java +[grant_access]: https://docs.microsoft.com/azure/cognitive-services/authentication#assign-a-role-to-a-service-principal [http_clients_wiki]: https://github.com/Azure/azure-sdk-for-java/wiki/HTTP-clients -[fr_labeling_tool]: https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/quickstarts/label-tool -[fr_train_without_labels]: https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/overview#train-without-labels -[fr_train_with_labels]: https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/overview#train-with-labels +[fr_labeling_tool]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/quickstarts/label-tool +[fr_train_without_labels]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/overview#train-without-labels +[fr_train_with_labels]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/overview#train-with-labels [error_response_exception]: src/main/java/com/azure/ai/formrecognizer/models/ErrorResponseException.java [logging]: https://github.com/Azure/azure-sdk-for-java/wiki/Logging-with-Azure-SDK [package]: https://mvnrepository.com/artifact/com.azure/azure-ai-formrecognizer @@ -413,13 +421,14 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m [recognize_receipts_from_url_async]: src/samples/java/com/azure/ai/formrecognizer/RecognizeReceiptsFromUrlAsync.java [recognize_custom_forms]: src/samples/java/com/azure/ai/formrecognizer/RecognizeCustomForms.java [recognize_custom_forms_async]: src/samples/java/com/azure/ai/formrecognizer/RecognizeCustomFormsAsync.java +[register_AAD_application]: https://docs.microsoft.com/azure/cognitive-services/authentication#assign-a-role-to-a-service-principal [train_unlabeled_model]: src/samples/java/com/azure/ai/formrecognizer/TrainModelWithoutLabels.java [train_unlabeled_model_async]: src/samples/java/com/azure/ai/formrecognizer/TrainModelWithoutLabelsAsync.java [train_labeled_model]: src/samples/java/com/azure/ai/formrecognizer/TrainModelWithLabels.java [train_labeled_model_async]: src/samples/java/com/azure/ai/formrecognizer/TrainModelWithLabelsAsync.java [service_access]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account?tabs=multiservice%2Cwindows -[service_doc_train_unlabeled]: https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/overview#train-without-labels -[service_doc_train_labeled]: https://docs.microsoft.com/en-us/azure/cognitive-services/form-recognizer/overview#train-with-labels +[service_doc_train_unlabeled]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/overview#train-without-labels +[service_doc_train_labeled]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/overview#train-with-labels [source_code]: src [quickstart_training]: https://docs.microsoft.com/azure/cognitive-services/form-recognizer/quickstarts/curl-train-extract#train-a-form-recognizer-model [wiki_identity]: https://github.com/Azure/azure-sdk-for-java/wiki/Identity-and-Authentication diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java index e48c537fe59d..dfb1abd11284 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/FormRecognizerClientBuilder.java @@ -253,11 +253,10 @@ public FormRecognizerClientBuilder credential(AzureKeyCredential apiKeyCredentia * * @param tokenCredential {@link TokenCredential} used to authenticate HTTP requests. * @return The updated {@link FormRecognizerClientBuilder} object. - * @throws NullPointerException If {@code tokenCredential} is {@code null}. + * @throws NullPointerException If {@code tokenCredential} is null. */ public FormRecognizerClientBuilder credential(TokenCredential tokenCredential) { - Objects.requireNonNull(tokenCredential, "'tokenCredential' cannot be null."); - this.tokenCredential = tokenCredential; + this.tokenCredential = Objects.requireNonNull(tokenCredential, "'tokenCredential' cannot be null."); return this; } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java index 293705dec09c..5a031b3ad108 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java @@ -8,6 +8,7 @@ import com.azure.ai.formrecognizer.implementation.FormRecognizerClientImplBuilder; import com.azure.core.annotation.ServiceClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; import com.azure.core.http.ContentType; import com.azure.core.http.HttpClient; import com.azure.core.http.HttpHeaders; @@ -91,6 +92,7 @@ public final class FormTrainingClientBuilder { private HttpPipeline httpPipeline; private Configuration configuration; private RetryPolicy retryPolicy; + private TokenCredential tokenCredential; private FormRecognizerServiceVersion version; static final String OCP_APIM_SUBSCRIPTION_KEY = "Ocp-Apim-Subscription-Key"; @@ -242,6 +244,18 @@ public FormTrainingClientBuilder credential(AzureKeyCredential apiKeyCredential) return this; } + /** + * Sets the {@link TokenCredential} used to authenticate HTTP requests. + * + * @param tokenCredential {@link TokenCredential} used to authenticate HTTP requests. + * @return The updated {@link FormTrainingClientBuilder} object. + * @throws NullPointerException If {@code tokenCredential} is null. + */ + public FormTrainingClientBuilder credential(TokenCredential tokenCredential) { + this.tokenCredential = Objects.requireNonNull(tokenCredential, "'tokenCredential' cannot be null."); + return this; + } + /** * Sets the logging configuration for HTTP requests and responses. * diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java index 978e373abc34..c25728aba659 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/ReadmeSamples.java @@ -48,8 +48,7 @@ public void useAzureKeyCredentialSyncClient() { * Code snippet for getting async client using AAD authentication. */ public void useAadAsyncClient() { - TokenCredential credential = new DefaultAzureCredentialBuilder() - .build(); + TokenCredential credential = new DefaultAzureCredentialBuilder().build(); FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() .endpoint("{endpoint}") .credential(credential) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java deleted file mode 100644 index aa43cbc26317..000000000000 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/AadAuthenticationTest.java +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.formrecognizer; - -import com.azure.ai.formrecognizer.models.CustomFormModelInfo; -import com.azure.core.credential.AzureKeyCredential; -import com.azure.core.http.HttpClient; -import com.azure.core.test.TestBase; -import com.azure.core.util.Configuration; -import com.azure.identity.DefaultAzureCredentialBuilder; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.AZURE_FORM_RECOGNIZER_API_KEY; -import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.AZURE_FORM_RECOGNIZER_ENDPOINT; -import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/** - * Test for using Azure Active Directory token credential. - */ -public class AadAuthenticationTest extends TestBase { - private static FormTrainingClient client; - - private void setup(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - final String endpoint = getEndpoint(); - if (interceptorManager.isPlaybackMode()) { - // In playback mode use connection string because CI environment doesn't set up to support AAD - client = new FormRecognizerClientBuilder() - .credential(new AzureKeyCredential(getApiKey())) - .endpoint(endpoint) - .httpClient(interceptorManager.getPlaybackClient()) - .buildClient().getFormTrainingClient(); - } else { - client = new FormRecognizerClientBuilder() - .httpClient(httpClient) - .credential(new DefaultAzureCredentialBuilder().build()) - .endpoint(endpoint) - .addPolicy(interceptorManager.getRecordPolicy()) // Record - .serviceVersion(serviceVersion) - .buildClient().getFormTrainingClient(); - } - } - - @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) - @MethodSource("com.azure.ai.formrecognizer.TestUtils#getTestParameters") - public void aadAuthenticationTest(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - setup(httpClient, serviceVersion); - for (CustomFormModelInfo modelInfo : client.getModelInfos()) { - assertTrue(modelInfo.getModelId() != null && modelInfo.getCreatedOn() != null - && modelInfo.getLastUpdatedOn() != null && modelInfo.getStatus() != null); - } - } - - private String getApiKey() { - return interceptorManager.isPlaybackMode() ? "apiKeyInPlayback" - : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_API_KEY); - } - - private String getEndpoint() { - return interceptorManager.isPlaybackMode() ? "https://localhost:8080" - : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_ENDPOINT); - } -} diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java index 1ae44d58823c..a7273c059b51 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java @@ -59,15 +59,7 @@ static void afterAll() { private FormRecognizerAsyncClient getFormRecognizerAsyncClient(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - FormRecognizerClientBuilder builder = new FormRecognizerClientBuilder() - .endpoint(getEndpoint()).httpClient(httpClient == null - ? interceptorManager.getPlaybackClient() : httpClient) - .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) - .serviceVersion(serviceVersion).addPolicy(interceptorManager.getRecordPolicy()); - AzureKeyCredential credential = (getTestMode() == TestMode.PLAYBACK) ? new AzureKeyCredential(INVALID_KEY) - : new AzureKeyCredential(getApiKey()); - builder.credential(credential); - return builder.buildAsyncClient(); + return getFormRecognizerClientBuilder(httpClient, serviceVersion).buildAsyncClient(); } private FormTrainingAsyncClient getFormTrainingAsyncClient(HttpClient httpClient, diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java index fcf29535db72..aad842b86749 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java @@ -43,16 +43,7 @@ public class FormRecognizerClientTest extends FormRecognizerClientTestBase { private FormRecognizerClient getFormRecognizerClient(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - FormRecognizerClientBuilder builder = new FormRecognizerClientBuilder() - .endpoint(getEndpoint()) - .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) - .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) - .serviceVersion(serviceVersion) - .addPolicy(interceptorManager.getRecordPolicy()); - AzureKeyCredential credential = (getTestMode() == TestMode.PLAYBACK) - ? new AzureKeyCredential(INVALID_KEY) : new AzureKeyCredential(getApiKey()); - builder.credential(credential); - return builder.buildClient(); + return getFormRecognizerClientBuilder(httpClient, serviceVersion).buildClient(); } private FormTrainingClient getFormTrainingClient(HttpClient httpClient, diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java index f0f52ce668d0..cd9c63ef80e0 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java @@ -31,12 +31,17 @@ import com.azure.ai.formrecognizer.models.TextContentType; import com.azure.ai.formrecognizer.models.USReceipt; import com.azure.ai.formrecognizer.models.USReceiptItem; +import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.test.TestBase; +import com.azure.core.test.TestMode; import com.azure.core.test.models.NetworkCallRecord; import com.azure.core.util.Configuration; import com.azure.core.util.IterableStream; import com.azure.core.util.serializer.SerializerAdapter; +import com.azure.identity.DefaultAzureCredentialBuilder; import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; @@ -55,6 +60,7 @@ import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.FORM_RECOGNIZER_TRAINING_BLOB_CONTAINER_SAS_URL; import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.deserializeRawResponse; import static com.azure.ai.formrecognizer.TestUtils.FORM_JPG; +import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.getFileData; import static com.azure.ai.formrecognizer.TestUtils.getSerializerAdapter; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -70,6 +76,23 @@ public abstract class FormRecognizerClientTestBase extends TestBase { private static final String EXPECTED_MULTIPAGE_PHONE_NUMBER_VALUE = "+15555555555"; private static final String ITEMIZED_RECEIPT_VALUE = "Itemized"; + FormRecognizerClientBuilder getFormRecognizerClientBuilder(HttpClient httpClient, + FormRecognizerServiceVersion serviceVersion) { + FormRecognizerClientBuilder builder = new FormRecognizerClientBuilder() + .endpoint(getEndpoint()) + .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .serviceVersion(serviceVersion) + .addPolicy(interceptorManager.getRecordPolicy()); + + if (getTestMode() == TestMode.PLAYBACK) { + builder.credential(new AzureKeyCredential(INVALID_KEY)); + } else { + builder.credential(new DefaultAzureCredentialBuilder().build()); + } + return builder; + } + private static void validateReferenceElementsData(List expectedElements, IterableStream actualFormContents, List readResults) { if (expectedElements != null && actualFormContents != null) { diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java index 89295e8684ef..864f63d40a99 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java @@ -6,12 +6,7 @@ import com.azure.ai.formrecognizer.models.CustomFormModel; import com.azure.ai.formrecognizer.models.OperationResult; import com.azure.ai.formrecognizer.training.FormTrainingAsyncClient; -import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; -import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLogOptions; -import com.azure.core.test.TestMode; import com.azure.core.util.polling.SyncPoller; import io.netty.handler.codec.http.HttpResponseStatus; import org.junit.jupiter.api.AfterAll; @@ -23,7 +18,6 @@ import java.time.Duration; import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; -import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.INVALID_MODEL_ID; import static com.azure.ai.formrecognizer.TestUtils.INVALID_MODEL_ID_ERROR; import static com.azure.ai.formrecognizer.TestUtils.NULL_SOURCE_URL_ERROR; @@ -48,16 +42,7 @@ static void afterAll() { private FormTrainingAsyncClient getFormTrainingAsyncClient(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - FormTrainingClientBuilder builder = new FormTrainingClientBuilder() - .endpoint(getEndpoint()) - .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) - .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) - .serviceVersion(serviceVersion) - .addPolicy(interceptorManager.getRecordPolicy()); - AzureKeyCredential credential = (getTestMode() == TestMode.PLAYBACK) - ? new AzureKeyCredential(INVALID_KEY) : new AzureKeyCredential(getApiKey()); - builder.credential(credential); - return builder.buildAsyncClient(); + return getFormTrainingClientBuilder(httpClient, serviceVersion).buildAsyncClient(); } /** diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientBuilderUnitTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientBuilderUnitTest.java index 725b9c3a3a27..9fc64545dbe0 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientBuilderUnitTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientBuilderUnitTest.java @@ -5,6 +5,7 @@ import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; import org.junit.jupiter.api.Test; import static com.azure.ai.formrecognizer.TestUtils.VALID_HTTPS_LOCALHOST; @@ -53,9 +54,22 @@ public void invalidProtocol() { */ @Test public void nullAzureKeyCredential() { + AzureKeyCredential credential = null; assertThrows(NullPointerException.class, () -> { final FormTrainingClientBuilder builder = new FormTrainingClientBuilder(); - builder.endpoint(VALID_HTTPS_LOCALHOST).credential(null); + builder.endpoint(VALID_HTTPS_LOCALHOST).credential(credential); + }); + } + + /** + * Test for null AAD credential + */ + @Test + public void nullAADCredential() { + TokenCredential tokenCredential = null; + assertThrows(NullPointerException.class, () -> { + final FormTrainingClientBuilder builder = new FormTrainingClientBuilder(); + builder.endpoint(VALID_HTTPS_LOCALHOST).credential(tokenCredential); }); } diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java index 13a4862457c1..a8d010c9ef67 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java @@ -9,13 +9,8 @@ import com.azure.ai.formrecognizer.models.ErrorResponseException; import com.azure.ai.formrecognizer.models.OperationResult; import com.azure.ai.formrecognizer.training.FormTrainingClient; -import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; -import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.http.rest.Response; -import com.azure.core.test.TestMode; import com.azure.core.util.Context; import com.azure.core.util.polling.SyncPoller; import io.netty.handler.codec.http.HttpResponseStatus; @@ -23,7 +18,6 @@ import org.junit.jupiter.params.provider.MethodSource; import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; -import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.INVALID_MODEL_ID; import static com.azure.ai.formrecognizer.TestUtils.INVALID_MODEL_ID_ERROR; import static com.azure.ai.formrecognizer.TestUtils.NULL_SOURCE_URL_ERROR; @@ -38,16 +32,7 @@ public class FormTrainingClientTest extends FormTrainingClientTestBase { private FormTrainingClient getFormTrainingClient(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - FormTrainingClientBuilder builder = new FormTrainingClientBuilder() - .endpoint(getEndpoint()) - .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) - .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) - .serviceVersion(serviceVersion) - .addPolicy(interceptorManager.getRecordPolicy()); - AzureKeyCredential credential = (getTestMode() == TestMode.PLAYBACK) - ? new AzureKeyCredential(INVALID_KEY) : new AzureKeyCredential(getApiKey()); - builder.credential(credential); - return builder.buildClient(); + return getFormTrainingClientBuilder(httpClient, serviceVersion).buildClient(); } /** diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java index b4784222e945..8d06995c2294 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java @@ -12,12 +12,18 @@ import com.azure.ai.formrecognizer.models.ErrorInformation; import com.azure.ai.formrecognizer.models.FormRecognizerError; import com.azure.ai.formrecognizer.models.TrainingDocumentInfo; +import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; +import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.test.TestBase; +import com.azure.core.test.TestMode; import com.azure.core.test.models.NetworkCallRecord; import com.azure.core.util.Configuration; import com.azure.core.util.serializer.SerializerAdapter; import com.azure.core.util.serializer.SerializerEncoding; +import com.azure.identity.DefaultAzureCredentialBuilder; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -26,6 +32,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.getSerializerAdapter; import static com.azure.ai.formrecognizer.implementation.models.ModelStatus.READY; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -40,6 +47,23 @@ public abstract class FormTrainingClientTestBase extends TestBase { static final String AZURE_FORM_RECOGNIZER_API_KEY = "AZURE_FORM_RECOGNIZER_API_KEY"; static final String AZURE_FORM_RECOGNIZER_ENDPOINT = "AZURE_FORM_RECOGNIZER_ENDPOINT"; + FormTrainingClientBuilder getFormTrainingClientBuilder(HttpClient httpClient, + FormRecognizerServiceVersion serviceVersion) { + FormTrainingClientBuilder builder = new FormTrainingClientBuilder() + .endpoint(getEndpoint()) + .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .serviceVersion(serviceVersion) + .addPolicy(interceptorManager.getRecordPolicy()); + + if (getTestMode() == TestMode.PLAYBACK) { + builder.credential(new AzureKeyCredential(INVALID_KEY)); + } else { + builder.credential(new DefaultAzureCredentialBuilder().build()); + } + return builder; + } + private static void validateTrainingDocumentsData(List expectedTrainingDocuments, List actualTrainingDocuments) { assertEquals(expectedTrainingDocuments.size(), actualTrainingDocuments.size()); diff --git a/sdk/formrecognizer/test-resources.json b/sdk/formrecognizer/test-resources.json index e3dbfa46b0d9..75f39bd568a7 100644 --- a/sdk/formrecognizer/test-resources.json +++ b/sdk/formrecognizer/test-resources.json @@ -3,7 +3,11 @@ "contentVersion": "1.0.0.0", "parameters": { "baseName": { - "type": "String" + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "The base resource name." + } }, "testApplicationOid": { "type": "string", @@ -11,6 +15,24 @@ "description": "The principal to assign the role to. This is application object id." } }, + "tenantId": { + "type": "String", + "metadata": { + "description": "The tenant id to which the application and resources belong." + } + }, + "testApplicationId": { + "type": "String", + "metadata": { + "description": "The application client id used to run tests." + } + }, + "testApplicationSecret": { + "type": "String", + "metadata": { + "description": "The application client secret used to run tests." + } + }, "formRecognizerEndpointSuffix": { "defaultValue": ".cognitiveservices.azure.com/", "type": "String" @@ -98,9 +120,17 @@ } ], "outputs": { - "AZURE_FORM_RECOGNIZER_API_KEY": { - "type": "string", - "value": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('formRecognizerBaseName')), variables('formRecognizerApiVersion')).key1]" + "AZURE_TENANT_ID": { + "type": "String", + "value": "[parameters('tenantId')]" + }, + "AZURE_CLIENT_ID": { + "type": "String", + "value": "[parameters('testApplicationId')]" + }, + "AZURE_CLIENT_SECRET": { + "type": "String", + "value": "[parameters('testApplicationSecret')]" }, "AZURE_FORM_RECOGNIZER_ENDPOINT": { "type": "string", @@ -119,4 +149,4 @@ "value": "[concat(reference(parameters('blobResourceId'), '2019-06-01').primaryEndpoints.blob, parameters('multiPageTestingDataContainer'), '?', listServiceSas(parameters('blobResourceId'), '2019-06-01', parameters('multiPageTestingDataSasProperties')).serviceSasToken)]" } } -} \ No newline at end of file +} From 083b52ddfe5728932073b3301e31b7d51ca07358 Mon Sep 17 00:00:00 2001 From: shafang Date: Fri, 29 May 2020 10:10:54 -0700 Subject: [PATCH 03/10] address iscai feedbacks --- .../azure-ai-formrecognizer/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/README.md index d50b1fe219ad..dbdbe075afef 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/README.md @@ -361,13 +361,13 @@ The following section provides several code snippets illustrating common pattern These code samples show common scenario operations with the Azure Form Recognizer client library. The async versions of the samples show asynchronous operations with Form Recognizer. -* Recognize receipts: [RecognizeReceipts][recognize_receipts], ([async][recognize_receipts_async]) -* Recognize receipts from a URL: [RecognizeReceiptsFromUrl][recognize_receipts_from_url], ([async][recognize_receipts_from_url_async]) -* Recognize content: [RecognizeContent][recognize_content], ([async][recognize_content_async]) -* Recognize custom forms: [RecognizeCustomForms][recognize_custom_forms], ([async][recognize_custom_forms_async]) -* Train a model without labels: [TrainModelWithoutLabels][train_unlabeled_model], ([async][train_unlabeled_model_async]) -* Train a model with labels: [TrainModelWithLabels][train_labeled_model], ([async][train_labeled_model_async]) -* Manage custom models: [ManageCustomModels][manage_custom_models], ([async_version][manage_custom_models_async]) +* Recognize receipts: [RecognizeReceipts][recognize_receipts] ([async][recognize_receipts_async]) +* Recognize receipts from a URL: [RecognizeReceiptsFromUrl][recognize_receipts_from_url] ([async][recognize_receipts_from_url_async]) +* Recognize content: [RecognizeContent][recognize_content] ([async][recognize_content_async]) +* Recognize custom forms: [RecognizeCustomForms][recognize_custom_forms] ([async][recognize_custom_forms_async]) +* Train a model without labels: [TrainModelWithoutLabels][train_unlabeled_model] ([async][train_unlabeled_model_async]) +* Train a model with labels: [TrainModelWithLabels][train_labeled_model] ([async][train_labeled_model_async]) +* Manage custom models: [ManageCustomModels][manage_custom_models] ([async][manage_custom_models_async]) ### Additional documentation @@ -387,7 +387,9 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m [key]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account?tabs=multiservice%2Cwindows#get-the-keys-for-your-resource [api_reference_doc]: https://aka.ms/azsdk-java-formrecognizer-ref-docs [authentication]: https://docs.microsoft.com/azure/cognitive-services/authentication +[azure_identity_credential_type]: https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/identity/azure-identity#credentials [azure_cli]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account-cli?tabs=windows +[azure_cli_endpoint]: https://docs.microsoft.com/cli/azure/cognitiveservices/account?view=azure-cli-latest#az-cognitiveservices-account-show [azure_identity]: https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/identity/azure-identity#credentials [azure_portal]: https://ms.portal.azure.com [azure_subscription]: https://azure.microsoft.com/free From d04924dd41dc2870e8adfd5a74c3499259085753 Mon Sep 17 00:00:00 2001 From: shafang Date: Fri, 29 May 2020 15:04:40 -0700 Subject: [PATCH 04/10] refactor --- .../training/FormTrainingClientBuilder.java | 3 +- .../FormRecognizerAsyncClientTest.java | 16 +--------- .../FormRecognizerClientTest.java | 17 +--------- .../FormRecognizerClientTestBase.java | 31 ++++++++++++------- 4 files changed, 23 insertions(+), 44 deletions(-) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java index 5a031b3ad108..9c886ac6a8fd 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java @@ -44,7 +44,8 @@ * *

* The client needs the service endpoint of the Azure Form Recognizer to access the resource service. - * {@link #credential(AzureKeyCredential)} gives the builder access credential. + * {@link #credential(AzureKeyCredential)} or {@link #credential(TokenCredential) credential(TokenCredential)} gives + * the builder access credential. *

* *

Instantiating an asynchronous Form Training Client

diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java index 9d64a93ceab3..2b35f58f0c88 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerAsyncClientTest.java @@ -11,12 +11,7 @@ import com.azure.ai.formrecognizer.models.RecognizedForm; import com.azure.ai.formrecognizer.models.RecognizedReceipt; import com.azure.ai.formrecognizer.training.FormTrainingAsyncClient; -import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; -import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLogOptions; -import com.azure.core.test.TestMode; import com.azure.core.util.polling.SyncPoller; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -30,7 +25,6 @@ import static com.azure.ai.formrecognizer.TestUtils.CUSTOM_FORM_FILE_LENGTH; import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; import static com.azure.ai.formrecognizer.TestUtils.FORM_LOCAL_URL; -import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.INVALID_SOURCE_URL_ERROR; import static com.azure.ai.formrecognizer.TestUtils.INVALID_URL; import static com.azure.ai.formrecognizer.TestUtils.LAYOUT_FILE_LENGTH; @@ -64,15 +58,7 @@ private FormRecognizerAsyncClient getFormRecognizerAsyncClient(HttpClient httpCl private FormTrainingAsyncClient getFormTrainingAsyncClient(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - FormTrainingClientBuilder builder = new FormTrainingClientBuilder() - .endpoint(getEndpoint()).httpClient(httpClient == null - ? interceptorManager.getPlaybackClient() : httpClient) - .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) - .serviceVersion(serviceVersion).addPolicy(interceptorManager.getRecordPolicy()); - AzureKeyCredential credential = (getTestMode() == TestMode.PLAYBACK) ? new AzureKeyCredential(INVALID_KEY) - : new AzureKeyCredential(getApiKey()); - builder.credential(credential); - return builder.buildAsyncClient(); + return getFormTrainingClientBuilder(httpClient, serviceVersion).buildAsyncClient(); } /** * Verifies receipt data for a document using source as file url. diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java index 9db5317a7cc9..bb6bbdbd27f8 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTest.java @@ -11,12 +11,7 @@ import com.azure.ai.formrecognizer.models.RecognizedForm; import com.azure.ai.formrecognizer.models.RecognizedReceipt; import com.azure.ai.formrecognizer.training.FormTrainingClient; -import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; -import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLogOptions; -import com.azure.core.test.TestMode; import com.azure.core.util.polling.SyncPoller; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -26,7 +21,6 @@ import static com.azure.ai.formrecognizer.TestUtils.CUSTOM_FORM_FILE_LENGTH; import static com.azure.ai.formrecognizer.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; import static com.azure.ai.formrecognizer.TestUtils.FORM_LOCAL_URL; -import static com.azure.ai.formrecognizer.TestUtils.INVALID_KEY; import static com.azure.ai.formrecognizer.TestUtils.INVALID_SOURCE_URL_ERROR; import static com.azure.ai.formrecognizer.TestUtils.INVALID_URL; import static com.azure.ai.formrecognizer.TestUtils.LAYOUT_FILE_LENGTH; @@ -49,16 +43,7 @@ private FormRecognizerClient getFormRecognizerClient(HttpClient httpClient, private FormTrainingClient getFormTrainingClient(HttpClient httpClient, FormRecognizerServiceVersion serviceVersion) { - FormTrainingClientBuilder builder = new FormTrainingClientBuilder() - .endpoint(getEndpoint()) - .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) - .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) - .serviceVersion(serviceVersion) - .addPolicy(interceptorManager.getRecordPolicy()); - AzureKeyCredential credential = (getTestMode() == TestMode.PLAYBACK) - ? new AzureKeyCredential(INVALID_KEY) : new AzureKeyCredential(getApiKey()); - builder.credential(credential); - return builder.buildClient(); + return getFormTrainingClientBuilder(httpClient, serviceVersion).buildClient(); } /** diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java index 6d1c3733c04a..f2676b1224b3 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormRecognizerClientTestBase.java @@ -20,10 +20,10 @@ import com.azure.ai.formrecognizer.models.FormField; import com.azure.ai.formrecognizer.models.FormLine; import com.azure.ai.formrecognizer.models.FormPage; +import com.azure.ai.formrecognizer.models.FormPageRange; import com.azure.ai.formrecognizer.models.FormTable; import com.azure.ai.formrecognizer.models.FormTableCell; import com.azure.ai.formrecognizer.models.FormWord; -import com.azure.ai.formrecognizer.models.FormPageRange; import com.azure.ai.formrecognizer.models.Point; import com.azure.ai.formrecognizer.models.ReceiptItemType; import com.azure.ai.formrecognizer.models.RecognizedForm; @@ -31,6 +31,7 @@ import com.azure.ai.formrecognizer.models.TextContentType; import com.azure.ai.formrecognizer.models.USReceipt; import com.azure.ai.formrecognizer.models.USReceiptItem; +import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; import com.azure.core.credential.AzureKeyCredential; import com.azure.core.http.HttpClient; import com.azure.core.http.policy.HttpLogDetailLevel; @@ -51,7 +52,6 @@ import java.util.function.Consumer; import java.util.regex.Pattern; -import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.AZURE_FORM_RECOGNIZER_API_KEY; import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.AZURE_FORM_RECOGNIZER_ENDPOINT; import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.FORM_RECOGNIZER_TESTING_BLOB_CONTAINER_SAS_URL; import static com.azure.ai.formrecognizer.FormTrainingClientTestBase.FORM_RECOGNIZER_TRAINING_BLOB_CONTAINER_SAS_URL; @@ -90,6 +90,23 @@ FormRecognizerClientBuilder getFormRecognizerClientBuilder(HttpClient httpClient return builder; } + FormTrainingClientBuilder getFormTrainingClientBuilder(HttpClient httpClient, + FormRecognizerServiceVersion serviceVersion) { + FormTrainingClientBuilder builder = new FormTrainingClientBuilder() + .endpoint(getEndpoint()) + .httpClient(httpClient == null ? interceptorManager.getPlaybackClient() : httpClient) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .serviceVersion(serviceVersion) + .addPolicy(interceptorManager.getRecordPolicy()); + + if (getTestMode() == TestMode.PLAYBACK) { + builder.credential(new AzureKeyCredential(INVALID_KEY)); + } else { + builder.credential(new DefaultAzureCredentialBuilder().build()); + } + return builder; + } + private static void validateReferenceElementsData(List expectedElements, List actualFormContentList, List readResults) { if (expectedElements != null && actualFormContentList != null) { @@ -593,16 +610,6 @@ static void validateMultipageReceiptData(List recognizedRecei assertEquals(ITEMIZED_RECEIPT_VALUE, receiptPage3.getReceiptType().getType()); } - /** - * Get the string of API key value based on the test running mode. - * - * @return the API key string - */ - String getApiKey() { - return interceptorManager.isPlaybackMode() ? "apiKeyInPlayback" - : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_API_KEY); - } - protected String getEndpoint() { return interceptorManager.isPlaybackMode() ? "https://localhost:8080" : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_ENDPOINT); From 68d1868b69b82fc727340a155503dc087f7d79b3 Mon Sep 17 00:00:00 2001 From: shafang Date: Fri, 29 May 2020 15:15:39 -0700 Subject: [PATCH 05/10] remove non-used json --- .../aadAuthenticationTest.json | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json deleted file mode 100644 index d436a7a02fc3..000000000000 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/resources/session-records/aadAuthenticationTest.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "networkCallRecords" : [ { - "Method" : "GET", - "Uri" : "https://REDACTED.cognitiveservices.azure.com/formrecognizer/v2.0-preview//custom/models?op=full", - "Headers" : { - "User-Agent" : "azsdk-java-azure-ai-formrecognizer/1.0.0-beta.3 (11.0.4; Windows 10 10.0)", - "x-ms-client-request-id" : "ef2ef0bf-ef69-4daa-acd3-cc035a5d1726" - }, - "Response" : { - "Transfer-Encoding" : "chunked", - "x-envoy-upstream-service-time" : "177", - "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", - "x-content-type-options" : "nosniff", - "apim-request-id" : "8e597a63-c9cd-40f1-a466-f1bf81246050", - "retry-after" : "0", - "StatusCode" : "200", - "Body" : "{\"modelList\":[{\"modelId\":\"117464da-390b-47b6-9d38-93e1d76e7636\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T20:51:26Z\",\"lastUpdatedDateTime\":\"2020-05-13T20:51:26Z\"},{\"modelId\":\"1d61a182-955b-4ebc-b5ec-235bc14adb19\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T20:51:54Z\",\"lastUpdatedDateTime\":\"2020-05-13T20:51:54Z\"},{\"modelId\":\"67bd8405-2c52-4514-9a2d-fe573561a240\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T18:07:38Z\",\"lastUpdatedDateTime\":\"2020-05-13T18:07:44Z\"},{\"modelId\":\"90dfe0d0-a397-496c-869b-9dbca9bb7300\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T18:01:18Z\",\"lastUpdatedDateTime\":\"2020-05-13T18:01:19Z\"},{\"modelId\":\"af4cb9e1-216f-4b2f-b1d4-809cd2b582c2\",\"status\":\"invalid\",\"createdDateTime\":\"2020-05-13T18:00:47Z\",\"lastUpdatedDateTime\":\"2020-05-13T18:00:48Z\"}],\"nextLink\":\"\"}", - "Date" : "Wed, 13 May 2020 21:06:08 GMT", - "Content-Type" : "application/json; charset=utf-8" - }, - "Exception" : null - } ], - "variables" : [ ] -} \ No newline at end of file From bc653df7429ea3172dc5bdf11ae835753ad85b97 Mon Sep 17 00:00:00 2001 From: shafang Date: Mon, 1 Jun 2020 15:44:14 -0700 Subject: [PATCH 06/10] add api key back --- .../ai/formrecognizer/FormTrainingClientTestBase.java | 10 ---------- sdk/formrecognizer/test-resources.json | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java index 581f9e184a55..bd07eedf8979 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java @@ -211,16 +211,6 @@ void beginTrainingUnlabeledRunner(BiConsumer testRunner) { testRunner.accept(getTrainingSasUri(), false); } - /** - * Get the string of API key value based on what running mode is on. - * - * @return the API key string - */ - String getApiKey() { - return interceptorManager.isPlaybackMode() ? "apiKeyInPlayback" - : Configuration.getGlobalConfiguration().get(AZURE_FORM_RECOGNIZER_API_KEY); - } - String getEndpoint() { return interceptorManager.isPlaybackMode() ? "https://localhost:8080" diff --git a/sdk/formrecognizer/test-resources.json b/sdk/formrecognizer/test-resources.json index 75f39bd568a7..f197aa209e58 100644 --- a/sdk/formrecognizer/test-resources.json +++ b/sdk/formrecognizer/test-resources.json @@ -132,6 +132,10 @@ "type": "String", "value": "[parameters('testApplicationSecret')]" }, + "AZURE_FORM_RECOGNIZER_API_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('formRecognizerBaseName')), variables('formRecognizerApiVersion')).key1]" + }, "AZURE_FORM_RECOGNIZER_ENDPOINT": { "type": "string", "value": "[variables('azureFormRecognizerUrl')]" From 1472dbedc2b23b1495c3c8296e7b269dbf8df98a Mon Sep 17 00:00:00 2001 From: shafang Date: Tue, 2 Jun 2020 11:39:19 -0700 Subject: [PATCH 07/10] add aad to training client --- .../training/FormTrainingClientBuilder.java | 10 +- .../ai/formrecognizer/Authentication.java | 130 ++++++++++++++++++ 2 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java index 9c886ac6a8fd..07aac52ec765 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/main/java/com/azure/ai/formrecognizer/training/FormTrainingClientBuilder.java @@ -17,6 +17,7 @@ import com.azure.core.http.policy.AddDatePolicy; import com.azure.core.http.policy.AddHeadersPolicy; import com.azure.core.http.policy.AzureKeyCredentialPolicy; +import com.azure.core.http.policy.BearerTokenAuthenticationPolicy; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.http.policy.HttpLoggingPolicy; @@ -96,7 +97,9 @@ public final class FormTrainingClientBuilder { private TokenCredential tokenCredential; private FormRecognizerServiceVersion version; - static final String OCP_APIM_SUBSCRIPTION_KEY = "Ocp-Apim-Subscription-Key"; + private static final String DEFAULT_SCOPE = "https://cognitiveservices.azure.com/.default"; + private static final String OCP_APIM_SUBSCRIPTION_KEY = "Ocp-Apim-Subscription-Key"; + /** * The constructor with defaults. */ @@ -186,7 +189,10 @@ private HttpPipeline getDefaultHttpPipeline() { policies.add(retryPolicy == null ? DEFAULT_RETRY_POLICY : retryPolicy); policies.add(new AddDatePolicy()); // Authentications - if (credential != null) { + if (tokenCredential != null) { + // User token based policy + policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, DEFAULT_SCOPE)); + } else if (credential != null) { policies.add(new AzureKeyCredentialPolicy(OCP_APIM_SUBSCRIPTION_KEY, credential)); } else { // Throw exception that credential and tokenCredential cannot be null diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java new file mode 100644 index 000000000000..0933836ba147 --- /dev/null +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java @@ -0,0 +1,130 @@ +package com.azure.ai.formrecognizer; + +import com.azure.ai.formrecognizer.models.AccountProperties; +import com.azure.ai.formrecognizer.models.OperationResult; +import com.azure.ai.formrecognizer.models.RecognizedReceipt; +import com.azure.ai.formrecognizer.models.USReceipt; +import com.azure.ai.formrecognizer.training.FormTrainingClient; +import com.azure.ai.formrecognizer.training.FormTrainingClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.util.polling.SyncPoller; +import com.azure.identity.DefaultAzureCredentialBuilder; + +import java.io.IOException; +import java.util.List; + +/** + * Samples for two supported methods of authentication in Form Recognizer and Form Training clients: + * 1) Use a Form Recognizer API key with AzureKeyCredential from azure.core.credentials + * 2) Use a token credential from azure-identity to authenticate with Azure Active Directory + */ +public class Authentication { + /** + * Main method to invoke this demo. + * + * @param args Unused arguments to the program. + * + * @throws IOException Exception thrown when there is an error in reading all the bytes from the File. + */ + public static void main(String[] args) { + /* + Set the environment variables with your own values before running the sample: + + 1) AZURE_FORM_RECOGNIZER_ENDPOINT - the endpoint to your Form Recognizer resource. + 2) AZURE_FORM_RECOGNIZER_KEY - your Form Recognizer API key + 3) AZURE_CLIENT_ID - the client ID of your active directory application. + 4) AZURE_TENANT_ID - the tenant ID of your active directory application. + 5) AZURE_CLIENT_SECRET - the secret of your active directory application. + */ + // Form recognizer client: Key credential + authenticationWithKeyCredentialFormRecognizerClient(); + // Form recognizer client: Azure Active Directory + authenticationWithAzureActiveDirectoryFormRecognizerClient(); + // Form training client: Key credential + authenticationWithKeyCredentialFormTrainingClient(); + // Form training client: Azure Active Directory + authenticationWithAzureActiveDirectoryFormTrainingClient(); + } + + private static void authenticationWithKeyCredentialFormRecognizerClient() { + FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() + .credential(new AzureKeyCredential("{key}")) + .endpoint("{endpoint}") + .buildClient(); + beginRecognizeCustomFormsFromUrl(formRecognizerClient); + } + + private static void authenticationWithAzureActiveDirectoryFormRecognizerClient() { + FormRecognizerClient formRecognizerClient = new FormRecognizerClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint("{endpoint}") + .buildClient(); + beginRecognizeCustomFormsFromUrl(formRecognizerClient); + } + + private static void authenticationWithKeyCredentialFormTrainingClient() { + FormTrainingClient formTrainingClient = new FormTrainingClientBuilder() + .credential(new AzureKeyCredential("{key}")) + .endpoint("{endpoint}") + .buildClient(); + getAccountProperties(formTrainingClient); + } + + private static void authenticationWithAzureActiveDirectoryFormTrainingClient() { + FormTrainingClient formTrainingClient = new FormTrainingClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint("{endpoint}") + .buildClient(); + getAccountProperties(formTrainingClient); + } + + private static void beginRecognizeCustomFormsFromUrl(FormRecognizerClient formRecognizerClient) { + String receiptUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-java/master/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/sample-forms/receipts/contoso-allinone.jpg"; + + SyncPoller> recognizeReceiptPoller = + formRecognizerClient.beginRecognizeReceiptsFromUrl(receiptUrl); + + List receiptPageResults = recognizeReceiptPoller.getFinalResult(); + + for (int i = 0; i < receiptPageResults.size(); i++) { + final RecognizedReceipt recognizedReceipt = receiptPageResults.get(i); + System.out.printf("----------- Recognized Receipt page %s -----------", i); + USReceipt usReceipt = ReceiptExtensions.asUSReceipt(recognizedReceipt); + System.out.printf("Merchant Name: %s, confidence: %.2f%n", usReceipt.getMerchantName().getFieldValue(), + usReceipt.getMerchantName().getConfidence()); + System.out.printf("Merchant Address: %s, confidence: %.2f%n", usReceipt.getMerchantAddress().getName(), + usReceipt.getMerchantAddress().getConfidence()); + System.out.printf("Merchant Phone Number %s, confidence: %.2f%n", + usReceipt.getMerchantPhoneNumber().getFieldValue(), usReceipt.getMerchantPhoneNumber().getConfidence()); + System.out.printf("Total: %s confidence: %.2f%n", usReceipt.getTotal().getName(), + usReceipt.getTotal().getConfidence()); + System.out.printf("Receipt Items: %n"); + usReceipt.getReceiptItems().forEach(receiptItem -> { + if (receiptItem.getName() != null) { + System.out.printf("Name: %s, confidence: %.2f%n", receiptItem.getName().getFieldValue(), + receiptItem.getName().getConfidence()); + } + if (receiptItem.getQuantity() != null) { + System.out.printf("Quantity: %s, confidence: %.2f%n", receiptItem.getQuantity().getFieldValue(), + receiptItem.getQuantity().getConfidence()); + } + if (receiptItem.getPrice() != null) { + System.out.printf("Price: %s, confidence: %.2f%n", receiptItem.getPrice().getFieldValue(), + receiptItem.getPrice().getConfidence()); + } + if (receiptItem.getTotalPrice() != null) { + System.out.printf("Total Price: %s, confidence: %.2f%n", + receiptItem.getTotalPrice().getFieldValue(), receiptItem.getTotalPrice().getConfidence()); + } + }); + System.out.print("-----------------------------------"); + } + } + + private static void getAccountProperties(FormTrainingClient formTrainingClient) { + AccountProperties accountProperties = formTrainingClient.getAccountProperties(); + System.out.printf("Max number of models that can be trained for this account: %s%n", + accountProperties.getCustomModelLimit()); + System.out.printf("Current count of trained custom models: %d%n", accountProperties.getCustomModelCount()); + } +} From e887003429bc34ea2f338146701c6cab239f3f96 Mon Sep 17 00:00:00 2001 From: shafang Date: Tue, 2 Jun 2020 12:06:34 -0700 Subject: [PATCH 08/10] add license title --- .../java/com/azure/ai/formrecognizer/Authentication.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java index 0933836ba147..d3f0438ac452 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/java/com/azure/ai/formrecognizer/Authentication.java @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.ai.formrecognizer; import com.azure.ai.formrecognizer.models.AccountProperties; From 70d6222b9e5fd473f87c1f7dbaf2f07c2872f86b Mon Sep 17 00:00:00 2001 From: shafang Date: Wed, 3 Jun 2020 12:53:15 -0700 Subject: [PATCH 09/10] hide model id --- .../azure/ai/formrecognizer/FormTrainingAsyncClientTest.java | 2 +- .../com/azure/ai/formrecognizer/FormTrainingClientTest.java | 2 +- .../com/azure/ai/formrecognizer/FormTrainingClientTestBase.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java index 8813b5c14032..24ccd9dc68ba 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingAsyncClientTest.java @@ -348,7 +348,7 @@ void beginTrainingInvalidModelStatus(HttpClient httpClient, FormRecognizerServic HttpResponseException httpResponseException = assertThrows(HttpResponseException.class, () -> client.beginTraining(invalidTrainingFilesUrl, useTrainingLabels).getSyncPoller().getFinalResult()); ErrorInformation errorInformation = (ErrorInformation) ((List) httpResponseException.getValue()).get(0); - assertEquals(EXPECTED_INVALID_MODEL_STATUS_MESSAGE, httpResponseException.getMessage()); + assertTrue(httpResponseException.getMessage().contains(EXPECTED_INVALID_MODEL_STATUS_MESSAGE)); assertEquals(EXPECTED_INVALID_MODEL_STATUS_ERROR_CODE, errorInformation.getCode()); assertEquals(EXPECTED_INVALID_STATUS_ERROR_INFORMATION, errorInformation.getMessage()); }); diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java index 0bbbecaa1d08..05e6bba2f5a9 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTest.java @@ -301,7 +301,7 @@ void beginTrainingInvalidModelStatus(HttpClient httpClient, FormRecognizerServic HttpResponseException httpResponseException = assertThrows(HttpResponseException.class, () -> client.beginTraining(invalidTrainingFilesUrl, useTrainingLabels).getFinalResult()); ErrorInformation errorInformation = (ErrorInformation) ((List) httpResponseException.getValue()).get(0); - assertEquals(EXPECTED_INVALID_MODEL_STATUS_MESSAGE, httpResponseException.getMessage()); + assertTrue(httpResponseException.getMessage().contains(EXPECTED_INVALID_MODEL_STATUS_MESSAGE)); assertEquals(EXPECTED_INVALID_MODEL_STATUS_ERROR_CODE, errorInformation.getCode()); assertEquals(EXPECTED_INVALID_STATUS_ERROR_INFORMATION, errorInformation.getMessage()); }); diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java index aa07c277c55c..2807cf4a75c2 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/test/java/com/azure/ai/formrecognizer/FormTrainingClientTestBase.java @@ -48,7 +48,7 @@ public abstract class FormTrainingClientTestBase extends TestBase { "FORM_RECOGNIZER_TESTING_BLOB_CONTAINER_SAS_URL"; static final String AZURE_FORM_RECOGNIZER_API_KEY = "AZURE_FORM_RECOGNIZER_API_KEY"; static final String AZURE_FORM_RECOGNIZER_ENDPOINT = "AZURE_FORM_RECOGNIZER_ENDPOINT"; - static final String EXPECTED_INVALID_MODEL_STATUS_MESSAGE = "Invalid model created with ID: cae9d062-71e0-44a3-8630-70b32ae94f4d"; + static final String EXPECTED_INVALID_MODEL_STATUS_MESSAGE = "Invalid model created with ID"; static final String EXPECTED_INVALID_MODEL_STATUS_ERROR_CODE = "2012"; static final String EXPECTED_INVALID_STATUS_ERROR_INFORMATION = "Unable to list blobs on the Azure blob storage account."; From 3c6a265eb13538f22a19e1473cc33a7d68d22231 Mon Sep 17 00:00:00 2001 From: shafang Date: Wed, 3 Jun 2020 13:00:40 -0700 Subject: [PATCH 10/10] minor feedbacks --- sdk/formrecognizer/azure-ai-formrecognizer/README.md | 4 ++-- .../azure-ai-formrecognizer/src/samples/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/README.md index f097050d603c..77a266eda7db 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/README.md @@ -368,8 +368,8 @@ The async versions of the samples show asynchronous operations with Form Recogni * Recognize custom forms: [RecognizeCustomForms][recognize_custom_forms] ([async][recognize_custom_forms_async]) * Train a model without labels: [TrainModelWithoutLabels][train_unlabeled_model] ([async][train_unlabeled_model_async]) * Train a model with labels: [TrainModelWithLabels][train_labeled_model] ([async][train_labeled_model_async]) -* Manage custom models: [ManageCustomModels][manage_custom_models] ([async_version][manage_custom_models_async]) -* Copy a model between Form Recognizer resources: [CopyModel][copy_model] ([async_version][copy_model_async]) +* Manage custom models: [ManageCustomModels][manage_custom_models] ([async][manage_custom_models_async]) +* Copy a model between Form Recognizer resources: [CopyModel][copy_model] ([async][copy_model_async]) ### Additional documentation diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/README.md index aa9529a6c0d4..5434d9578b8f 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/src/samples/README.md @@ -35,7 +35,7 @@ The following sections provide code samples covering common scenario operations - Manage the custom models in your account - [ManageCustomModels][manage_custom_models] and [ManageCustomModelsAsync][manage_custom_models_async] - Copy custom model between Form Recognizer resources - - [CopyModel](copy_model) and [CopyModelAsync](copy_model_async) + - [CopyModel][copy_model] and [CopyModelAsync][copy_model_async] ## Troubleshooting Troubleshooting steps can be found [here][SDK_README_TROUBLESHOOTING].