M365関連 プログラム 技術

KotlinでGraphAPIを実行する

これまで色々な言語でGraphAPIについて記事を書いてきましたが、今回はKotlinでGraphAPIを読んでみようと思います
本記事の内容でJavaも同じように実装できると思います。また、Azure上でのGraphAPIの設定については本記事では取り扱いませんので他の記事で参考にしてみてください

名称バージョン
jdk21
Kotlin2.3.10
com.microsoft.graph:microsoft-graph6.+
com.azure:azure-identity1.+
関連記事
C#・PowerShellで会議室のイベントを取得(アプリケーション版)<実行編> - ナストンのまとめ
C#・PowerShellで会議室のイベントを取得(アプリケーション版)<実行編> - ナストンのまとめ

前回はMSGraphAPIを使用するための準備をしました。今回は実際にC#やPowerShellで呼び出します アクセス ...

関連記事へ

関連記事
C#・PowerShellで会議室のイベントを取得(委任されたアクセス許可版)<実行編> - ナストンのまとめ
C#・PowerShellで会議室のイベントを取得(委任されたアクセス許可版)<実行編> - ナストンのまとめ

前回、ユーザー認証でアクセストークンを取得できるように設定できたので、それを使用して実際に会議室の情報を取得していきます ...

関連記事へ

関連記事
JavaScriptでMicrosoftGraphAPIを使う(Express&MSAL版) - ナストンのまとめ
JavaScriptでMicrosoftGraphAPIを使う(Express&MSAL版) - ナストンのまとめ

GraphAPIをJavaScriptから呼び出そうとした際に色々と手間取ったので、そのメモです今回はNodeJSのEx ...

関連記事へ

関連記事
JavaScriptでMicrosoftGraphAPIを使う(Express&SDK版) - ナストンのまとめ
JavaScriptでMicrosoftGraphAPIを使う(Express&SDK版) - ナストンのまとめ

前回、ExpressとMSALを使用してGraphAPIを呼び出しましたが、今回はSDKを使用してGraphAPIを呼び ...

関連記事へ

関連記事
PythonからGraphAPI経由でSharePointのリストアイテムを取得する - ナストンのまとめ
PythonからGraphAPI経由でSharePointのリストアイテムを取得する - ナストンのまとめ

以前、C#やJavaScriptからM365のGraphAPIを呼び出すことは何度かあったのですが、今回はPythonか ...

関連記事へ

Gradleで必要なSDKをインストールする

以下のサイトを参考にするとMSサイトに記載されているJava版のままで問題なさそうなので、MSサイトの設定を元にプラグインをインストールします。今回もGradle経由でプラグインをインストールしています

参考サイト
Using Java SDK and Microsoft Graph API V6 with Kotlin for Email Dispatch
Using Java SDK and Microsoft Graph API V6 with Kotlin for Email Dispatch

参考サイトへ

MSサイト
Microsoft Graph SDK をインストールする - Microsoft Graph | Microsoft Learn
Microsoft Graph SDK をインストールする - Microsoft Graph | Microsoft Learn

.NET、Go、Java、JavaScript、PHP、PowerShell、Python 用の Microsoft G ...

MSサイトへ

// build.gradle.kts
plugins {
    kotlin("jvm") version "2.3.10"
}

group = "org.m365graphapi"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    // Include the sdk as a dependency
    implementation("com.microsoft.graph:microsoft-graph:6.+") // 追加
    // Include Azure identity for authentication
    implementation("com.azure:azure-identity:1.+") // 追加
    testImplementation(kotlin("test"))
}

kotlin {
    jvmToolchain(21)
}

tasks.test {
    useJUnitPlatform()
}

Kotlinへの実装時の関門

上記でプラグインをインストールしましたが、色々と躓くことがありました。その解決策です

プラグインバージョンアップによる仕様変更

