A Notion SDK for Any JVM Language

Related tags

notion-sdk-jvm
Overview

Notion SDK for Any JVM Language

A simple and easy to use client for the Notion API


Maven Central CI Build

Here is an Notion API SDK for any JVM language users 👋

This project aims to provide a Notion API client for any JVM language developers without hurdles. To realize the goal, its code is written in Kotlin with a nice consideration for Java compatibility.

This SDK works on Android runtime and any distributions based on OpenJDK. With regard to programming languages, this project provides out-of-the-box supports for Java (of course!), Kotlin, and the novel Scala 3! We don't have nice wrappers for some other JVM lanaguages such as Groovy and Clojure, but your code using this library should work in the lanaguges too.

Getting Started

You can start using this library just by adding notion-sdk-jvm-core dependency to your project.

For Gradle users:

ext.notionSdkVersion = "0.1.12"
dependencies {
  // This dependency is at least required
  implementation("com.github.seratch:notion-sdk-jvm-core:${notionSdkVersion}")
}

For Maven users:

<properties>
  <notion-sdk.version>0.1.12</notion-sdk.version>
</properties>

<dependencies>
  <dependency>
    <groupId>com.github.seratch</groupId>
    <artifactId>notion-sdk-jvm-core</artifactId>
    <version>${notion-sdk.version}</version>
  </dependency>
</dependencies>

As this library is in Kotlin, using in the same language is the smoothest :) Let's start with the following code, which manipulates Notion pages 👋

import notion.api.v1.NotionClient
import notion.api.v1.model.pages.PageParent
import notion.api.v1.model.pages.PageProperty as prop

fun main() {
    val client = NotionClient(token = System.getenv("NOTION_TOKEN"))
    client.use {

        // Look up all databases that this app can access
        val databases = client.listDatabases()
        // Find the "Test Database" from the list
        val database = databases.results.find { it.title.any { t -> t.plainText.contains("Test Database") } }
            ?: throw IllegalStateException("Create a database named 'Test Database' and invite this app's user!")

        // All the options for "Severity" property (select type)
        val severityOptions = database.properties?.get("Severity")?.select?.options
        // All the options for "Tags" property (multi_select type)
        val tagOptions = database.properties?.get("Tags")?.multiSelect?.options
        // The user object for "Assignee" property (people type)
        val assignee = client.listUsers().results[0] // just picking the first user up

        // Create a new page in the database
        val newPage = client.createPage(
            // Use the "Test Database" as this page's parent
            parent = PageParent.database(database.id),
            // Set values to the page's properties
            // (these must be pre-defined before this API call)
            properties = mapOf(
                "Title" to prop(title = listOf(prop.RichText(text = prop.RichText.Text(content = "Fix a bug")))),
                "Severity" to prop(select = severityOptions?.find { it.name == "High" }),
                "Tags" to prop(multiSelect = tagOptions),
                "Due" to prop(date = prop.Date(start = "2021-05-13", end = "2021-12-31")),
                "Velocity Points" to prop(number = 3),
                "Assignee" to prop(people = listOf(assignee)),
                "Done" to prop(checkbox = true),
                "Link" to prop(url = "https://www.example.com"),
                "Contact" to prop(email = "[email protected]"),
            )
        )

        // Update properties in the page
        val updatedPage =
            client.updatePageProperties(
                pageId = newPage.id,
                // Update only "Severity" property
                properties = mapOf(
                    "Severity" to prop(select = severityOptions?.find { it.name == "Medium" }),
                )
            )

        // Fetch the latest data of the page
        val retrievedPage = client.retrievePage(newPage.id)
    }
}

Using in Java

Even when you use this SDK in Java and other languages, all the classes/methods should be accessible. If you find issues, please let us know the issue in this project's issue tracker.

import notion.api.v1.NotionClient;
import notion.api.v1.model.databases.Databases;

public class Readme {
    public static void main(String[] args) {
        try (NotionClient client = new NotionClient(System.getenv("NOTION_TOKEN"))) {
            Databases databases = client.listDatabases();
        }
    }
}

Scala 3 Support

Although many classes are still Java/Kotlin objects, you can seamlessly use this SDK in Scala 3 too! Here is a simple build.sbt example:

val notionSdkVersion = "0.1.12"

lazy val root = project
  .in(file("."))
  .settings(
    scalaVersion := "3.0.0",
    libraryDependencies ++= Seq(
      "com.github.seratch" % "notion-sdk-jvm-scala3" % notionSdkVersion,
      "com.github.seratch" % "notion-sdk-jvm-httpclient" % notionSdkVersion,
    )
  )

