Slack SDK for Java

Composing Messages

This section shows how to build Slack messages using slack-api-client library. If you’re not familiar with chat.postMessage API yet, read this page before trying the samples here.

Also, before jumping into Java code, we recommend developing an understanding of composing Slack messages. Read the API documentation for more information.


Text Formatting

Composing a text message is the simplest way to post a message to Slack conversations.

import com.slack.api.Slack;
import com.slack.api.methods.response.chat.ChatPostMessageResponse;

String channelId = "C1234567";
String text = ":wave: Hi from a bot written in Java!";

Slack slack = Slack.getInstance();
String token = System.getenv("SLACK_TOKEN");

ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
  .channel(channelId)
  .text(text)
);

As you see, using text is fairly simple. The only thing to know is to give a string value with a valid format. Consult Basic formatting with mrkdwn for understanding the markup language.


Building Blocks for Rich Message Layouts

Block Kit is a UI framework for Slack apps that offers a balance of control and flexibility when building experiences in messages and other surfaces.

It may not be so easy to compose a large JSON data structure in Java code. So, we offer setter methods like blocksAsString(String) that accept a whole blocks part as a single string value. Such method is supposed to be used with loaded external file data or outcomes by template engines.

ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
  .channel("C1234567")
  .blocksAsString("[{\"type\": \"divider\"}]")
);

This library also offers a type-safe way to build blocks like the one below. Just by having a few static imports, building blocks is much easier, safer, and more readable to everyone.

import static com.slack.api.model.block.Blocks.*;
import static com.slack.api.model.block.composition.BlockCompositions.*;
import static com.slack.api.model.block.element.BlockElements.*;

ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
  .channel("C1234567")
  .blocks(asBlocks(
    section(section -> section.text(markdownText("*Please select a restaurant:*"))),
    divider(),
    actions(actions -> actions
      .elements(asElements(
        button(b -> b.text(plainText(pt -> pt.emoji(true).text("Farmhouse"))).value("v1")),
        button(b -> b.text(plainText(pt -> pt.emoji(true).text("Kin Khao"))).value("v2"))
      ))
    )
  ))
);

You can use this way also for building a message for Incoming Webhooks and response_url calls.


Block Kit Kotlin DSL

If you’re using Kotlin, the Java Slack SDK also provides Kotlin-style builders which you can use to build your Block Kit structures.

import com.slack.api.Slack
import com.slack.api.model.block.Blocks.*
import com.slack.api.methods.kotlin_extension.request.chat.blocks

val slack = Slack.getInstance()
val token = System.getenv("token")
val response = slack.methods(token).chatPostMessage { req -> req
  .channel("C1234567")
  .blocks {
    section {
      // "text" fields can be constructed via `plainText()` and `markdownText()`
      markdownText("*Please select a restaurant:*")
    }
    divider()
    actions {
      // To align with the JSON structure, you could put the `elements { }` block around the buttons but for brevity it can be omitted
      // The same is true for things such as the section block's "accessory" container
      button {
          // For instances where only `plain_text` is acceptable, the field's name can be filled with `plain_text` inputs
          text("Farmhouse", emoji = true)
          value("v1")
      }
      button {
          text("Kin Khao", emoji = true)
          value("v2")
      }
    }
  }
}

Installation

You can add the Block Kit Kotlin DSL via 2 artifacts:

artifactId Description
com.slack.api:slack-api-model-kotlin-extension 📖 The slack-api-model Kotlin extension, which adds the Kotlin DSL itself as well as the standalone withBlocks { } builder and View.ViewBuilder’s .blocks { } extension function.
com.slack.api:slack-api-client-kotlin-extension 📖 The slack-api-client Kotlin extension, which adds the .blocks { } extension function to MethodsClient’s request object builders for seamless use of the DSL with the Java builders such as ChatPostEphemeralRequestBuilder, ChatPostMessageRequestBuilder, ChatScheduleMessageRequestBuilder, and ChatUpdateRequestBuilder.

Adding via Gradle:

dependencies {
  implementation "com.slack.api:slack-api-model-kotlin-extension:1.39.0"
  implementation "com.slack.api:slack-api-client-kotlin-extension:1.39.0"
}

Adding via Gradle Kotlin DSL:

dependencies {
  implementation("com.slack.api:slack-api-model-kotlin-extension:1.39.0")
  implementation("com.slack.api:slack-api-client-kotlin-extension:1.39.0")
}

Notable examples and features

In this section, I’ll share some code snippets demonstrating how to use this DSL.

Standalone withBlocks { } builder which comes with the model extension

You can create lists of blocks outside of the slack-api-client Kotlin extension functions with the withBlocks { } builder.

import com.slack.api.model.kotlin_extension.block.withBlocks

val blocks = withBlocks {
  section {
    plainText("Now this can be passed to anything that requires a list of LayoutBlocks")
  }
}

Type safe enums for inputs which require specific string inputs

Type-safe enums are available for properties of some block elements which require specific input strings.

With this, you get the benefit of verifying your inputs are correct at compile time, and you gain access to Kotlin enum features such as being able to iterate over or retrieve all possible values for these inputs. Versions of these inputs which accept strings are also available, if you prefer.

import com.slack.api.model.kotlin_extension.block.element.ButtonStyle
import com.slack.api.model.kotlin_extension.block.element.ConversationType
import com.slack.api.model.kotlin_extension.block.withBlocks

val blocks = withBlocks { 
  section { 
    plainText("Please select the person or group you would like to send a cat GIF to.")

    // "accessory" is provided here, but it can be omitted for brevity
    accessory { 
      conversationsSelect { 
        // Or alternatively, provide strings via `filter("im", "mpim")` if you'd prefer
        filter(ConversationType.IM, ConversationType.MULTIPARTY_IM)
        placeholder("Where should we send the cat?")
        
        confirm { 
          title("Confirm destination")
          plainText("Are you sure you want to send a cat GIF to this person or group?")
          confirm("Yes, send it")
          deny("Don't send it")
          
          style(ButtonStyle.PRIMARY)
        }
      }
    }
  }
}

Write DSL extension functions for message templating

Because it is a Kotlin DSL, you benefit from Kotlin language features while you are constructing your messages, one of which being able to create extension functions which reproduce common Block Kit structures. This makes your code less repetitive and easier to read. You also benefit from being able to use conditionals and loops as you construct your blocks.

import com.slack.api.model.kotlin_extension.block.ActionsBlockBuilder
import com.slack.api.model.kotlin_extension.block.withBlocks

fun ActionsBlockBuilder.presentOptions(vararg optionNames: String, prompt: String? = null) {
  staticSelect { 
    if (prompt != null) {
      placeholder(prompt)
    }
    
    options {
      for (optionName in optionNames) {
        option {
          plainText(optionName)
          value(optionName.toLowerCase())
        }
      }
    }
  }
}

val blocks = withBlocks { 
  section {
    markdownText("Please select your favorite color.")
  }
  actions {
    presentOptions(
      "Green", "Red", "Blue", "Yellow", "Orange", "Black",
      prompt = "Pick a color..."
    )
  }
}