### Clone and Run Quarkus Example Source: https://github.com/slackapi/java-slack-sdk/blob/main/bolt-quarkus-examples/README.md Steps to clone the repository, install dependencies, and run the Quarkus example in development mode. Includes setting up ngrok for external access. ```bash git clone git@github.com:slackapi/java-slack-sdk.git cd java-slack-sdk/ mvn install -Dmaven.test.skip=true mvn -pl bolt-quarkus-examples compile quarkus:dev ngrok http 3000 ``` -------------------------------- ### Maven Command to Run Example Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-client-setup.md Execute this command in your terminal to compile and run the Example.main method, verifying your installation. ```bash mvn compile exec:java \ -Dexec.cleanupDaemonThreads=false \ -Dexec.mainClass="Example" ``` -------------------------------- ### Initialize and Start Socket Mode App with Java-WebSocket Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/socket-mode.md This example demonstrates how to initialize a SocketModeApp using the Java-WebSocket backend and start the connection. Ensure the Java-WebSocket library is added as a dependency. ```java String appToken = "xapp-"; App app = new App(); SocketModeApp socketModeApp = new SocketModeApp( appToken, SocketModeClient.Backend.JavaWebSocket, app ); socketModeApp.start(); ``` -------------------------------- ### Install and Run Slack API Client Tests Source: https://github.com/slackapi/java-slack-sdk/blob/main/AGENTS.md Installs all modules locally and then runs specific tests for the slack-api-client module. Note that failures in unrelated modules during installation are acceptable. ```bash ./scripts/install_local.sh ``` ```bash ./mvnw test -pl slack-api-client '-Dtest=test_locally.api.methods.AppsTest,test_locally.api.MethodsTest' ``` -------------------------------- ### Helidon App Startup Output Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Example output from the `stdout` when the Helidon SE Bolt app starts successfully, indicating the server and Bolt app are running. ```bash [main] io.helidon.webserver.NettyWebServer Version: helidonVersion [nioEventLoopGroup-2-1] io.helidon.webserver.NettyWebServer Channel '@default' started: [id: 0x9fcf416d, L:/0:0:0:0:0:0:0:0:3000] [nioEventLoopGroup-2-1] com.slack.api.bolt.helidon.SlackAppServer ⚡️ Bolt app is running! ``` -------------------------------- ### Build Quarkus Example JAR Source: https://github.com/slackapi/java-slack-sdk/blob/main/bolt-quarkus-examples/README.md Instructions to package the Quarkus Bolt example into an executable JAR file and run it. ```bash mvn -pl bolt-quarkus-examples package java -jar bolt-quarkus-examples/target/bolt-quarkus-examples-*-runner.jar ``` -------------------------------- ### Configure Custom Installation and OAuth Services Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-distribution.md Implement custom `InstallationService` and `OAuthStateService` using Spring Beans, for example, by leveraging Amazon S3 for storage. This allows for more control over how installation data and OAuth states are managed. ```java public class SlackApp { // Please be careful about the security policies on this bucket. private static final String S3_BUCKET_NAME = "your-s3-bucket-name"; @Bean public InstallationService initInstallationService() { InstallationService installationService = new AmazonS3InstallationService(S3_BUCKET_NAME); installationService.setHistoricalDataEnabled(true); return installationService; } @Bean public OAuthStateService initStateService() { return new AmazonS3OAuthStateService(S3_BUCKET_NAME); } @Bean public App initSlackApp(InstallationService installationService, OAuthStateService stateService) { App app = new App().asOAuthApp(true); app.service(installationService); app.service(stateService); return app; } } ``` -------------------------------- ### Logback configuration example Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/bolt-basics.md Example XML configuration for logback-classic to set up logging appenders and root level. ```xml %date %level [%thread] %logger{64} %msg%n ``` -------------------------------- ### Bolt App with API and OAuth Handlers Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-distribution.md This example demonstrates setting up a Bolt app to handle both standard Slack API requests (like commands) and the OAuth flow for app installation. Ensure all required environment variables are set for each app instance. ```java import com.slack.api.bolt.App; import com.slack.api.bolt.jetty.SlackAppServer; import java.util.HashMap; import java.util.Map; import static java.util.Map.entry; // API Request Handler App // expected env variables: // SLACK_SIGNING_SECRET App apiApp = new App(); apiApp.command("/hi", (req, ctx) -> { return ctx.ack("Hi there!"); }); // OAuth Flow Handler App // expected env variables: // SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_REDIRECT_URI, SLACK_SCOPES, // SLACK_INSTALL_PATH, SLACK_REDIRECT_URI_PATH // SLACK_OAUTH_COMPLETION_URL, SLACK_OAUTH_CANCELLATION_URL App oauthApp = new App().asOAuthApp(true); // Mount the two apps with their root path SlackAppServer server = new SlackAppServer(new HashMap<>(Map.ofEntries( entry("/slack/events", apiApp), // POST /slack/events (incoming API requests from the Slack Platform) entry("/slack/oauth", oauthApp) // GET /slack/oauth/start, /slack/oauth/callback (user access) ))); server.start(); // http://localhost:3000 ``` -------------------------------- ### Install Slack API Client Modules Locally Source: https://github.com/slackapi/java-slack-sdk/blob/main/AGENTS.md Before running tests, install all modules locally using `mvn install` to ensure dependencies are met, especially when `slack-api-client` depends on `slack-api-model`. ```bash mvn install ``` -------------------------------- ### Java RTM Client Example Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/rtm.md This example demonstrates initializing the RTM client, connecting to Slack, handling events, sending messages, and managing the WebSocket connection. It requires a `SLACK_BOT_TOKEN` environment variable. ```java import com.slack.api.Slack; import com.slack.api.model.event.UserTypingEvent; import com.slack.api.rtm.*; import com.slack.api.rtm.message.*; // Dispatches incoming message events from RTM API RTMEventsDispatcher dispatcher = RTMEventsDispatcherFactory.getInstance(); // Register a event handler runtime RTMEventHandler userTyping = new RTMEventHandler() { @Override public void handle(UserTypingEvent event) { // do something here } }; dispatcher.register(userTyping); String botToken = System.getenv("SLACK_BOT_TOKEN"); Slack slack = Slack.getInstance(); // Initialize the client with a valid WSS URL RTMClient rtm = slack.rtmConnect(botToken); // Establish a WebSocket connection and start subscribing Slack events rtm.connect(); // Enable an event dispatcher rtm.addMessageHandler(dispatcher.toMessageHandler()); // Deregister a event handler runtime dispatcher.deregister(userTyping); // Send messages over a WebSocket connection String channelId = "C1234567"; String message = Message.builder().id(1234567L).channel(channelId).text(":wave: Hi there!").build().toJSONString(); rtm.sendMessage(message); // To subscribe "presence_change" events String userId = "U1234567"; String presenceQuery = PresenceQuery.builder().ids(Arrays.asList(userId)).build().toJSONString(); rtm.sendMessage(presenceQuery); String presenceSub = PresenceSub.builder().ids(Arrays.asList(userId)).build().toJSONString(); rtm.sendMessage(presenceSub); // A bit heavy-weight operation to re-establish a WS connection for sure // Don't call this method frequently - it will result in a rate-limited error rtm.reconnect(); // Disconnect from Slack - #close() method does the same rtm.disconnect(); ``` -------------------------------- ### Install all modules locally Source: https://github.com/slackapi/java-slack-sdk/blob/main/AGENTS.md Install all project modules into the local Maven repository, skipping tests. ```bash # Install all modules locally (skips tests) ./scripts/install_local.sh ``` -------------------------------- ### Initialize Slack SDK Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md Instantiate the Slack SDK with default configuration. This is the starting point for all SDK operations. ```java import com.slack.api.Slack; import com.slack.api.SlackConfig; SlackConfig config = new SlackConfig(); Slack slack = Slack.getInstance(config); ``` -------------------------------- ### Start Micronaut Application Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Command to start your Micronaut application using Maven. ```bash [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1321ms. Server Running: http://localhost:3000 ``` -------------------------------- ### Configure App and Handle Slash Command Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/bolt-basics.md Initialize the `App` class and register a handler for a slash command. This is a basic setup for responding to user commands. ```java import com.slack.api.bolt.App; App app = new App(); app.command("/echo", (req, ctx) -> { return ctx.ack(req.getText()); }); ``` -------------------------------- ### Quarkus Development Mode Output Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Example stdout output when a Quarkus application starts in development mode, indicating successful startup and enabled features. ```text [INFO] --- quarkus-maven-plugin:quarkusVersion:dev (default-cli) @ code-with-quarkus --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /path-to-projet/target/classes Listening for transport dt_socket at address: 5005 __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ INFO [io.quarkus] (main) code-with-quarkus 1.0.0-SNAPSHOT (powered by Quarkus quarkusVersion)) started in 0.846s. Listening on: http://0.0.0.0:3000 INFO [io.quarkus] (main) Profile dev activated. Live Coding activated. INFO [io.quarkus] (main) Installed features: [cdi, servlet] ``` -------------------------------- ### Initialize Slack App with Spring Boot Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-distribution.md Configure and initialize the Slack App within a Spring Boot application. Ensure you call `asOAuthApp(true)` to enable OAuth functionality. This setup includes defining servlets for Slack events, installation, and OAuth redirects. ```java package hello; // export SLACK_SIGNING_SECRET=xxx // export SLACK_CLIENT_ID=111.222 // export SLACK_CLIENT_SECRET=xxx // export SLACK_SCOPES=commands,chat:write.public,chat:write // export SLACK_USER_SCOPES= // export SLACK_INSTALL_PATH=/slack/install // export SLACK_REDIRECT_URI_PATH=/slack/oauth_redirect // export SLACK_OAUTH_COMPLETION_URL=https://www.example.com/completion // export SLACK_OAUTH_CANCELLATION_URL=https://www.example.com/cancellation import com.slack.api.bolt.App; import javax.servlet.annotation.WebServlet; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SlackApp { @Bean public App initSlackApp() { App app = new App().asOAuthApp(true); // Do not forget calling `asOAuthApp(true)` here app.command("/hello-oauth-app", (req, ctx) -> { return ctx.ack("What's up?"); }); return app; } } import com.slack.api.bolt.servlet.SlackAppServlet; import com.slack.api.bolt.servlet.SlackOAuthAppServlet; @WebServlet("/slack/events") public class SlackEventsController extends SlackAppServlet { public SlackEventsController(App app) { super(app); } } @WebServlet("/slack/install") public class SlackOAuthInstallController extends SlackOAuthAppServlet { public SlackOAuthInstallController(App app) { super(app); } } @WebServlet("/slack/oauth_redirect") public class SlackOAuthRedirectController extends SlackOAuthAppServlet { public SlackOAuthRedirectController(App app) { super(app); } } ``` -------------------------------- ### Java Example for Maven Verification Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-client-setup.md Create this Java class with a main method to verify your Maven build settings. Run it using the provided Maven command. ```java import com.slack.api.Slack; import com.slack.api.methods.response.api.ApiTestResponse; public class Example { public static void main(String[] args) throws Exception { Slack slack = Slack.getInstance(); ApiTestResponse response = slack.methods().apiTest(r -> r.foo("bar")); System.out.println(response); } } ``` -------------------------------- ### Start Bolt App with HTTP in Kotlin Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/getting-started-with-bolt.md This is a minimal Kotlin `main` function to start a Bolt app using HTTP with the embedded Jetty server. Replace `// Write some code here` with your app's event listeners and middleware. ```kotlin import com.slack.api.bolt.App import com.slack.api.bolt.jetty.SlackAppServer fun main() { val app = App() // Write some code here val server = SlackAppServer(app) server.start() // http://localhost:3000/slack/events } ``` -------------------------------- ### Initialize and Start Slack App with Helidon Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md This Java code initializes a Slack Bolt App and starts it using the Helidon web server. It includes configuration for metrics and health checks. ```java package hello; import com.slack.api.bolt.App; import com.slack.api.bolt.helidon.SlackAppServer; import com.slack.api.model.event.AppMentionEvent; import io.helidon.health.HealthSupport; import io.helidon.health.checks.HealthChecks; import io.helidon.metrics.MetricsSupport; public final class Main { public static void main(final String[] args) { startServer(); } public static SlackAppServer startServer() { SlackAppServer server = new SlackAppServer(apiApp(), oauthApp()); // If you add more settings to Routing, overwrite this configurator server.setAdditionalRoutingConfigurator(builder -> builder .register(MetricsSupport.create()) .register(HealthSupport.builder().addLiveness(HealthChecks.healthChecks()).build())); server.start(); return server; } // POST /slack/events - this path is configurable with bolt.apiPath in application.yaml public static App apiApp() { App app = new App(); app.event(AppMentionEvent.class, (event, ctx) -> { ctx.say("May I help you?"); return ctx.ack(); }); return app; } } ``` -------------------------------- ### Boot Spring Boot Application Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Command to start your Spring Boot application using Gradle. ```bash $ gradle bootRun ``` -------------------------------- ### Initialize Slack Object Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md Instantiate the main Slack client object. This is the starting point for accessing all other API clients. ```java import com.slack.api.Slack; Slack slack = Slack.getInstance(); ``` -------------------------------- ### Manage Users with SCIM API in Java Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/scim-api.md Provides examples for common user management operations: searching, reading, creating, filtering, and deleting users. Ensure you have the necessary scopes and user IDs. ```java import com.slack.api.Slack; import com.slack.api.scim.*; import com.slack.api.scim.model.*; import com.slack.api.scim.response.*; // Search Users UsersSearchResponse users = slack.scim(token).searchUsers(req -> req.count(1000)); // Read a User final String userId = users.getResources().get(0).getId(); UsersReadResponse read = slack.scim(token).readUser(req -> req.id(userId)); // Pagination for Users UsersSearchResponse users = slack.scim(token).searchUsers(req -> req.count(1).startIndex(2)); users.getItemsPerPage(); // 1 users.getResources().size(); // 1 users.getStartIndex(); // 2 // Create a new User User newUser = new User(); newUser.setName(new User.Name()); newUser.getName().setGivenName("Kazuhiro"); newUser.getName().setFamilyName("Sera"); // set other fields as well... UsersCreateResponse creation = slack.scim(token).createUser(req -> req.user(newUser)); // Run a filter query for user search // /admins/scim-api UsersSearchResponse searchResp = slack.scim(token).searchUsers(req -> req .count(1) .filter("userName eq \"" + userName + "\"") ); // Delete a User UsersDeleteResponse deletion = slack.scim(token).deleteUser(req -> req.id(userId)); ``` -------------------------------- ### Assistant Simple App Java Example Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/ai-apps.md This Java code sets up a Slack Bolt application with Assistant middleware to handle user messages, file uploads, and thread interactions. It requires SLACK_BOT_TOKEN and SLACK_APP_TOKEN environment variables. ```java package samples; import com.slack.api.bolt.App; import com.slack.api.bolt.AppConfig; import com.slack.api.bolt.middleware.builtin.Assistant; import com.slack.api.bolt.socket_mode.SocketModeApp; import com.slack.api.model.assistant.SuggestedPrompt; import com.slack.api.model.event.AppMentionEvent; import com.slack.api.model.event.MessageEvent; import java.util.Arrays; import java.util.Collections; public class AssistantSimpleApp { public static void main(String[] args) throws Exception { String botToken = System.getenv("SLACK_BOT_TOKEN"); String appToken = System.getenv("SLACK_APP_TOKEN"); App app = new App(AppConfig.builder().singleTeamBotToken(botToken).build()); Assistant assistant = new Assistant(app.executorService()); assistant.threadStarted((req, ctx) -> { try { ctx.say("Hi, how can I help you today?"); ctx.setSuggestedPrompts(r -> r .title("Select one of the following:") // optional .prompts(Collections.singletonList(SuggestedPrompt.create("What does SLACK stand for?"))) ); } catch (Exception e) { ctx.logger.error("Failed to handle assistant thread started event: {e}", e); } }); assistant.userMessage((req, ctx) -> { try { // ctx.setStatus(r -> r.status("is typing...")); works too ctx.setStatus("is typing..."); Thread.sleep(500L); if (ctx.getThreadContext() != null && ctx.getThreadContext().getChannelId() != null) { String contextChannel = ctx.getThreadContext().getChannelId(); ctx.say("I am aware of the channel context: <#" + contextChannel + ">"); } else { ctx.say("Here you are!"); } } catch (Exception e) { ctx.logger.error("Failed to handle assistant user message event: {e}", e); try { ctx.say(":warning: Sorry, something went wrong during processing your request!"); } catch (Exception ee) { ctx.logger.error("Failed to inform the error to the end-user: {ee}", ee); } } }); assistant.userMessageWithFiles((req, ctx) -> { try { ctx.setStatus("is downloading the files..."); Thread.sleep(500L); ctx.setStatus("is analyzing the files...", Arrays.asList("Reading bytes...", "Confirming hashes...")); Thread.sleep(500L); ctx.say("Your files do not have any issues!"); } catch (Exception e) { ctx.logger.error("Failed to handle assistant user message event: {e}", e); try { ctx.say(":warning: Sorry, something went wrong during processing your request!"); } catch (Exception ee) { ctx.logger.error("Failed to inform the error to the end-user: {ee}", ee); } } }); app.use(assistant); app.event(MessageEvent.class, (req, ctx) -> { return ctx.ack(); }); app.event(AppMentionEvent.class, (req, ctx) -> { ctx.say("I can help you at our 1:1 DM!"); return ctx.ack(); }); new SocketModeApp(appToken, app).start(); } } ``` -------------------------------- ### HTTP Java App Entry Point Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/getting-started-with-bolt.md This Java code sets up a Bolt app to run with an HTTP server using bolt-jetty. It initializes the App, registers a command handler, and starts the SlackAppServer, which listens on port 3000 by default. It requires SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET environment variables. ```java package hello; import com.slack.api.bolt.App; // If you use bolt-jakarta-jetty, you can import `com.slack.api.bolt.jakarta_jetty.SlackAppServer` instead import com.slack.api.bolt.jetty.SlackAppServer; public class MyApp { public static void main(String[] args) throws Exception { // App expects env variables (SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET) App app = new App(); app.command("/hello", (req, ctx) -> { return ctx.ack(":wave: Hello!"); }); SlackAppServer server = new SlackAppServer(app); server.start(); // http://localhost:3000/slack/events } } ``` -------------------------------- ### Example Section Block with External Select Menu Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/interactive-components.md Shows the JSON structure for a 'section' block featuring an 'multi_external_select' accessory, used for selecting topics. ```json { "block_id": "topics", "type": "section", "text": { "type": "mrkdwn", "text": "Select the meeting topics" }, "accessory": { "action_id": "topics-action", "type": "multi_external_select", "min_query_length": 1, "placeholder": { "type": "plain_text", "text": "Select", "emoji": true } } } ``` -------------------------------- ### Initialize Bolt App and Register Event Listener Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/socket-mode.md Initialize an App instance and register listeners for events. This setup is the same for both HTTP and Socket Mode. Ensure the SLACK_BOT_TOKEN environment variable is set. ```java import com.slack.api.bolt.App; import com.slack.api.bolt.AppConfig; import com.slack.api.model.event.AppMentionEvent; // The bot token that starts with xoxb- is NOT the app-level token. // The token here is the one you got by installing the app into a workspace String botToken = System.getenv("SLACK_BOT_TOKEN"); AppConfig appConfig = AppConfig.builder().singleTeamBotToken(botToken).build(); // If you go with the default constructor, the App initialization requires an env variable named SLACK_BOT_TOKEN. App app = new App(appConfig); app.event(AppMentionEvent.class, (req, ctx) -> { ctx.say("Hi there!"); return ctx.ack(); }); ``` -------------------------------- ### Publish App Home Tab View (Kotlin) Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-home.md This Kotlin code achieves the same functionality as the Java example, publishing an App Home tab view upon receiving the `app_home_opened` event. It utilizes Kotlin's syntax for building views and includes race condition protection using the view's hash. ```kotlin // static imports import com.slack.api.model.block.Blocks.* import com.slack.api.model.block.composition.BlockCompositions.* import com.slack.api.model.view.Views.* import com.slack.api.model.event.AppHomeOpenedEvent import java.time.ZonedDateTime // /reference/events/app_home_opened app.event(AppHomeOpenedEvent::class.java) { event, ctx -> // Build a Home tab view val now = ZonedDateTime.now() val appHomeView = view { it.type("home") .blocks(asBlocks( section { section -> section.text(markdownText { mt -> mt.text(":wave: Hello, App Home! (Last updated: ${now})") }) }, image { img -> img.imageUrl("https://www.example.com/foo.png").altText("alt text for image") } )) } // Update the App Home for the given user val res = ctx.client().viewsPublish { it.userId(event.event.user) .hash(event.event.view?.hash) // To protect against possible race conditions .view(appHomeView) } ctx.ack() } ``` -------------------------------- ### Configure Redis Metrics Datastore Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md Use this snippet to configure a Redis-backed datastore for collecting metrics across nodes. Ensure Redis is installed and running. ```java import com.slack.api.Slack; import com.slack.api.SlackConfig; import com.slack.api.methods.metrics.RedisMetricsDatastore; import redis.clients.jedis.JedisPool; SlackConfig config = new SlackConfig(); // brew install redis // redis-server /usr/local/etc/redis.conf --loglevel verbose JedisPool jedis = new JedisPool("localhost"); config.getMethodsConfig().setMetricsDatastore(new RedisMetricsDatastore("test", jedis)); Slack slack = Slack.getInstance(config); ``` -------------------------------- ### Configure Amazon S3 Storage for Bolt Apps Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-distribution.md Demonstrates setting up Amazon S3 for both installation and OAuth state services in a Bolt application. Ensure AWS credentials and bucket name are correctly configured. ```java import com.slack.api.bolt.App; import com.slack.api.bolt.jetty.SlackAppServer; import com.slack.api.bolt.service.InstallationService; import com.slack.api.bolt.service.OAuthStateService; import com.slack.api.bolt.service.builtin.AmazonS3InstallationService; import com.slack.api.bolt.service.builtin.AmazonS3OAuthStateService; import java.util.HashMap; import java.util.Map; import static java.util.Map.entry; // The standard AWS env variables are expected // export AWS_REGION=us-east-1 // export AWS_ACCESS_KEY_ID=AAAA************* // export AWS_SECRET_ACCESS_KEY=4o7*********************** // Please be careful about the security policies on this bucket. String awsS3BucketName = "YOUR_OWN_BUCKET_NAME_HERE"; InstallationService installationService = new AmazonS3InstallationService(awsS3BucketName); // Set true if you'd like to store every single installation as a different record installationService.setHistoricalDataEnabled(true); // apiApp uses only InstallationService to access stored tokens App apiApp = new App(); apiApp.command("/hi", (req, ctx) -> { return ctx.ack("Hi there!"); }); apiApp.service(installationService); // Needless to say, oauthApp uses InstallationService // In addition, it uses OAuthStateService to create/read/delete state parameters App oauthApp = new App().asOAuthApp(true); oauthApp.service(installationService); // Store valid state parameter values in Amazon S3 storage OAuthStateService stateService = new AmazonS3OAuthStateService(awsS3BucketName); // This service is necessary only for OAuth flow apps oauthApp.service(stateService); // Mount the two apps with their root path SlackAppServer server = new SlackAppServer(new HashMap<>(Map.ofEntries( entry("/slack/events", apiApp), // POST /slack/events (incoming API requests from the Slack Platform) entry("/slack/oauth", oauthApp) // GET /slack/oauth/start, /slack/oauth/callback (user access) ))); server.start(); // http://localhost:3000 ``` -------------------------------- ### Initialize SocketModeApp Adapter Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/socket-mode.md Initialize the SocketModeApp adapter using an app-level token and your configured Bolt app. The `start()` method establishes a WebSocket connection and blocks the current thread. ```java import com.slack.api.bolt.socket_mode.SocketModeApp; // Note: If you use bolt-jakarta-socket-mode instead, the import would be: // import com.slack.api.bolt.jakarta_socket_mode.SocketModeApp; // the app-level token with `connections:write` scope String appToken = System.getenv("SLACK_APP_TOKEN"); // Initialize the adapter for Socket Mode // with an app-level token and your Bolt app with listeners. SocketModeApp socketModeApp = new SocketModeApp(appToken, app); // #start() method establishes a new WebSocket connection and then blocks the current thread. // If you do not want to block this thread, use #startAsync() instead. socketModeApp.start(); ``` -------------------------------- ### Publish App Home Tab View (Java) Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-home.md Call `views.publish` to update a user's Home tab when the `app_home_opened` event is received. This example builds a simple view with a welcome message and an image. It includes logic to use the view's hash for race condition protection if a view already exists. ```java import com.slack.api.methods.response.views.ViewsPublishResponse; import com.slack.api.model.event.AppHomeOpenedEvent; import com.slack.api.model.view.View; import java.time.ZonedDateTime; import static com.slack.api.model.block.Blocks.*; import static com.slack.api.model.block.composition.BlockCompositions.*; import static com.slack.api.model.view.Views.*; // /reference/events/app_home_opened app.event(AppHomeOpenedEvent.class, (payload, ctx) -> { // Build a Home tab view ZonedDateTime now = ZonedDateTime.now(); View appHomeView = view(view -> view .type("home") .blocks(asBlocks( section(section -> section.text(markdownText(mt -> mt.text(":wave: Hello, App Home! (Last updated: " + now + ")")))), image(img -> img.imageUrl("https://www.example.com/foo.png").altText("alt text for image")) )) ); // Update the App Home for the given user if (payload.getEvent().getView() == null) { ViewsPublishResponse res = ctx.client().viewsPublish(r -> r .userId(payload.getEvent().getUser()) .view(appHomeView) ); } else { ViewsPublishResponse res = ctx.client().viewsPublish(r -> r .userId(payload.getEvent().getUser()) .hash(payload.getEvent().getView().getHash()) // To safeguard against potential race conditions .view(appHomeView) ); } return ctx.ack(); }); ``` -------------------------------- ### Helidon SE Application Configuration Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Configure Helidon SE applications using `application.yml`. This example sets the server port and host, and defines the API path for Slack events. ```yaml server: port: 3000 host: 0.0.0.0 bolt: apiPath: /slack/events ``` -------------------------------- ### Handle Block Kit Interactions in Assistant Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/ai-apps.md Configure an app to handle Block Kit button clicks within an assistant thread. This example demonstrates setting up the Assistant middleware to ignore self-messages and respond to button actions with metadata. ```java App app = new App(AppConfig.builder() .singleTeamBotToken(System.getenv("SLACK_BOT_TOKEN")) .ignoringSelfAssistantMessageEventsEnabled(false) .build()); Assistant assistant = new Assistant(app.executorService()); assistant.threadStarted((req, ctx) -> { try { ctx.say(r -> r .text("Hi, how can I help you today?") .blocks(Arrays.asList( section(s -> s.text(plainText("Hi, how can I help you today?"))), actions(a -> a.elements(Collections.singletonList( button(b -> b.actionId("assistant-generate-numbers").text(plainText("Generate numbers"))) ))) )) ); } catch (Exception e) { ctx.logger.error("Failed to handle assistant thread started event: {e}", e); } }); app.blockAction("assistant-generate-numbers", (req, ctx) -> { app.executorService().submit(() -> { Map eventPayload = new HashMap<>(); eventPayload.put("num", 20); try { ctx.client().chatPostMessage(r -> r .channel(req.getPayload().getChannel().getId()) .threadTs(req.getPayload().getMessage().getThreadTs()) .text("OK, I will generate numbers for you!") .metadata(new Message.Metadata("assistant-generate-numbers", eventPayload)) ); } catch (Exception e) { ctx.logger.error("Failed to post a bot message: {e}", e); } }); return ctx.ack(); }); assistant.botMessage((req, ctx) -> { if (req.getEvent().getMetadata() != null && req.getEvent().getMetadata().getEventType().equals("assistant-generate-numbers")) { try { ctx.setStatus("is typing..."); Double num = (Double) req.getEvent().getMetadata().getEventPayload().get("num"); Set numbers = new HashSet<>(); SecureRandom random = new SecureRandom(); while (numbers.size() < num) { numbers.add(String.valueOf(random.nextInt(100))); } Thread.sleep(1000L); ctx.say(r -> r.text("Her you are: " + String.join(", ", numbers))); } catch (Exception e) { ctx.logger.error("Failed to handle assistant bot message event: {e}", e); } } }); assistant.userMessage((req, ctx) -> { try { ctx.setStatus("is typing..."); ctx.say(r -> r.text("Sorry, I couldn't understand your comment.")); } catch (Exception e) { ctx.logger.error("Failed to handle assistant user message event: {e}", e); try { ctx.say(r -> r.text(":warning: Sorry, something went wrong during processing your request!")); } catch (Exception ee) { ctx.logger.error("Failed to inform the error to the end-user: {ee}", ee); } } }); app.assistant(assistant); ``` -------------------------------- ### Initialize SCIM Client in Java Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/scim-api.md Demonstrates how to create an SCIM client instance using the slack-api-client library. Requires an admin access token with the 'admin' scope. ```java import com.slack.api.Slack; import com.slack.api.scim.*; Slack slack = Slack.getInstance(); String token = System.getenv("SLACK_ADMIN_ACCESS_TOKN"); // `admin` scope required SCIMClient scim = slack.scim(token); ``` -------------------------------- ### Import jSlack Classes and Initialize Slack Instance Source: https://github.com/slackapi/java-slack-sdk/wiki/Getting-Started-with-groovysh After resolving dependencies, import necessary jSlack classes and create an instance of the Slack client. ```groovy :i com.github.seratch.jslack.* slack = Slack.getInstance() ``` -------------------------------- ### Start Bolt App with Socket Mode in Kotlin Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/getting-started-with-bolt.md This is a minimal Kotlin `main` function to start a Bolt app using Socket Mode. Replace `// Write some code here` with your app's event listeners and middleware. ```kotlin import com.slack.api.bolt.App import com.slack.api.bolt.socket_mode.SocketModeApp fun main() { val app = App() // Write some code here SocketModeApp(app).start() } ``` -------------------------------- ### Initialize Audit Client in Java Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/audit-logs-api.md Instantiate the Slack client and obtain an AuditClient instance using an admin access token. Ensure the token has the `auditlogs:read` scope. ```java import com.slack.api.Slack; import com.slack.api.audit.*; Slack slack = Slack.getInstance(); String token = System.getenv("SLACK_ADMIN_ACCESS_TOKN"); // `auditlogs:read` scope required AuditClient audit = slack.audit(token); ``` -------------------------------- ### Start Embedded Jetty Web Server for OAuth Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/socket-mode.md Start an embedded Jetty web server to handle OAuth flows for a distributed Slack application. This server runs in the current process and can be used alongside Socket Mode. ```java import com.slack.api.bolt.jetty.SlackAppServer; import java.util.HashMap; import java.util.Map; Map apps = new HashMap<>(); apps.put("/slack/", new App(appConfig).asOAuthApp(true)); SlackAppServer oauthSever = new SlackAppServer(apps); // Block the current thread oauthSever.start(); // Access the OAuth URL - https://{your public domain}/slack/install ``` -------------------------------- ### Start Socket Mode App Asynchronously Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/socket-mode.md Start the Socket Mode app in a new thread without blocking the main thread. This is useful for distributed applications where other processes, like a web server, need to run concurrently. ```java import com.slack.api.bolt.socket_mode.SocketModeApp; // Note: If you use bolt-jakarta-socket-mode instead, the import would be: // import com.slack.api.bolt.jakarta_socket_mode.SocketModeApp; String appToken = "xapp-1-A111-111-xxx"; SocketModeApp socketModeApp = new SocketModeApp(appToken, app); // This does not block the current thread socketModeApp.startAsync(); ``` -------------------------------- ### Build App Home View with Block Kit Kotlin DSL Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/app-home.md Demonstrates how to construct an App Home view using the Block Kit Kotlin DSL. This provides a more concise and idiomatic way to define Block Kit UI elements in Kotlin. ```kotlin // These imports are necessary for this code import com.slack.api.model.kotlin_extension.view.blocks import com.slack.api.model.view.Views.view val appHomeView = view { it .type("home") .blocks { section { markdownText(":wave: Hello, App Home! (Last updated: ${now}") } image { imageUrl("https://www.example.com/foo.png") } } } ``` -------------------------------- ### Search Users with AsyncSCIMClient Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/scim-api.md Demonstrates how to use the `AsyncSCIMClient` to search for users, respecting rate limits. Ensure you have an organization admin user token. ```java import com.slack.api.Slack; import com.slack.api.scim.response.*; import java.util.concurrent.CompletableFuture; Slack slack = Slack.getInstance(); String token = "xoxp-***"; // Org admin user token CompletableFuture users = slack.scimAsync(token).searchUsers(req -> req .startIndex(1) .count(100) .filter("userName Eq \"Carly\"") ); ``` -------------------------------- ### Start groovysh Shell Source: https://github.com/slackapi/java-slack-sdk/wiki/Getting-Started-with-groovysh Invoke the groovysh interactive shell. The JVM option for logging is optional but helpful for debugging. ```bash $ groovysh -Dorg.slf4j.simpleLogger.defaultLogLevel=debug Groovy Shell (2.4.7, JVM: 1.8.0_71) Type ':help' or ':h' for help. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ groovy:000> ``` -------------------------------- ### Example Actions Block Payload Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/interactive-components.md Illustrates the JSON payload structure for an 'actions' block containing a button element. ```json { "type": "actions", "elements": [{ "type": "button", "action_id": "button-action", "text": { "type": "plain_text", "text": "Button", "emoji": true }, "value": "button's value" }] } ``` -------------------------------- ### Run Simple App with Gradle Source: https://github.com/slackapi/java-slack-sdk/blob/main/bolt-spring-boot-examples/spring-boot-2/README.md Use Gradle to build and run your simple Bolt application after setting the necessary environment variables. ```bash ./gradlew bootRun ``` -------------------------------- ### Quarkus Hot Reload Output Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Example stdout output during hot-reloading in Quarkus development mode, showing recompilation and restart messages. ```text INFO [io.qua.dev] (vert.x-worker-thread-0) Changed source files detected, recompiling [/path-to-project/src/main/java/hello/SlackApp.java] INFO [io.quarkus] (vert.x-worker-thread-0) Quarkus stopped in 0.001s __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ INFO [io.quarkus] (vert.x-worker-thread-0) code-with-quarkus 1.0.0-SNAPSHOT (powered by Quarkus quarkusVersion) started in 0.021s. Listening on: http://0.0.0.0:3000 INFO [io.quarkus] (vert.x-worker-thread-0) Profile dev activated. Live Coding activated. INFO [io.quarkus] (vert.x-worker-thread-0) Installed features: [cdi, servlet] INFO [io.qua.dev] (vert.x-worker-thread-0) Hot replace total time: 0.232s ``` -------------------------------- ### Acknowledge a Command Request Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/bolt-basics.md Always acknowledge incoming requests using `ctx.ack()`. This example shows a basic acknowledgment for a slash command. ```java app.command("/hello", (req, ctx) -> { // ctx: Context return ctx.ack(); // empty body, that means your bot won't post a reply this time }); ``` -------------------------------- ### Build Slack SDK from Source (Bash) Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-client-setup.md Clone the Slack Java SDK repository and build it using Maven. This makes the SDK modules available in your local Maven repository. ```bash git clone git@github.com:slackapi/java-slack-sdk.git cd java-slack-sdk mvn install -Dmaven.test.skip=true ``` -------------------------------- ### Disable Traffic Metrics Globally Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md Configure the Slack SDK to disable all traffic metrics collection. This can be done during the initial `SlackConfig` setup. ```java SlackConfig config = new SlackConfig(); config.setStatsEnabled(false); Slack slack = Slack.getInstance(config); ``` -------------------------------- ### Deploy Bolt App to Google Cloud Run Source: https://github.com/slackapi/java-slack-sdk/blob/main/bolt-docker-examples/echo-command-app/README.md Set up Google Cloud project and Slack environment variables. Build and upload the Docker image to Google Container Registry, then deploy it to Cloud Run with specified environment variables and region. ```bash export GCLOUD_PROJECT_ID={something-great-12345} export SLACK_SIGNING_SECRET={abcabcabcabcabcbabc} export SLACK_BOT_TOKEN={xoxb-1234123412-123412341212-abcabcabc} # Build and upload a Docker image gcloud config set project ${GCLOUD_PROJECT_ID} gcloud builds submit --tag gcr.io/${GCLOUD_PROJECT_ID}/hello-bolt # Deploy the image to Cloud Run gcloud config set run/region asia-northeast1 # set your region here gcloud beta run deploy hello-bolt \ --image gcr.io/${GCLOUD_PROJECT_ID}/hello-bolt \ --platform managed \ --allow-unauthenticated \ --update-env-vars \ SLACK_SIGNING_SECRET=${SLACK_SIGNING_SECRET},\nSLACK_BOT_TOKEN=${SLACK_BOT_TOKEN} ``` -------------------------------- ### Run No-Prep CI Tests for Java Slack SDK Source: https://github.com/slackapi/java-slack-sdk/blob/main/AGENTS.md Executes CI tests without requiring any preparation steps. This is the recommended approach for development. ```bash ./scripts/run_no_prep_tests.sh ``` -------------------------------- ### Slack Web API Success Response Example Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md A typical JSON response from a successful Slack Web API call, indicating 'ok: true'. ```json { "ok": true, "stuff": "This is good" } ``` -------------------------------- ### Construct Modal View with Kotlin DSL Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/modals.md Demonstrates building a modal view using the Block Kit Kotlin DSL for a more type-safe and fluent API. This approach leverages extension functions for constructing Slack UI components. ```kotlin import com.slack.api.model.kotlin_extension.view.blocks import com.slack.api.model.view.Views.* fun buildView(): View { return view { thisView -> thisView .callbackId("meeting-arrangement") .type("modal") .notifyOnClose(true) .title(viewTitle { it.type("plain_text").text("Meeting Arrangement").emoji(true) }) .submit(viewSubmit { it.type("plain_text").text("Submit").emoji(true) }) .close(viewClose { it.type("plain_text").text("Cancel").emoji(true) }) .privateMetadata("{\"response_url\":\"https://hooks.slack.com/actions/T1ABCD2E12/330361579271/0dAEyLY19ofpLwxqozy3firz\"}") .blocks { // You can leverage Kotlin DSL here section { blockId("category-block") markdownText("Select a category of the meeting!") staticSelect { actionId("category-selection-action") placeholder("Select a category") options { option { description("Customer") value("customer") } option { description("Partner") value("partner") } option { description("Internal") value("internal") } } } } input { blockId("agenda-block") plainTextInput { actionId("agenda-action") multiline(true) } label("Detailed Agenda", emoji = true) } } } } ``` -------------------------------- ### Gradle Repository Configuration for Local Maven Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-client-setup.md Add `mavenLocal()` to your `build.gradle` repositories block if you are building the SDK from source and want to use locally installed modules. ```groovy repositories { mavenLocal() } ``` -------------------------------- ### Handle Chat Post Message Response in Java Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md Example of calling the chat.postMessage API method and checking the response for success or failure using the isOk() method. ```java import com.slack.api.model.Message; ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req .channel("C1234567") .text("Write one, post anywhere")); if (response.isOk()) { Message postedMessage = response.getMessage(); } else { String errorCode = response.getError(); // e.g., "invalid_auth", "channel_not_found" } ``` -------------------------------- ### Kotlin Slack App Servlet with Quarkus Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/supported-web-frameworks.md Example of a Kotlin Slack Bolt application integrated with Quarkus using a Servlet. It defines a command handler for '/ping'. ```kotlin package hello import com.slack.api.bolt.App import com.slack.api.bolt.servlet.SlackAppServlet import javax.servlet.annotation.WebServlet @WebServlet("/slack/events") class SlackApp : SlackAppServlet(initSlackApp()) { companion object { fun initSlackApp(): App { val app = App() app.command("/ping") { req, ctx -> ctx.ack("<@${req.payload.userId}> pong!") } return app } } } ``` -------------------------------- ### Slack Web API Error Response Example Source: https://github.com/slackapi/java-slack-sdk/blob/main/docs/english/guides/web-api-basics.md A typical JSON response from a failed Slack Web API call, indicating 'ok: false' with an error code. ```json { "ok": false, "error": "something_bad" } ```