Save the following source code as Main.scala. You can run the app by hitting sbt run.

import notion.api.v1.ScalaNotionClient
import notion.api.v1.http.JavaNetHttpClient
import notion.api.v1.model.common.PropertyType
import notion.api.v1.model.databases.query.filter.PropertyFilter
import notion.api.v1.model.databases.query.filter.condition.TextFilter

import scala.jdk.CollectionConverters._

@main def example: Unit = {

  val client = ScalaNotionClient(
    token = System.getenv("NOTION_TOKEN"),
    httpClient = new JavaNetHttpClient()
  )

  val users = client.listUsers(pageSize = 2)

  val databaseId = client
    .listDatabases()
    .getResults
    .asScala
    .find(_.getTitle.get(0).getPlainText == "Test Database")
    .get
    .getId

  val queryResult = client.queryDatabase(
    databaseId = databaseId,
    filter = {
      val filter = new PropertyFilter()
      filter.setProperty(PropertyType.Title)
      filter.setTitle {
        val title = new TextFilter()
        title.setContains("bug")
        title
      }
      filter
    },
    pageSize = 3
  )
}

Plugins

By default, the NotionClient utilizes only JDK's java.net.HttpURLConnection and Gson library for JSON serialization.

For HTTP communications and logging, you can easily switch to other implementations.

Pluggable HTTP Client

As some may know, java.net.HttpURLConnection does not support PATCH request method 😢 . Thus, the default httpClient has to make an "illegal reflective access" to overcome the limitation for perfoming PATCH method requests (see this class for details).

If you use PATH method API calls such as PATCH https://api.notion.com/v1/pages/{page_id}, we recommend other httpClient implementations listed below. If you don't use PATCH method APIs at all and don't want to add any extra dependencies, the default httpClient works fine for you.

// Add this if you use java.net.http.HttpClient in JDK 11+
// Please note that this module does not work on Android runtime
implementation("com.github.seratch:notion-sdk-jvm-httpclient:${notionSdkVersion}")

// Add this if you use OkHttp 5.x (still alpha)
// If you have other dependencies relying on okhttp 5.x (e.g., Retrofit)
implementation("com.github.seratch:notion-sdk-jvm-okhttp5:${notionSdkVersion}")

// Add this if you use OkHttp 4.x
// Although the package name is `okhttp3`, the latest version is 4.x
implementation("com.github.seratch:notion-sdk-jvm-okhttp4:${notionSdkVersion}")

// Add this if you use OkHttp 3.x
// If you have other dependencies relying on okhttp 3.x (e.g., Retrofit)
implementation("com.github.seratch:notion-sdk-jvm-okhttp3:${notionSdkVersion}")

You can switch the httpClient in either of the following ways:

import notion.api.v1.NotionClient
import notion.api.v1.http.JavaNetHttpClient

val client = NotionClient(
    token = System.getenv("NOTION_TOKEN"),
    httpClient = JavaNetHttpClient(),
)

or

import notion.api.v1.NotionClient
import notion.api.v1.http.OkHttp3Client

val client = NotionClient(token = System.getenv("NOTION_TOKEN"))
client.httpClient = OkHttp3Client()

Pluggable Logging

You can change the logger property of a NotionClient instances Currently, this libarary supports its own stdout logger (default), java.util.logging, and slf4j-api based ones. Here are the steps to switch to an slf4j-api logger. Add the following optional module along with your favorite implementation (e.g., logback-classic, slf4j-simple).

implementation("com.github.seratch:notion-sdk-jvm-slf4j:${notionSdkVersion}") // slf4j-api 1.7
implementation("org.slf4j:slf4j-simple:1.7.30")

Now you can switch to your slf4j logger. As with the httpClient example, you can use the setter method too.

import notion.api.v1.NotionClient
import notion.api.v1.http.JavaNetHttpClient
import notion.api.v1.logging.Slf4jLogger

// for slf4j-simple
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug")

val client = NotionClient(
    token = System.getenv("NOTION_TOKEN"),
    httpClient = JavaNetHttpClient(),
    logger = Slf4jLogger(),
)

Why isn't JSON serialization pluggable?

We don't support other JSON libraries yet. There are two reasons:

Necessity of polymorphic serializers for list objects

