0

Application Type : Java Spring Boot Daemon application using Client Credentials Flow.

I was earlier using microsoft-graph 2.10.0 for fetching data from Microsoft graph. However with the recent microsoft-graph 3.0.0, I wanted to update the project.

Following the upgrade and auth details, i have used the below to get the GraphServiceClient using ClientCredentials azure-identity:

String proxyUrl = "xxxxx";
int proxyPort = 8080;

ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP,new InetSocketAddress(proxyUrl, proxyPort));
// proxyOptions.setCredentials(proxyUser, proxyPassword);

final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId(this.clientId).clientSecret(this.clientSecret).tenantId(this.tenantId)
.httpClient(HttpClient.createDefault(new HttpClientOptions().setProxyOptions(proxyOptions))).build();

final TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(this.scopes, clientSecretCredential);

final GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider)
                .buildClient();

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- exclude logback , add log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <!-- Microsoft Graph -->
        <dependency>
            <groupId>com.microsoft.graph</groupId>
            <artifactId>microsoft-graph</artifactId>
            <version>3.0.0</version>
        </dependency>   

        <!-- For SMTP Email -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
            <scope>runtime</scope>
        </dependency>

        <!-- SQL -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>   
    </dependencies>

Note : Using 2.10.0 i used to pass the Proxy using JVM arguments, however the same did not work using 3.0.0 hence ended up using the proxyOptions following link.

Issue : Receiving the below error while fetching any data, the error is seen while setting the httpClient in the above code.

2021-03-22T16:04:18,295 ERROR [restartedMain] o.s.b.SpringApplication: Application run failed
java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: reactor/netty/tcp/ProxyProvider$TypeSpec
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.lambda$build$7(NettyAsyncHttpClientBuilder.java:142)
    at reactor.netty.http.client.HttpClient.tcpConfiguration(HttpClient.java:1343)
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.build(NettyAsyncHttpClientBuilder.java:122)
    at com.azure.core.http.netty.NettyAsyncHttpClientProvider.createInstance(NettyAsyncHttpClientProvider.java:32)
    at com.azure.core.implementation.http.HttpClientProviders.createInstance(HttpClientProviders.java:48)
    at com.azure.core.http.HttpClient.createDefault(HttpClient.java:50)
    at com.app.intune.config.GraphClient.getGraphServiceClient(GraphClient.java:48)
    at com.app.intune.util.UserUtil.getUsersWithRegisteredDevicesAndSave(UserUtil.java:140)
    at com.app.intune.IntuneApplication.run(IntuneApplication.java:61)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
    at com.app.intune.IntuneApplication.main(IntuneApplication.java:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NoClassDefFoundError: reactor/netty/tcp/ProxyProvider$TypeSpec
    ... 18 more
Caused by: java.lang.ClassNotFoundException: reactor.netty.tcp.ProxyProvider$TypeSpec
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 18 more

Any help on the above will be greatly appreciated.

Update 1: Seems the Spring Boot Dependency was managing okhttp3.version. After updating the property to below, the error was resolved.

<properties>
    <java.version>1.8</java.version>
    <okhttp3.version>4.9.1</okhttp3.version>        
</properties>

However now there is new error:

java.lang.NoClassDefFoundError: reactor/netty/channel/BootstrapHandlers
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.lambda$build$4(NettyAsyncHttpClientBuilder.java:139)
    at reactor.netty.tcp.TcpClient.bootstrap(TcpClient.java:144)
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.lambda$build$7(NettyAsyncHttpClientBuilder.java:138)
    at reactor.netty.http.client.HttpClient.tcpConfiguration(HttpClient.java:1343)
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.build(NettyAsyncHttpClientBuilder.java:122)
    at com.app.intune.config.GraphClient.getGraphServiceClient(GraphClient.java:43)
    at com.app.intune.util.UserUtil.getUsersWithRegisteredDevicesAndSave(UserUtil.java:140)
    at com.app.intune.IntuneApplication.run(IntuneApplication.java:57)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298)
    at com.app.intune.IntuneApplication.main(IntuneApplication.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.ClassNotFoundException: reactor.netty.channel.BootstrapHandlers
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 19 more
2
  • Yes use the latest SDK/dependencies is the best way to get rid of the above errors; don't update partially and it will break all of it. Commented Mar 23, 2021 at 3:32
  • I have used the latest version of microsoft-graph and spring boot as well, however still doesnt work as spring boot uses lower version and higher version of some dependencies. Commented Mar 23, 2021 at 4:41

2 Answers 2

1

For anyone facing the issue, below is a solution: Project Details:
Spring Boot 2.4.4
microsoft-graph 3.0.0

Create GraphClient using below:

final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
    .clientId(<clientId>)
    .clientSecret(<clientSecret>)
    .tenantId(<tenantId>)
    .httpClient(new NettyAsyncHttpClientBuilder().proxy(
        new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("<proxyHost>", <proxyPort>))
        .setCredentials("<proxyUser>","<proxyPassword>"))
        .build())
    .build();
    
final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(this.scopes, clientSecretCredential);
    
final GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(tokenCredentialAuthProvider).buildClient();

You might get additional errors as :

Exception in thread "main" java.lang.NoClassDefFoundError: reactor/netty/channel/BootstrapHandlers
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.lambda$build$4(NettyAsyncHttpClientBuilder.java:139)
    at reactor.netty.tcp.TcpClient.bootstrap(TcpClient.java:187)
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.lambda$build$7(NettyAsyncHttpClientBuilder.java:138)
    at reactor.netty.http.client.HttpClient.tcpConfiguration(HttpClient.java:1466)
    at com.azure.core.http.netty.NettyAsyncHttpClientBuilder.build(NettyAsyncHttpClientBuilder.java:122)
    at com.app.graph_test.App.main(App.java:43)
Caused by: java.lang.ClassNotFoundException: reactor.netty.channel.BootstrapHandlers
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 6 more

The above issues occurs as microsoft-graph : 3.0.0 has below dependency tree:

microsoft-graph : 3.0.0
 - microsoft-graph-core : 2.0.0     
 -   azure-identity :1.2.3
 -     azure-core-http-netty : 1.8.0
 -       reactor-netty : 0.9.15.RELEASE

Spring boot 2.4.4 has managed dependency, hence it includes the below versions :

reactor-core : 3.4.4  
reactor-netty : 1.0.5  

The new version of reactor-netty doesnt work for microsoft-graph 3.0. Hence manually override it by adding the below in pom.xml.

<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
<version>0.9.15.RELEASE</version>
</dependency>

Post this there should be no errors.

Sign up to request clarification or add additional context in comments.

Comments

0

It took me a long time to find the solution to this issue. I am using spring boot 2.2.x and MS Graph SDK version 5.33.0. I was not able to update my spring boot version, because that would cause issues in other components of my application. In the end, I was able to solve the issue, using this GitHub link: https://github.com/Azure/azure-sdk-for-java/issues/17986.

I had to add the following in the properties section of my pom:

<reactor-bom.version>2020.0.6</reactor-bom.version>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.