まず最初にGraphAPIを実装しようとした際に躓いたことは、使用しているプライグインのアップデートに伴うAPIの仕様変更でした
com.microsoft.graph:microsoft-graph がVer 6になった際にAPI周りがガラリと変わっているみたいです
その為、エラーが解消できなくてなかなか困りました

// Ver 5 (旧) 仕様が変わる前
import com.microsoft.graph.requests.GraphServiceClient

val credential = ClientSecretCredentialBuilder()
        .clientId(clientId)
        .tenantId(tenantId)
        .clientSecret(clientSecret)
        .build()
val graphClient = GraphServiceClient.builder().authenticationProvider(credential).buildClient()


// Ver 6 (新) 仕様が変わった後
// 変更点1:importするパッケージ名が変わっている
// 変更点2:GraphServiceClient生成時にscopesを渡す形になっている
import com.microsoft.graph.serviceclient.GraphServiceClient

val credential = ClientSecretCredentialBuilder()
        .clientId(clientId)
        .tenantId(tenantId)
        .clientSecret(clientSecret)
        .build()

val graphClient = GraphServiceClient(credential, *scopes)

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". というエラーが出る

実際にコードを実行すると以下のような文が出ます。調べたところ動作への影響はないようですが、これはエラーではなく警告のようです
SLF4J(ロギングAPI)の実装ライブラリがクラスパスにないため、ログ出力が無効化(NOP)されているだけです

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

上記警告文を表示させたくない場合は対象プラグインをbuild.gradle.ktsに追加します

dependencies {
    // Include the sdk as a dependency
    implementation("com.microsoft.graph:microsoft-graph:6.+")
    // Include Azure identity for authentication
    implementation("com.azure:azure-identity:1.+")
    // SLF4J logging implementation
    implementation("org.slf4j:slf4j-simple:2.0.16") // 追加
    testImplementation(kotlin("test"))
}

GraphAPIから返却されるデータが文字化けする

GraphAPIから返却されるデータに日本語が含まれている場合に文字化けが発生していました
原因はWindows環境では、JVMのデフォルト文字エンコーディングが Windows-31J(Shift_JIS系) ですが、GraphAPIから返されるデータはUTF-8のためです。このエンコーディングの不一致により、日本語などのマルチバイト文字が文字化けが発生するようです
そのため、gradle.propertiesとbuild.gradle.ktsにそれぞれ以下を追記します

// gradle.propertiesに追記
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 // 追加

// build.gradle.ktsに追記
tasks.withType<JavaExec> {
    jvmArgs("-Dfile.encoding=UTF-8", "-Dstdout.encoding=UTF-8", "-Dstderr.encoding=UTF-8")
}

実際に実装する

これでやっとGraphAPIの実装ができるようになりましたので、いつものことながらSharePointのリストアイテムの取得までを実装します

GraphAPIを呼び出すためのオブジェクトを生成する

まず初めにGraphAPIを呼び出すために必要となるオブジェクトを作成します

fun main() {
    val clientId = "YOUR_CLIENT_ID"
    val tenantId = "YOUR_TENANT_ID"
    val clientSecret = "YOUR_CLIENT_SECRET"
    val scopes = arrayOf("https://graph.microsoft.com/.default")

    val credential = ClientSecretCredentialBuilder()
        .clientId(clientId)
        .tenantId(tenantId)
        .clientSecret(clientSecret)
        .build()

    val graphClient = GraphServiceClient(credential, *scopes)
}

サイト情報を取得する

リストアイテムを取得するための第一段階としてサイト情報を取得します

fun main() {
    val siteId = "ドメイン.sharepoint.com:/sites/HogeHugaPiyo"
    val resolvedSiteId = getSiteId(graphClient, siteId)
}

fun getSiteId(graphClient: GraphServiceClient, siteId: String): String? {
    val site = graphClient.sites().bySiteId(siteId).get()
    println("Site ID   : ${site?.id}")
    println("Site Name : ${site?.displayName}")
    println("Web URL   : ${site?.webUrl}")
    return site?.id
}

リスト情報を取得する

リストアイテムを取得するための第二段階としてリスト情報を取得します

