diff --git a/.github/workflows/api-level-lint.yml b/.github/workflows/api-level-lint.yml
index d84787fdd..0761df0a8 100644
--- a/.github/workflows/api-level-lint.yml
+++ b/.github/workflows/api-level-lint.yml
@@ -18,7 +18,7 @@ jobs:
java-version: 21
cache: gradle
- name: Setup Android SDK
- uses: android-actions/setup-android@v3.2.1
+ uses: android-actions/setup-android@v3.2.2
- name: Add execution right to the script
run: chmod +x gradlew
working-directory: ./android
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 466b7195f..395791d45 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.3.1"
+ ".": "3.4.0"
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e2b60af6d..3ba81fb0a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [3.4.0](https://github.com/microsoftgraph/msgraph-sdk-java-core/compare/v3.3.1...v3.4.0) (2024-11-19)
+
+
+### Features
+
+* add GraphClientFactory method using TokenCredential ([b75c471](https://github.com/microsoftgraph/msgraph-sdk-java-core/commit/b75c471d17436712d7e6cc8e32e606af200670e7))
+* Support overriding default interceptors via request options ([667cae6](https://github.com/microsoftgraph/msgraph-sdk-java-core/commit/667cae662ec46e938d73817e79d58e84d97171e6))
+
+
+### Bug Fixes
+
+* issue where custom interceptors would fail to override default interceptors ([adf470a](https://github.com/microsoftgraph/msgraph-sdk-java-core/commit/adf470aa76e12920effbc9d8feee5721ecb68101))
+
## [3.3.1](https://github.com/microsoftgraph/msgraph-sdk-java-core/compare/v3.3.0...v3.3.1) (2024-10-23)
diff --git a/README.md b/README.md
index 54296fc8c..09866781e 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ repositories {
dependencies {
// Include the sdk as a dependency
// x-release-please-start-version
- implementation 'com.microsoft.graph:microsoft-graph-core:3.3.1'
+ implementation 'com.microsoft.graph:microsoft-graph-core:3.4.0'
// x-release-please-end
// This dependency is only needed if you are using the TokenCredentialAuthProvider
implementation 'com.azure:azure-identity:1.11.0'
@@ -40,7 +40,7 @@ Add the dependency in `dependencies` in pom.xml
com.microsoft.graph
microsoft-graph-core
- 3.3.1
+ 3.4.0
com.azure
diff --git a/android/build.gradle b/android/build.gradle
index 2c9ea95c2..9821c0c24 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -5,8 +5,8 @@ buildscript {
}
dependencies {
- classpath "com.gradle:gradle-enterprise-gradle-plugin:3.18.1"
- classpath "com.android.tools.build:gradle:8.7.1"
+ classpath "com.gradle:gradle-enterprise-gradle-plugin:3.18.2"
+ classpath "com.android.tools.build:gradle:8.7.2"
classpath "com.github.ben-manes:gradle-versions-plugin:0.51.0"
}
}
@@ -43,19 +43,17 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
+ lint {
+ baseline = file("lint-baseline.xml")
+ }
+
lintOptions {
textOutput "stdout"
checkAllWarnings true
warningsAsErrors true
- disable "UnusedResources" // Unused will be removed on release
- disable "IconExpectedSize" // Using the material icons provided from Google
- disable "GoogleAppIndexingApiWarning" // We might want to index our app later
- disable "InvalidPackage" // Butterknife, Okio and Realm
- disable "ResourceType" // Annotation binding
- disable "GradleDependency"
- disable "NewerVersionAvailable"
- disable "DuplicatePlatformClasses" // xpp3 added by azure-identity
+ lintConfig file("lint.xml")
}
+
sourceSets {
main {
java.srcDirs = ['../src/main/java']
diff --git a/android/lint-baseline.xml b/android/lint-baseline.xml
new file mode 100644
index 000000000..11149ca54
--- /dev/null
+++ b/android/lint-baseline.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/android/lint.xml b/android/lint.xml
new file mode 100644
index 000000000..0e7a8f716
--- /dev/null
+++ b/android/lint.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index d8f84e580..e156b5e6c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ plugins {
id 'maven-publish'
id 'signing'
id 'jacoco'
- id 'com.github.spotbugs' version '6.0.25'
+ id 'com.github.spotbugs' version '6.0.26'
id "org.sonarqube" version "5.1.0.4882"
id 'io.github.gradle-nexus.publish-plugin' version '2.0.0'
}
diff --git a/gradle.properties b/gradle.properties
index ee942d982..9996fb853 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -27,10 +27,10 @@ mavenArtifactId = microsoft-graph-core
mavenMajorVersion = 3
# x-release-please-end
# x-release-please-start-minor
-mavenMinorVersion = 3
+mavenMinorVersion = 4
# x-release-please-end
# x-release-please-start-patch
-mavenPatchVersion = 1
+mavenPatchVersion = 0
# x-release-please-end
mavenArtifactSuffix =
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index c569a3f67..03159bff0 100644
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -4,21 +4,21 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.3'
testImplementation 'org.mockito:mockito-core:5.14.2'
- testImplementation 'io.opentelemetry:opentelemetry-api:1.43.0'
- testImplementation 'io.opentelemetry:opentelemetry-context:1.43.0'
+ testImplementation 'io.opentelemetry:opentelemetry-api:1.44.1'
+ testImplementation 'io.opentelemetry:opentelemetry-context:1.44.1'
testImplementation 'io.github.std-uritemplate:std-uritemplate:1.0.6'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1'
api 'com.squareup.okhttp3:okhttp:4.12.0'
- api 'com.azure:azure-core:1.53.0'
+ api 'com.azure:azure-core:1.54.1'
- api 'com.microsoft.kiota:microsoft-kiota-abstractions:1.7.0'
- api 'com.microsoft.kiota:microsoft-kiota-authentication-azure:1.7.0'
- implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:1.7.0'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:1.7.0'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:1.7.0'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-form:1.7.0'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.7.0'
+ api 'com.microsoft.kiota:microsoft-kiota-abstractions:1.8.0'
+ api 'com.microsoft.kiota:microsoft-kiota-authentication-azure:1.8.0'
+ implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:1.8.0'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:1.8.0'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:1.8.0'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-form:1.8.0'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.8.0'
}
diff --git a/pom.xml b/pom.xml
index a199192ca..a99338bed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
com.microsoft.graph
microsoft-graph-core
- 3.3.1
+ 3.4.0
pom
@@ -32,7 +32,7 @@
com.azure
azure-core
- 1.53.0
+ 1.54.1
org.junit.jupiter
diff --git a/spotBugsExcludeFilter.xml b/spotBugsExcludeFilter.xml
index ffb0ea6f2..619fb292d 100644
--- a/spotBugsExcludeFilter.xml
+++ b/spotBugsExcludeFilter.xml
@@ -64,6 +64,7 @@ xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubu
+
@@ -111,4 +112,4 @@ xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubu
-
\ No newline at end of file
+
diff --git a/src/main/java/com/microsoft/graph/core/CoreConstants.java b/src/main/java/com/microsoft/graph/core/CoreConstants.java
index 9025da1e8..2aaf8a7c0 100644
--- a/src/main/java/com/microsoft/graph/core/CoreConstants.java
+++ b/src/main/java/com/microsoft/graph/core/CoreConstants.java
@@ -16,10 +16,10 @@ private static class VersionValues {
private static final int MAJOR = 3;
// x-release-please-end
// x-release-please-start-minor
- private static final int MINOR = 3;
+ private static final int MINOR = 4;
// x-release-please-end
// x-release-please-start-patch
- private static final int PATCH = 1;
+ private static final int PATCH = 0;
// x-release-please-end
}
diff --git a/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java b/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java
index baa38bd76..d20c9afae 100644
--- a/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java
+++ b/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java
@@ -1,8 +1,11 @@
package com.microsoft.graph.core.requests;
+import com.azure.core.credential.TokenCredential;
import com.microsoft.graph.core.CoreConstants;
+import com.microsoft.graph.core.authentication.AzureIdentityAccessTokenProvider;
import com.microsoft.graph.core.requests.middleware.GraphTelemetryHandler;
import com.microsoft.graph.core.requests.options.GraphClientOption;
+import com.microsoft.kiota.RequestOption;
import com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider;
import com.microsoft.kiota.http.KiotaClientFactory;
import com.microsoft.kiota.http.middleware.AuthorizationHandler;
@@ -36,7 +39,7 @@ public static OkHttpClient.Builder create() {
* @return an OkHttpClient Builder instance.
*/
@Nonnull
- public static OkHttpClient.Builder create(@Nonnull Interceptor... interceptors) {
+ public static OkHttpClient.Builder create(@Nonnull final Interceptor... interceptors) {
return create(new GraphClientOption(), interceptors);
}
@@ -46,10 +49,31 @@ public static OkHttpClient.Builder create(@Nonnull Interceptor... interceptors)
* @return an OkHttpClient Builder instance.
*/
@Nonnull
- public static OkHttpClient.Builder create(@Nonnull List interceptors) {
+ public static OkHttpClient.Builder create(@Nonnull final List interceptors) {
return create(new GraphClientOption(), interceptors.toArray(new Interceptor[0]));
}
+ /**
+ * OkHttpClient Builder for Graph with authentication middleware that uses the specified TokenCredential.
+ * @param tokenCredential the TokenCredential to use for authentication.
+ * @return an OkHttpClient Builder instance.
+ */
+ @Nonnull
+ public static OkHttpClient.Builder create(@Nonnull final TokenCredential tokenCredential) {
+ return create(tokenCredential, new RequestOption[0]);
+ }
+
+ /**
+ * OkHttpClient Builder for Graph with authentication middleware that uses the specified TokenCredential and RequestOptions to override default graph interceptors.
+ * @param tokenCredential the TokenCredential to use for authentication.
+ * @param requestOptions custom request options to override default graph interceptors
+ * @return an OkHttpClient Builder instance.
+ */
+ @Nonnull
+ public static OkHttpClient.Builder create(@Nonnull final TokenCredential tokenCredential, @Nonnull final RequestOption[] requestOptions) {
+ return create(new BaseBearerTokenAuthenticationProvider(new AzureIdentityAccessTokenProvider(tokenCredential)), requestOptions);
+ }
+
/**
* OkHttpClient Builder for Graph with specified AuthenticationProvider.
* Adds an AuthorizationHandler to the OkHttpClient Builder.
@@ -57,9 +81,22 @@ public static OkHttpClient.Builder create(@Nonnull List interceptor
* @return an OkHttpClient Builder instance.
*/
@Nonnull
- public static OkHttpClient.Builder create(@Nonnull BaseBearerTokenAuthenticationProvider authenticationProvider) {
+ public static OkHttpClient.Builder create(@Nonnull final BaseBearerTokenAuthenticationProvider authenticationProvider) {
+ return create(authenticationProvider, new RequestOption[0]);
+ }
+
+ /**
+ * OkHttpClient Builder for Graph with specified AuthenticationProvider and RequestOptions to override default graph interceptors
+ * @param authenticationProvider the AuthenticationProvider to use for requests.
+ * @param requestOptions custom request options to override default graph interceptors
+ * @return an OkHttpClient Builder instance.
+ */
+ @Nonnull
+ public static OkHttpClient.Builder create(@Nonnull final BaseBearerTokenAuthenticationProvider authenticationProvider, @Nonnull final RequestOption[] requestOptions) {
final GraphClientOption graphClientOption = new GraphClientOption();
- final Interceptor[] interceptors = createDefaultGraphInterceptors(graphClientOption);
+ final List requestOptionsList = new ArrayList<>(Arrays.asList(requestOptions));
+ requestOptionsList.add(graphClientOption);
+ final Interceptor[] interceptors = createDefaultGraphInterceptors(requestOptionsList.toArray(new RequestOption[0]));
final ArrayList interceptorList = new ArrayList<>(Arrays.asList(interceptors));
interceptorList.add(new AuthorizationHandler(authenticationProvider));
graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.AUTH_HANDLER_FLAG);
@@ -74,18 +111,12 @@ public static OkHttpClient.Builder create(@Nonnull BaseBearerTokenAuthentication
* @return an OkHttpClient Builder instance.
*/
@Nonnull
- public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClientOption, @Nonnull Interceptor... interceptors) {
- final OkHttpClient.Builder builder = create(graphClientOption);
- //Skip adding interceptor if that class of interceptor already exist.
- final List appliedInterceptors = new ArrayList<>();
- for(Interceptor interceptor: builder.interceptors()) {
- appliedInterceptors.add(interceptor.getClass().toString());
- }
- for (Interceptor interceptor:interceptors){
- if(appliedInterceptors.contains(interceptor.getClass().toString())) {
- continue;
- }
- builder.addInterceptor(interceptor);
+ public static OkHttpClient.Builder create(@Nonnull final GraphClientOption graphClientOption, @Nonnull final Interceptor... interceptors) {
+ final OkHttpClient.Builder builder = KiotaClientFactory.create(interceptors);
+ final List customInterceptors = builder.interceptors();
+ final boolean telemetryHandlerExists = customInterceptors.stream().anyMatch(x -> x instanceof GraphTelemetryHandler);
+ if (!telemetryHandlerExists) {
+ customInterceptors.add(new GraphTelemetryHandler(graphClientOption));
}
return builder;
}
@@ -97,7 +128,7 @@ public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClient
* @return an OkHttpClient Builder instance.
*/
@Nonnull
- public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClientOption, @Nonnull List interceptors) {
+ public static OkHttpClient.Builder create(@Nonnull final GraphClientOption graphClientOption, @Nonnull final List interceptors) {
return create(graphClientOption, interceptors.toArray(new Interceptor[0]));
}
@@ -108,10 +139,21 @@ public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClient
* @return an OkHttpClient Builder instance.
*/
@Nonnull
- public static OkHttpClient.Builder create(@Nullable GraphClientOption graphClientOption) {
- GraphClientOption options = graphClientOption != null ? graphClientOption : new GraphClientOption();
- return KiotaClientFactory.create(createDefaultGraphInterceptors(options));
+ public static OkHttpClient.Builder create(@Nullable final GraphClientOption graphClientOption) {
+ GraphClientOption option = graphClientOption == null ? new GraphClientOption() : graphClientOption;
+ return KiotaClientFactory.create(createDefaultGraphInterceptors(option));
}
+
+ /**
+ * The OkHttpClient Builder with optional GraphClientOption and RequestOptions to override default graph interceptors
+ * @param requestOptions custom request options to override default graph interceptors
+ * @return an OkHttpClient Builder instance.
+ */
+ @Nonnull
+ public static OkHttpClient.Builder create(@Nonnull final RequestOption[] requestOptions) {
+ return KiotaClientFactory.create(createDefaultGraphInterceptors(requestOptions));
+ }
+
/**
* Creates the default Interceptors for use with Graph.
*
@@ -119,15 +161,46 @@ public static OkHttpClient.Builder create(@Nullable GraphClientOption graphClien
* @return an array of interceptors.
*/
@Nonnull
- public static Interceptor[] createDefaultGraphInterceptors(@Nonnull GraphClientOption graphClientOption) {
- List handlers = new ArrayList<>();
- addDefaultFeatureUsages(graphClientOption);
+ public static Interceptor[] createDefaultGraphInterceptors(@Nonnull final GraphClientOption graphClientOption) {
+ return getDefaultGraphInterceptors(new RequestOption[]{ graphClientOption }).toArray(new Interceptor[0]);
+ }
- handlers.add(new UrlReplaceHandler(new UrlReplaceHandlerOption(CoreConstants.ReplacementConstants.getDefaultReplacementPairs())));
+ /**
+ * Creates the default Interceptors for use with Graph configured with the provided RequestOptions.
+ * @param requestOptions custom request options to override default graph interceptors
+ * @return an array of interceptors.
+ */
+ @Nonnull
+ public static Interceptor[] createDefaultGraphInterceptors(@Nonnull final RequestOption[] requestOptions) {
+ Objects.requireNonNull(requestOptions, "parameter requestOptions cannot be null");
+ return getDefaultGraphInterceptors(requestOptions).toArray(new Interceptor[0]);
+ }
+
+ /**
+ * Creates the default Interceptors for use with Graph.
+ * @param requestOptions custom request options to override default graph interceptors
+ * @return a list of interceptors.
+ */
+ private static List getDefaultGraphInterceptors(@Nonnull final RequestOption[] requestOptions) {
+ GraphClientOption graphClientOption = new GraphClientOption();
+ UrlReplaceHandlerOption urlReplaceHandlerOption = new UrlReplaceHandlerOption(CoreConstants.ReplacementConstants.getDefaultReplacementPairs());
+ for (RequestOption option : requestOptions) {
+ if (option instanceof UrlReplaceHandlerOption) {
+ urlReplaceHandlerOption = (UrlReplaceHandlerOption) option;
+ }
+ if (option instanceof GraphClientOption) {
+ graphClientOption = (GraphClientOption) option;
+ }
+ }
+
+ List handlers = new ArrayList<>();
+ handlers.add(new UrlReplaceHandler(urlReplaceHandlerOption));
handlers.add(new GraphTelemetryHandler(graphClientOption));
- handlers.addAll(Arrays.asList(KiotaClientFactory.createDefaultInterceptors()));
- return handlers.toArray(new Interceptor[0]);
+ handlers.addAll(Arrays.asList(KiotaClientFactory.createDefaultInterceptors(requestOptions)));
+ addDefaultFeatureUsages(graphClientOption);
+ return handlers;
}
+
//These are the default features used by the Graph Client
private static void addDefaultFeatureUsages(GraphClientOption graphClientOption) {
graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.RETRY_HANDLER_FLAG);
diff --git a/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java b/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java
index fcc2972b9..001173c46 100644
--- a/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java
+++ b/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java
@@ -10,23 +10,88 @@
import java.io.IOException;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import com.azure.core.credential.AccessToken;
+import com.azure.core.credential.TokenCredential;
import com.microsoft.graph.core.authentication.AzureIdentityAccessTokenProvider;
import com.microsoft.graph.core.authentication.AzureIdentityAuthenticationProvider;
+import com.microsoft.graph.core.requests.middleware.GraphTelemetryHandler;
+import com.microsoft.graph.core.requests.options.GraphClientOption;
+import com.microsoft.kiota.RequestOption;
import com.microsoft.kiota.authentication.AccessTokenProvider;
import com.microsoft.kiota.authentication.AllowedHostsValidator;
import com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider;
+import com.microsoft.kiota.http.middleware.HeadersInspectionHandler;
+import com.microsoft.kiota.http.middleware.ParametersNameDecodingHandler;
+import com.microsoft.kiota.http.middleware.RedirectHandler;
+import com.microsoft.kiota.http.middleware.RetryHandler;
+import com.microsoft.kiota.http.middleware.UrlReplaceHandler;
+import com.microsoft.kiota.http.middleware.UserAgentHandler;
+import com.microsoft.kiota.http.middleware.options.RetryHandlerOption;
+import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
+import reactor.core.publisher.Mono;
class GraphClientFactoryTest {
private static final String ACCESS_TOKEN_STRING = "token";
+ @Test
+ void testDefaultCreate() {
+ final OkHttpClient.Builder clientBuilder = GraphClientFactory.create();
+ assertDefaultHandlersPresent(clientBuilder.interceptors());
+ }
+
+ @Test
+ void testCreateWithCustomInterceptorsAddsTelemetry() {
+ final OkHttpClient.Builder clientBuilder = GraphClientFactory.create(
+ new RetryHandler(), new RedirectHandler()
+ );
+
+ assertEquals(3, clientBuilder.interceptors().size());
+
+ for (Interceptor interceptor : clientBuilder.interceptors()) {
+ assertTrue(
+ interceptor instanceof GraphTelemetryHandler
+ || interceptor instanceof RetryHandler
+ || interceptor instanceof RedirectHandler
+ );
+ }
+ }
+
+ @Test
+ void testCreateWithGraphClientOption() {
+ final OkHttpClient.Builder clientBuilder = GraphClientFactory.create(new GraphClientOption());
+ assertDefaultHandlersPresent(clientBuilder.interceptors());
+ }
+
+ @Test
+ void testCreateDefaultInterceptorsWithCustomOptions() {
+ Interceptor[] interceptors = GraphClientFactory.createDefaultGraphInterceptors(
+ new RequestOption[] {new RetryHandlerOption(null, 0, 0)}
+ );
+ assertDefaultHandlersPresent(Arrays.asList(interceptors));
+
+ for (Interceptor interceptor : interceptors) {
+ if (interceptor instanceof RetryHandler) {
+ RetryHandlerOption retryOptions = ((RetryHandler) interceptor).getRetryOptions();
+ Assertions.assertEquals(0, retryOptions.maxRetries());
+ Assertions.assertEquals(0, retryOptions.delay());
+ }
+ }
+ }
+
@Test
void testCreateWithAuthenticationProvider() throws IOException {
final BaseBearerTokenAuthenticationProvider mockAuthenticationProvider =
@@ -42,6 +107,92 @@ void testCreateWithAuthenticationProvider() throws IOException {
assertEquals("Bearer " + ACCESS_TOKEN_STRING, response.request().header("Authorization"));
}
+ @Test
+ void testCreateWithTokenCredential() throws IOException {
+ final TokenCredential tokenCredential = mock(TokenCredential.class);
+ when(tokenCredential.getTokenSync(any())).thenReturn(new AccessToken(ACCESS_TOKEN_STRING, null));
+ when(tokenCredential.getToken(any())).thenReturn(Mono.just(new AccessToken(ACCESS_TOKEN_STRING, null)));
+
+ final OkHttpClient graphClient = GraphClientFactory.create(tokenCredential).addInterceptor(new MockResponseHandler()).build();
+ Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me").build();
+ Response response = graphClient.newCall(request).execute();
+
+ assertEquals(200, response.code());
+ assertNotNull(response.request());
+ assertTrue(response.request().headers().names().contains("Authorization"));
+ assertEquals("Bearer " + ACCESS_TOKEN_STRING, response.request().header("Authorization"));
+ }
+
+ @Test
+ void testCreateWithAuthenticationProviderAndCustomRequestOptions() throws IOException {
+ final BaseBearerTokenAuthenticationProvider mockAuthenticationProvider =
+ getMockAuthenticationProvider();
+ var requestOptions = new ArrayList();
+ requestOptions.add(new RetryHandlerOption(null, 0, 0));
+ OkHttpClient graphClient = GraphClientFactory.create(mockAuthenticationProvider, requestOptions.toArray(new RequestOption[0])).addInterceptor(new MockResponseHandler()).build();
+
+ var interceptors = graphClient.interceptors();
+ for (Interceptor interceptor : interceptors) {
+ if (interceptor instanceof RetryHandler) {
+ RetryHandlerOption retryOptions = ((RetryHandler) interceptor).getRetryOptions();
+ Assertions.assertEquals(0, retryOptions.maxRetries());
+ Assertions.assertEquals(0, retryOptions.delay());
+ }
+ }
+
+ Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me")
+ .addHeader("CustomHeader", "CustomValue").build();
+ Response response = graphClient.newCall(request).execute();
+
+ assertEquals(200, response.code());
+ assertNotNull(response.request());
+ assertTrue(response.request().headers().names().contains("Authorization"));
+ assertTrue(response.request().headers().names().contains("CustomHeader"));
+ assertEquals("Bearer " + ACCESS_TOKEN_STRING, response.request().header("Authorization"));
+ assertEquals("CustomValue", response.request().header("CustomHeader"));
+ }
+
+ @Test
+ void testCreateWithCustomInterceptorsOverwritesDefaults() throws IOException {
+
+ final Interceptor[] interceptors = {new GraphTelemetryHandler(), getDisabledRetryHandler(),
+ new RedirectHandler()};
+ final OkHttpClient client = GraphClientFactory.create(interceptors).build();
+ final Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build();
+ client.newCall(request).execute();
+
+ for (Interceptor clientInterceptor : client.interceptors()) {
+ if (clientInterceptor instanceof RetryHandler) {
+ RetryHandlerOption retryOptions = ((RetryHandler) clientInterceptor).getRetryOptions();
+ Assertions.assertEquals(0, retryOptions.maxRetries());
+ Assertions.assertEquals(0, retryOptions.delay());
+
+ }
+
+ assertTrue(clientInterceptor instanceof GraphTelemetryHandler
+ || clientInterceptor instanceof RedirectHandler
+ || clientInterceptor instanceof RetryHandler);
+ }
+ }
+
+ private void assertDefaultHandlersPresent(final List interceptors) {
+ HashSet> expectedInterceptors = new HashSet<>(
+ Arrays.asList(
+ GraphTelemetryHandler.class,
+ RetryHandler.class,
+ UrlReplaceHandler.class,
+ UserAgentHandler.class,
+ RedirectHandler.class,
+ ParametersNameDecodingHandler.class,
+ HeadersInspectionHandler.class
+ )
+ );
+
+ for (Interceptor interceptor : interceptors) {
+ assertTrue(expectedInterceptors.contains(interceptor.getClass()));
+ }
+ }
+
private static BaseBearerTokenAuthenticationProvider getMockAuthenticationProvider() {
final AccessTokenProvider mockAccessTokenProvider = mock(AzureIdentityAccessTokenProvider.class);
when(mockAccessTokenProvider.getAuthorizationToken(any(URI.class), anyMap()))
@@ -53,4 +204,11 @@ private static BaseBearerTokenAuthenticationProvider getMockAuthenticationProvid
.thenReturn(mockAccessTokenProvider);
return mockAuthenticationProvider;
}
+
+ private static @NotNull RetryHandler getDisabledRetryHandler() {
+ RetryHandlerOption retryHandlerOption = new RetryHandlerOption(
+ (delay, executionCount, request, response) -> false, 0, 0);
+ RetryHandler retryHandler = new RetryHandler(retryHandlerOption);
+ return retryHandler;
+ }
}
diff --git a/src/test/java/com/microsoft/graph/core/requests/middleware/GraphTelemetryHandlerTest.java b/src/test/java/com/microsoft/graph/core/requests/middleware/GraphTelemetryHandlerTest.java
index b03f40615..06bf4f9e5 100644
--- a/src/test/java/com/microsoft/graph/core/requests/middleware/GraphTelemetryHandlerTest.java
+++ b/src/test/java/com/microsoft/graph/core/requests/middleware/GraphTelemetryHandlerTest.java
@@ -10,7 +10,9 @@
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
+
import org.junit.jupiter.api.Test;
+
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -29,23 +31,31 @@ void telemetryHandlerDefaultTests() throws IOException {
final Response response = client.newCall(request).execute();
assertNotNull(response);
+ assertNotNull(response.request());
+ assertNotNull(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME));
assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(expectedCore));
- assertTrue(!response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(CoreConstants.Headers.ANDROID_VERSION_PREFIX)); // Android version is not going to be present on unit tests running on java platform
- assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(defaultSDKVersion));
+ assertTrue(!response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(
+ CoreConstants.Headers.ANDROID_VERSION_PREFIX)); // Android version is not going to be present on unit tests running on java platform
+ assertTrue(
+ response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(defaultSDKVersion));
}
@Test
void arrayInterceptorsTest() throws IOException {
final String expectedCore = CoreConstants.Headers.GRAPH_VERSION_PREFIX + "/" + CoreConstants.Headers.VERSION;
- final Interceptor[] interceptors = {new GraphTelemetryHandler(), new RetryHandler(), new RedirectHandler()};
+ final Interceptor[] interceptors = {new GraphTelemetryHandler(), new RetryHandler(),
+ new RedirectHandler()};
final OkHttpClient client = GraphClientFactory.create(interceptors).build();
final Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build();
final Response response = client.newCall(request).execute();
assertNotNull(response);
+ assertNotNull(response.request());
+ assertNotNull(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME));
assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(expectedCore));
- assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(defaultSDKVersion));
+ assertTrue(
+ response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(defaultSDKVersion));
}
@Test
@@ -58,8 +68,11 @@ void arrayInterceptorEmptyTest() throws IOException {
final Response response = client.newCall(request).execute();
assertNotNull(response);
+ assertNotNull(response.request());
+ assertNotNull(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME));
assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(expectedCore));
- assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(defaultSDKVersion));
+ assertTrue(
+ response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(defaultSDKVersion));
}
@Test
@@ -76,7 +89,7 @@ void testClientOptions() throws IOException {
graphClientOption.setGraphServiceTargetVersion(serviceLibVer);
final String expectedCoreVer =
- CoreConstants.Headers.GRAPH_VERSION_PREFIX + "/" +coreLibVer;
+ CoreConstants.Headers.GRAPH_VERSION_PREFIX + "/" + coreLibVer;
final String expectedClientEndpoint =
CoreConstants.Headers.JAVA_VERSION_PREFIX + "-" + serviceLibVer + "/" + clientLibVer;
@@ -84,8 +97,12 @@ void testClientOptions() throws IOException {
final Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/users/").build();
final Response response = client.newCall(request).execute();
+ assertNotNull(response);
+ assertNotNull(response.request());
+ assertNotNull(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME));
assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(expectedCoreVer));
- assertTrue(response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(expectedClientEndpoint));
+ assertTrue(
+ response.request().header(CoreConstants.Headers.SDK_VERSION_HEADER_NAME).contains(expectedClientEndpoint));
assertTrue(response.request().header(CoreConstants.Headers.CLIENT_REQUEST_ID).contains(requestId));
}
}