diff --git a/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexAsyncClientImpl.java b/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexAsyncClientImpl.java index 093d63c34bfc6..cee6f75dd48be 100644 --- a/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexAsyncClientImpl.java +++ b/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexAsyncClientImpl.java @@ -3,11 +3,12 @@ package com.azure.search.data.customization; +import com.azure.core.http.HttpClient; import com.azure.core.http.HttpPipelineBuilder; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.http.rest.PagedFlux; import com.azure.search.data.SearchIndexAsyncClient; import com.azure.search.data.common.DocumentResponseConversions; -import com.azure.search.data.common.SearchPipelinePolicy; -import com.azure.core.http.rest.PagedFlux; import com.azure.search.data.generated.SearchIndexRestClient; import com.azure.search.data.generated.implementation.SearchIndexRestClientBuilder; import com.azure.search.data.generated.models.AutocompleteParameters; @@ -47,6 +48,17 @@ public class SearchIndexAsyncClientImpl extends SearchIndexBaseClient implements */ private String indexName; + /** + * The Http Client to be used. + */ + private HttpClient httpClient; + + /** + * The Http Client to be used. + */ + private List policies; + + /** * The underlying REST client to be used to actually interact with the Search service */ @@ -54,13 +66,18 @@ public class SearchIndexAsyncClientImpl extends SearchIndexBaseClient implements /** * Package private constructor to be used by {@link SearchIndexClientBuilder} + * * @param searchServiceName * @param searchDnsSuffix * @param indexName * @param apiVersion - * @param policy + * @param httpClient + * @param policies */ - SearchIndexAsyncClientImpl(String searchServiceName, String searchDnsSuffix, String indexName, String apiVersion, SearchPipelinePolicy policy) { + SearchIndexAsyncClientImpl( + String searchServiceName, String searchDnsSuffix, String indexName, String apiVersion, + HttpClient httpClient, + List policies) { if (StringUtils.isBlank(searchServiceName)) { throw new IllegalArgumentException("Invalid searchServiceName"); } @@ -73,25 +90,32 @@ public class SearchIndexAsyncClientImpl extends SearchIndexBaseClient implements if (StringUtils.isBlank(apiVersion)) { throw new IllegalArgumentException("Invalid apiVersion"); } - if (policy == null) { - throw new IllegalArgumentException("Invalid policy"); + if (httpClient == null) { + throw new IllegalArgumentException("Invalid httpClient"); + } + if (policies == null) { + throw new IllegalArgumentException("Invalid policies"); } this.searchServiceName = searchServiceName; this.searchDnsSuffix = searchDnsSuffix; this.indexName = indexName; this.apiVersion = apiVersion; + this.httpClient = httpClient; + this.policies = policies; - initialize(policy); + initialize(); } - private void initialize(SearchPipelinePolicy policy) { + private void initialize() { restClient = new SearchIndexRestClientBuilder() .searchServiceName(searchServiceName) .indexName(indexName) .searchDnsSuffix(searchDnsSuffix) .apiVersion(apiVersion) - .pipeline(new HttpPipelineBuilder().policies(policy).build()) + .pipeline(new HttpPipelineBuilder() + .httpClient(httpClient) + .policies(policies.toArray(new HttpPipelinePolicy[0])).build()) .build(); } @@ -129,14 +153,15 @@ public Mono countDocuments() { @Override public PagedFlux search() { - return null; //return restClient.documents().searchGetAsync(); + return null; //return restClient.documents().searchPostAsync(); } @Override - public PagedFlux search(String searchText, - SearchParameters searchParameters, - SearchRequestOptions searchRequestOptions) { - return null; //return restClient.documents().searchGetAsync(searchText, searchParameters, searchRequestOptions); + public PagedFlux search( + String searchText, + SearchParameters searchParameters, + SearchRequestOptions searchRequestOptions) { + return null; //return restClient.documents().searchPostAsync(searchText, searchParameters, searchRequestOptions); } @Override @@ -145,8 +170,9 @@ public Mono> getDocument(String key) { } @Override - public Mono> getDocument(String key, List selectedFields, - SearchRequestOptions searchRequestOptions) { + public Mono> getDocument( + String key, List selectedFields, + SearchRequestOptions searchRequestOptions) { return restClient .documents() .getAsync(key, selectedFields, searchRequestOptions) @@ -159,10 +185,11 @@ public PagedFlux suggest(String searchText, String suggesterName) } @Override - public PagedFlux suggest(String searchText, - String suggesterName, - SuggestParameters suggestParameters, - SearchRequestOptions searchRequestOptions) { + public PagedFlux suggest( + String searchText, + String suggesterName, + SuggestParameters suggestParameters, + SearchRequestOptions searchRequestOptions) { return null; } @@ -177,13 +204,15 @@ public Mono autocomplete(String searchText, String suggester } @Override - public Mono autocomplete(String searchText, - String suggesterName, - SearchRequestOptions searchRequestOptions, - AutocompleteParameters autocompleteParameters) { - return restClient.documents().autocompleteGetAsync(searchText, - suggesterName, - searchRequestOptions, - autocompleteParameters); + public Mono autocomplete( + String searchText, + String suggesterName, + SearchRequestOptions searchRequestOptions, + AutocompleteParameters autocompleteParameters) { + return restClient.documents().autocompleteGetAsync( + searchText, + suggesterName, + searchRequestOptions, + autocompleteParameters); } } diff --git a/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexClientBuilder.java b/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexClientBuilder.java index fc6b826d8ffe4..1d15a206a70ed 100644 --- a/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexClientBuilder.java +++ b/search/data-plane/data/src/main/java/com/azure/search/data/customization/SearchIndexClientBuilder.java @@ -3,10 +3,14 @@ package com.azure.search.data.customization; +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.implementation.annotation.ServiceClientBuilder; import com.azure.search.data.SearchIndexAsyncClient; import com.azure.search.data.SearchIndexClient; -import com.azure.search.data.common.SearchPipelinePolicy; + +import java.util.ArrayList; +import java.util.List; /** * Fluent SearchIndexClientBuilder for instantiating a {@link SearchIndexClientImpl} or a {@link SearchIndexAsyncClientImpl} @@ -33,14 +37,17 @@ public class SearchIndexClientBuilder { private String apiVersion; private String serviceName; private String indexName; - private SearchPipelinePolicy policy; private String searchDnsSuffix; + private HttpClient httpClient; + private List policies; /** * Default Constructor */ public SearchIndexClientBuilder() { searchDnsSuffix = "search.windows.net"; + httpClient = HttpClient.createDefault(); + policies = new ArrayList<>(); } /** @@ -77,13 +84,24 @@ public SearchIndexClientBuilder indexName(String indexName) { } /** - * Set the authentication policy (api-key) + * Set the http client (optional). If this is not set, a default httpClient will be created + * + * @param httpClient value of httpClient + * @return the updated SearchIndexClientBuilder object + */ + public SearchIndexClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Http Pipeline policy * - * @param policy value of api-key + * @param policy policy to add to the pipeline * @return the updated SearchIndexClientBuilder object */ - public SearchIndexClientBuilder policy(SearchPipelinePolicy policy) { - this.policy = policy; + public SearchIndexClientBuilder addPolicy(HttpPipelinePolicy policy) { + this.policies.add(policy); return this; } @@ -110,6 +128,6 @@ public SearchIndexClient buildClient() { * @return a {@link SearchIndexAsyncClient} created from the configurations in this builder. */ public SearchIndexAsyncClient buildAsyncClient() { - return new SearchIndexAsyncClientImpl(serviceName, searchDnsSuffix, indexName, apiVersion, policy); + return new SearchIndexAsyncClientImpl(serviceName, searchDnsSuffix, indexName, apiVersion, httpClient, policies); } } diff --git a/search/data-plane/data/src/samples/java/com/azure/search/data/SearchIndexClientExample.java b/search/data-plane/data/src/samples/java/com/azure/search/data/SearchIndexClientExample.java index 43935a7dcb004..65965d4ae131c 100644 --- a/search/data-plane/data/src/samples/java/com/azure/search/data/SearchIndexClientExample.java +++ b/search/data-plane/data/src/samples/java/com/azure/search/data/SearchIndexClientExample.java @@ -22,6 +22,7 @@ public class SearchIndexClientExample { /** * sample + * * @param args arguments */ public static void main(String[] args) { @@ -33,12 +34,12 @@ public static void main(String[] args) { SearchIndexClient searchClient = new SearchIndexClientBuilder() - .serviceName(searchServiceName) - .searchDnsSuffix(dnsSuffix) - .indexName(indexName) - .apiVersion(apiVersion) - .policy(new SearchPipelinePolicy(apiKey)) - .buildClient(); + .serviceName(searchServiceName) + .searchDnsSuffix(dnsSuffix) + .indexName(indexName) + .apiVersion(apiVersion) + .addPolicy(new SearchPipelinePolicy(apiKey)) + .buildClient(); searchForAll(searchClient); @@ -50,7 +51,8 @@ private static void searchForAll(SearchIndexClient searchClient) { for (SearchResult searchResult : result.results()) { Hotel hotel = getDocument(Hotel.class, searchResult.additionalProperties()); - System.out.printf("\t score: %s, id: %s, name: %s\n", + System.out.printf( + "\t score: %s, id: %s, name: %s\n", searchResult.score(), hotel.HotelId, hotel.HotelName); diff --git a/search/data-plane/data/src/test/java/com/azure/search/data/SearchIndexAsyncClientTest.java b/search/data-plane/data/src/test/java/com/azure/search/data/SearchIndexAsyncClientTest.java new file mode 100644 index 0000000000000..1c662e910dc00 --- /dev/null +++ b/search/data-plane/data/src/test/java/com/azure/search/data/SearchIndexAsyncClientTest.java @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.search.data; + +import com.azure.search.data.generated.models.DocumentIndexResult; +import com.azure.search.data.generated.models.IndexAction; +import com.azure.search.data.generated.models.IndexActionType; +import com.azure.search.data.generated.models.IndexBatch; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SearchIndexAsyncClientTest extends SearchIndexClientTestBase { + + private SearchIndexAsyncClient searchIndexAsyncClient; + private static final String HOTELS_DATA_JSON = "HotelsDataArray.json"; + + @Override + protected void beforeTest() { + super.beforeTest(); + searchIndexAsyncClient = builderSetup().buildAsyncClient(); + } + + @Test + public void indexResultSucceeds() throws Exception { + + List hotels = loadHotels(); + + Map hotel = new HashMap(hotels.get(1)); + List indexActions = new ArrayList<>(); + indexActions.add(new IndexAction() + .actionType(IndexActionType.UPLOAD) + .additionalProperties(hotel) + ); + + DocumentIndexResult result = searchIndexAsyncClient.index(new IndexBatch().actions(indexActions)).block(); + + assert result.results().get(0).statusCode() == 200; + + } + + private List loadHotels() throws IOException { + Reader docsData = new InputStreamReader( + getClass().getClassLoader().getResourceAsStream(HOTELS_DATA_JSON)); + List hotels = new ObjectMapper().readValue(docsData, List.class); + assert hotels != null; + + return hotels; + } + + +} diff --git a/search/data-plane/data/src/test/java/com/azure/search/data/SearchIndexClientTestBase.java b/search/data-plane/data/src/test/java/com/azure/search/data/SearchIndexClientTestBase.java new file mode 100644 index 0000000000000..2760aa27dca3c --- /dev/null +++ b/search/data-plane/data/src/test/java/com/azure/search/data/SearchIndexClientTestBase.java @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.search.data; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLoggingPolicy; +import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.test.TestBase; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.search.data.common.SearchPipelinePolicy; +import com.azure.search.data.customization.SearchIndexClientBuilder; +import com.azure.search.data.env.AzureSearchResources; +import com.azure.search.data.env.SearchIndexDocs; +import com.azure.search.data.env.SearchIndexService; +import com.microsoft.azure.AzureEnvironment; +import com.microsoft.azure.credentials.ApplicationTokenCredentials; +import com.microsoft.azure.management.resources.fluentcore.arm.Region; +import org.junit.Rule; +import org.junit.rules.TestName; + + +public class SearchIndexClientTestBase extends TestBase { + + private final ClientLogger logger = new ClientLogger(SearchIndexClientTestBase.class); + + private static final String AZURE_DOMAIN_ID = "AZURE_DOMAIN_ID"; + private static final String AZURE_SUBSCRIPTION_ID = "AZURE_SUBSCRIPTION_ID"; + private static final String AZURE_SERVICE_PRINCIPAL_APP_ID = "AZURE_SERVICE_PRINCIPAL_APP_ID"; + private static final String AZURE_SERVICE_PRINCIPAL_APP_SECRET = "AZURE_SERVICE_PRINCIPAL_APP_SECRET"; + + private static String searchServiceName; + private static String apiKey; + private static String indexName; + + private AzureSearchResources azureSearchResources; + + @Rule + public TestName testName = new TestName(); + + @Override + public String testName() { + return testName.getMethodName(); + } + + SearchIndexClientBuilder builderSetup() { + if (!interceptorManager.isPlaybackMode()) { + createAzureTestEnvironment(); + + return new SearchIndexClientBuilder() + .serviceName(searchServiceName) + .searchDnsSuffix("search.windows.net") + .indexName(indexName) + .apiVersion("2019-05-06") + .httpClient(HttpClient.createDefault().wiretap(true)) + .addPolicy(new SearchPipelinePolicy(apiKey)) + .addPolicy(interceptorManager.getRecordPolicy()) + .addPolicy(new RetryPolicy()) + .addPolicy(new HttpLoggingPolicy(HttpLogDetailLevel.BODY_AND_HEADERS)); + } else { + return new SearchIndexClientBuilder() + .serviceName("searchServiceName") + .searchDnsSuffix("search.windows.net") + .indexName("hotels") + .apiVersion("2019-05-06") + .httpClient(interceptorManager.getPlaybackClient()) + .addPolicy(new SearchPipelinePolicy("apiKey")) + .addPolicy(new HttpLoggingPolicy(HttpLogDetailLevel.BODY_AND_HEADERS)); + } + } + + @Override + protected void afterTest() { + super.afterTest(); + deleteAzureTestEnvironment(); + } + + private void createAzureTestEnvironment() { + String appId = ConfigurationManager.getConfiguration().get(AZURE_SERVICE_PRINCIPAL_APP_ID); + String azureDomainId = ConfigurationManager.getConfiguration().get(AZURE_DOMAIN_ID); + String secret = ConfigurationManager.getConfiguration().get(AZURE_SERVICE_PRINCIPAL_APP_SECRET); + String subscriptionId = ConfigurationManager.getConfiguration().get(AZURE_SUBSCRIPTION_ID); + + ApplicationTokenCredentials applicationTokenCredentials = new ApplicationTokenCredentials( + appId, + azureDomainId, + secret, + AzureEnvironment.AZURE); + + azureSearchResources = new AzureSearchResources( + applicationTokenCredentials, subscriptionId, Region.US_EAST); + azureSearchResources.initialize(); + + searchServiceName = azureSearchResources.getSearchServiceName(); + apiKey = azureSearchResources.getSearchAdminKey(); + + try { + //Creating Index: + SearchIndexService searchIndexService = new SearchIndexService(searchServiceName, apiKey); + searchIndexService.initialize(); + indexName = searchIndexService.indexName(); + + // Uploading Documents: + SearchIndexDocs searchIndexDocs = new SearchIndexDocs(searchServiceName, apiKey, + indexName, + "search.windows.net", + "2019-05-06"); + searchIndexDocs.initialize(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void deleteAzureTestEnvironment() { + if (azureSearchResources != null) { + azureSearchResources.cleanup(); + } + } +} diff --git a/search/data-plane/data/src/test/java/com/azure/search/data/env/SearchIndexDocs.java b/search/data-plane/data/src/test/java/com/azure/search/data/env/SearchIndexDocs.java index eb4e667eb309b..812649884c975 100644 --- a/search/data-plane/data/src/test/java/com/azure/search/data/env/SearchIndexDocs.java +++ b/search/data-plane/data/src/test/java/com/azure/search/data/env/SearchIndexDocs.java @@ -63,7 +63,7 @@ public void initialize() throws IOException { .searchDnsSuffix(dnsSuffix) .indexName(indexName) .apiVersion(apiVersion) - .policy(new SearchPipelinePolicy(apiAdminKey)) + .addPolicy(new SearchPipelinePolicy(apiAdminKey)) .buildAsyncClient(); } addDocsData(); diff --git a/search/data-plane/data/src/test/java/com/azure/search/data/test/customization/SearchIndexClientBuildersTest.java b/search/data-plane/data/src/test/java/com/azure/search/data/test/customization/SearchIndexClientBuildersTest.java index 0b84beb18b225..303445e9e2017 100644 --- a/search/data-plane/data/src/test/java/com/azure/search/data/test/customization/SearchIndexClientBuildersTest.java +++ b/search/data-plane/data/src/test/java/com/azure/search/data/test/customization/SearchIndexClientBuildersTest.java @@ -31,7 +31,7 @@ private SearchIndexClientImpl buildClient(String searchServiceName, String index SearchPipelinePolicy policy = new SearchPipelinePolicy(apiKey); SearchIndexClientBuilder clientBuilder = new SearchIndexClientBuilder(); - SearchIndexClient client = clientBuilder.serviceName(searchServiceName).indexName(indexName).policy(policy).apiVersion(apiVersion).searchDnsSuffix(dnsSuffix).buildClient(); + SearchIndexClient client = clientBuilder.serviceName(searchServiceName).indexName(indexName).addPolicy(policy).apiVersion(apiVersion).searchDnsSuffix(dnsSuffix).buildClient(); assert (client != null); assert (client.getClass().getSimpleName().equals(SearchIndexClientImpl.class.getSimpleName())); @@ -46,7 +46,7 @@ private SearchIndexAsyncClientImpl buildASyncClient(String searchServiceName, St SearchPipelinePolicy policy = new SearchPipelinePolicy(apiKey); SearchIndexClientBuilder clientBuilder = new SearchIndexClientBuilder(); - SearchIndexAsyncClient client = clientBuilder.serviceName(searchServiceName).indexName(indexName).policy(policy).apiVersion(apiVersion).searchDnsSuffix(dnsSuffix).buildAsyncClient(); + SearchIndexAsyncClient client = clientBuilder.serviceName(searchServiceName).indexName(indexName).addPolicy(policy).apiVersion(apiVersion).searchDnsSuffix(dnsSuffix).buildAsyncClient(); assert (client != null); assert (client.getClass().getSimpleName().equals(SearchIndexAsyncClientImpl.class.getSimpleName())); @@ -318,7 +318,7 @@ public void verifyDefaultDnsSuffixIsCorrectTest() throws Exception { SearchIndexClientBuilder clientBuilder = new SearchIndexClientBuilder(); SearchIndexAsyncClient client = - clientBuilder.serviceName(searchServiceName).indexName(indexName).policy(policy).apiVersion(apiVersion).buildAsyncClient(); + clientBuilder.serviceName(searchServiceName).indexName(indexName).addPolicy(policy).apiVersion(apiVersion).buildAsyncClient(); assert (client != null); assert (client.getSearchDnsSuffix() == "search.windows.net"); diff --git a/search/data-plane/data/src/test/resources/session-records/indexResultSucceeds.json b/search/data-plane/data/src/test/resources/session-records/indexResultSucceeds.json new file mode 100644 index 0000000000000..742fe24b5ae9b --- /dev/null +++ b/search/data-plane/data/src/test/resources/session-records/indexResultSucceeds.json @@ -0,0 +1,26 @@ +{ + "networkCallRecords" : [ { + "Method" : "POST", + "Uri" : "https://azs-sdk42222156e7b7.search.windows.net/indexes('hotels')/docs/search.index?api-version=2019-05-06", + "Headers" : { + "Content-Type" : "application/json; charset=utf-8" + }, + "Response" : { + "Pragma" : "no-cache", + "retry-after" : "0", + "request-id" : "2352bde7-245b-41d0-8f5a-f35a88758686", + "StatusCode" : "200", + "Date" : "Thu, 08 Aug 2019 18:13:40 GMT", + "Strict-Transport-Security" : "max-age=15724800; includeSubDomains", + "Cache-Control" : "no-cache", + "elapsed-time" : "498", + "OData-Version" : "4.0", + "Expires" : "-1", + "Content-Length" : "227", + "Body" : "{\"@odata.context\":\"https://azs-sdk42222156e7b7.search.windows.net/indexes('hotels')/$metadata#Collection(Microsoft.Azure.Search.V2019_05_06.IndexResult)\",\"value\":[{\"key\":\"2\",\"status\":true,\"errorMessage\":null,\"statusCode\":200}]}", + "Preference-Applied" : "odata.include-annotations=\"*\"", + "Content-Type" : "application/json; odata.metadata=minimal" + } + } ], + "variables" : [ ] +}