fun main() {
    val siteId = "ドメイン.sharepoint.com:/sites/HogeHugaPiyo"
    val listDisplayName = "Testリスト"
    val resolvedSiteId = getSiteId(graphClient, siteId)
    if (resolvedSiteId != null) {
        val resolvedListId = getLisdId(graphClient, resolvedSiteId,listDisplayName)
        if (resolvedListId != null) {
            println("OK")
        } else {
            println("Failed to retrieve List ID.")
        }
    } else {
        println("Failed to retrieve Site ID.")
    }
}

fun getLisdId(graphClient: GraphServiceClient, siteId: String, listId: String): String? {
    val list = graphClient.sites().bySiteId(siteId).lists().byListId(listId).get()
    println("List ID   : ${list?.id}")
    println("List Name : ${list?.displayName}")
    println("Web URL   : ${list?.webUrl}")
    return list?.id
}

リストアイテムを取得する

最後に実際にリストアイテムを列情報を含めて取得します

fun main() {
    val siteId = "ドメイン.sharepoint.com:/sites/HogeHugaPiyo"
    val listDisplayName = "Testリスト"
    val resolvedSiteId = getSiteId(graphClient, siteId)
    if (resolvedSiteId != null) {
        val resolvedListId = getLisdId(graphClient, resolvedSiteId,listDisplayName)
        if (resolvedListId != null) {
            getListItems(graphClient, resolvedSiteId, resolvedListId)
        } else {
            println("Failed to retrieve List ID.")
        }
    } else {
        println("Failed to retrieve Site ID.")
    }
}

fun getListItems(graphClient: GraphServiceClient, siteId: String, listId: String) {
    val items = graphClient.sites().bySiteId(siteId).lists().byListId(listId).items().get { requestConfiguration ->
        requestConfiguration.queryParameters?.expand = arrayOf("fields")
    }

    items?.value?.forEachIndexed { index, item ->
        println("=== Item ${index + 1} (ID: ${item.id}) ===")
        val fields = item.fields
        if (fields != null) {
            fields.additionalData.forEach { (key, value) ->
                println("  $key : $value")
            }
        } else {
            println("  (fields is null)")
        }
    }
}

最後に

色々と躓くことがありましたが、なんとか目標としていたSharePointのリストアイテムの取得まで実装できました
また、いつものごとくサンプルコードをGitHubにアップしていますので参考にしてみてください

サンプルコード
BlogSampleCodeProjects/MicrosoftGraphAPI_Kotlin at main · nasuton/BlogSampleCodeProjects · GitHub
BlogSampleCodeProjects/MicrosoftGraphAPI_Kotlin at main · nasuton/BlogSampleCodeProjects · GitHub

Project for sample code used in the blog.(Blogで記載しているサンプルコード ...

GitHubへ

会社紹介

私が所属しているアドバンスド・ソリューション株式会社(以下、ADS)は一緒に働く仲間を募集しています

会社概要
「技術」×「知恵」=顧客課題の解決・新しい価値の創造

この方程式の実現はADSが大切にしている考えで、技術を磨き続けるgeekさと、顧客を思うloveがあってこそ実現できる世界観だと思っています
この『love & geek』の精神さえあれば、得意不得意はno problem!
技術はピカイチだけど顧客折衝はちょっと苦手。OKです。技術はまだ未熟だけど顧客と知恵を出し合って要件定義するのは大好き。OKです
凸凹な社員の集まり、色んなカラーや柄の個性が集まっているからこそ、常に新しいソリューションが生まれています

ミッション
私たちは、テクノロジーを活用し、業務や事業の生産性向上と企業進化を支援します

ホームページ
アドバンスド・ソリューション株式会社|ADS Co., Ltd.
アドバンスド・ソリューション株式会社|ADS Co., Ltd.

Microsoft 365/SharePoint/Power Platform/Azure による DX コンサル・シス ...

サイトへ移動

PR

-M365関連, プログラム, 技術
-,