In the early development stage of this SDK, we started with kotlinx.serialization. It worked well except for the Search API responses. The results returned by the API requires polymorphic serializers for properties: List<DatabaseProperty | PageProperty> (this is a pseudo-code illustrating the property is a list of union type). We could not find a way to handle the pattern with the library at that time.

Easily enabling camelCased property names

We know a few novel Kotlin libraries do not support the conversions between snake_cased keys and camelCased keys. Although we do respect the opinion and see the benefit, we still prefer consistent field naming in the Java world. This is another major reason why we did not go with either of kotlinx.serialization and Moshi.

Supported Java Runtimes

  • OpenJDK 8 or higher
  • All Android runtime versions supported by Kotlin 1.5

As notion-sdk-jvm-httpclient utilizes java.net.http.HttpClient, the module works with JDK 11 and higher versions.

License

The MIT License

Issues
Owner
Kazuhiro Sera
Slack Bolt Framework / SDK Developer
Kazuhiro Sera
Accept PayPal and credit cards in your Android app

Important: PayPal Mobile SDKs are Deprecated. The APIs powering them will remain operational long enough for merchants to migrate, but the SDKs themse

PayPal 783 Jul 23, 2021
AWS SDK for Android. For more information, see our web site:

AWS SDK for Android For new projects, we recommend interacting with AWS using the Amplify Framework. The AWS SDK for Android is a collection of low-le

AWS Amplify 865 Jul 31, 2021
AWS SDK for Android. For more information, see our web site:

AWS SDK for Android For new projects, we recommend interacting with AWS using the Amplify Framework. The AWS SDK for Android is a collection of low-le

AWS Amplify 865 Jul 31, 2021
Qiscus provide everything you need to power up your app with chats. And it's now made simple.

Introduction Qiscus Chat SDK (Software Development Kit) is a product provided by Qiscus that enables you to embed an in-app chat/chat feature in your

Qiscus - Multichannel Conversational Platform 182 Jul 12, 2021
Official Appwrite Android SDK 💚 🤖

Appwrite Android SDK This SDK is compatible with Appwrite server version 0.8.x. For older versions, please check previous releases. Appwrite is an ope

Appwrite 16 Jul 25, 2021
Android Chat SDK built on Firebase

Chat21 is the core of the open source live chat platform Tiledesk.com. Chat21 SDK Documentation Features With Chat21 Android SDK you can: Send a direc

Chat21 211 Jul 16, 2021
Android Real Time Chat & Messaging SDK

Android Chat SDK Overview Applozic brings real-time engagement with chat, video, and voice to your web, mobile, and conversational apps. We power emer

Applozic 635 Jul 28, 2021
Microsoft Services SDKs for Android produced by MS Open Tech.

Important: This preview SDK has been deprecated and is no longer being maintained. We recommend that you use Microsoft Graph and the associated Micros

Office Developer 215 Jul 14, 2021
Evernote SDK for Android

Evernote SDK for Android version 2.0.0-RC4 Evernote API version 1.25 Overview This SDK wraps the Evernote Cloud API and provides OAuth authentication

Evernote 421 Jun 30, 2021
新浪微博 Android SDK

ReadMe 公告: 鉴于线上服务器出现问题,推荐下载本地aar后上传到自己公司的服务器,保证后续服务稳定, 我们也将尽快重新提供一个稳定的地址供大家使用。 新包地址:https://github.com/sinaweibosdk/weibo_android_sdk/tree/master/2019

SinaWeiboSDK 1.7k Jul 29, 2021
Liquid SDK (Android)

Liquid Android SDK Quick Start to Liquid SDK for Android This document is just a quick start introduction to Liquid SDK for Android. We recommend you

Liquid 15 Jul 12, 2017
card.io provides fast, easy credit card scanning in mobile apps

card.io SDK for Android card.io provides fast, easy credit card scanning in mobile apps. Stay up to date Please be sure to keep your app up to date wi

card.io 1.9k Jul 23, 2021
Free forever Marketing SDK with a dashboard for in-app SplashScreen banners with built-in analytics

AdaptivePlus Android SDK AdaptivePlus is the control center for marketing campaigns in mobile applications Requirements minSdkVersion 16 Examples prov

Adaptive.Plus 16 Jun 12, 2021
Countly Product Analytics Android SDK

Countly Android SDK We're hiring: Countly is looking for Android SDK developers, full stack devs, devops and growth hackers (remote work). Click this

Countly Team 633 Aug 2, 2021