How to create a Slack bot with Java

Slack is a very powerful communication tool. And you can make it even more powerful with all the cool apps/bots you are going to develop for it!
So you got this awesome idea but you don’t know how to create a Slack bot with Java? Just continue reading then!
First of all, head to Slack API documentation. This extensive documentation will be our main guide.
There are mainly two nodes in this process. First one is the application you will create via Slack interface, which requires no coding or whatsoever. And the second one is the real application/server that will talk with this Slack application we are going to create. And all of our business logic will be there.
There is no language limitation, you can write a Slack App in any language you want as long as you are capable of sending and receiving HTTP requests.
If you go to Github and type Slack in search bar, you will see lots of different frameworks/kits/bots developed by community which you can use. There is also one for Java, called jbot.
But honestly we don’t need any development kit, I would like to be as independent as possible. And it is not like re-inventing the wheel anyway, it is fairly easy process.
So, let’s dive in!

Step 1: Creating Slack App

Let’s create the application on Slack side. Head to Slack Apps and create a new application by providing a name for the application and choosing a workspace. If you are not part of a workspace you can create your own but that’s beyond the topic of this tutorial.

After filling out those two boxes, go to the application page. I’ve created an application on my workspace with name TestApp:

There are two ways to interact with Slack, Webhooks and Slash Commands. Let’s hack around with slash commands because they are very straight forward. Go to Slash Commands from the left panel and click on Create New Command button. You will need to fill some information to be able to create the command. Command is the text we need to enter to be able to interact with this command. It always starts with a / (slash). But you don’t need to explicitly put slash here. If you don’t, Slack will put it anyway.
Request URL is the url that Slack will send requests when user enters the slash command. Well, at this point you don’t have a url because you didn’t write any application. No problem! Just imagine that we have an application running at www.mbcoder.com which listens /slack path. Later you can change this url to your real url when we develop and deploy our application anyway. And finally enter a Short Description which users will see when they try to use this slash command. So the final form will look like:

Now, click on save and we are done with it! No need to install the application on Slack yet because we will change the url later, and whenever you make a change on the app, you have to re-install it. Let’s leave it like this and move on to the Java backend!

Step 2: Developing Java Backend

What will be our application about? I will give my own application as an example. We have this ping-pong table at the office. But sometimes I go there to play with a friend only to find out that it is already occupied by someone else. So I build a little IOT device using NodeMCU and vibration sensor and planted it on the table. You can also find my tutorial about NodeMCU setup on this blog. Anyway, whenever the sensor detects a vibration on the table, it sends a request to my server and the server stores the record of the last received signal. So when someone sends slash command on Slack to see if the table is empty, my server responds with last seen activity and possible occupation status according to that. There are also more fun functionalities I have added on top of it but this is the basic use-case for my application. You can find the whole code on my Github repository called OfficeEyes.
You can directly jump there and try to figure out rest from code, or you can follow this tutorial to understand the basics and then you can freely dive into good mythical Slack documentation to tailor your application as your need. We won’t develop the whole application in this tutorial anyway, I just want to show the basics. Maybe later I can make an in-depth Slack API tutorial.

Let’s code!

I will use Spring Boot for this purpose. Because it is very easy and convenient to develop a RESTful web services with Spring Boot. You can also check this little tutorial on Building a RESTful Web Service.
Just create a new Spring Boot project with spring-boot-starter-web dependency. Or just go to Spring Initializr and create a project with Web dependency:

Then press the Generate Project button which will download a zip file which you can import and start developing on. IntelliJ IDEA also has embedded Spring Initializr which you can use, I am not sure if it is in the free version though. So we have our project setup, let’s start.

Controller

First create a controller which will receive the request from Slack whenever a user uses our slash command.

@RestController
public class SlackController {
    @RequestMapping(value = "/slack/slash",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public String onReceiveSlashCommand(@RequestParam("team_id") String teamId,
                                               @RequestParam("team_domain") String teamDomain,
                                               @RequestParam("channel_id") String channelId,
                                               @RequestParam("channel_name") String channelName,
                                               @RequestParam("user_id") String userId,
                                               @RequestParam("user_name") String userName,
                                               @RequestParam("command") String command,
                                               @RequestParam("text") String text,
                                               @RequestParam("response_url") String responseUrl) {
        return ""text":"This is my JSON response"";
    }
}

Those request params are the values Slack sends us whenever someone interacts with our slash command. Right now I don’t care about any of those information and just printing a text whenever someone uses my slash command. By printing I mean I am sending that value to Slack as a response which will be then posted on the channel or private chat where this slash command initiated. But argh! This looks ugly and hard to maintain, let’s create a SlackResponse model object and return that one.

Response Model

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SlackResponse {

    @JsonProperty("text")
    private String text;

    @JsonProperty("response_type")
    private String responseType;

    public SlackResponse() {
    }

    public SlackResponse(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getResponseType() {
        return responseType;
    }

    public void setResponseType(String responseType) {
        this.responseType = responseType;
    }
}

There are also many many more fields which I didn’t include here but can be found in my repository. It is mainly because I want to keep this as simple as possible. For complex messages you can always refer to Slack documentation and try to figure out how to shape your messages from there. I will talk about response type shortly but let’s use our model first!

@RestController
public class SlackController {
    @RequestMapping(value = "/slack/slash",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public SlackResponse onReceiveSlashCommand(@RequestParam("team_id") String teamId,
                                               @RequestParam("team_domain") String teamDomain,
                                               @RequestParam("channel_id") String channelId,
                                               @RequestParam("channel_name") String channelName,
                                               @RequestParam("user_id") String userId,
                                               @RequestParam("user_name") String userName,
                                               @RequestParam("command") String command,
                                               @RequestParam("text") String text,
                                               @RequestParam("response_url") String responseUrl) {
        return new SlackResponse("This is my response");
    }
}

Better! So what is a response type? response_type field determines if the response will be visible by the whole channel (if the slash command initiated inside of a channel chat) or by the user only. If we set the response type to in_channel, everyone in the channel will see the response and the initial slash request. if we set the response type to ephemeral, only the user who initiated the command will see the response, also the initial request will not be visible to others. Basically they will see nothing. And all responses are ephemeral by default if you don’t set it manually to in_channel.
What else? We can add attachments to our response. So what is an attachment? Attachments are rich fields which can be used to improve the content and visualisation of response. We can add sub texts, author info, colours, links and many more via attachments. And we can add more than one attachment to a response.

Attachments

Let’s create a basic Attachment object and add it to our SlackResponse object.

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Attachment {

    @JsonProperty("color")
    private String color;

    @JsonProperty("text")
    private String text;

    public Attachment() {
    }

    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getText() {
        return this.text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SlackResponse {

    @JsonProperty("text")
    private String text;

    @JsonProperty("response_type")
    private String responseType;

    @JsonProperty("attachments")
    private List<Attachment> attachments;

    public SlackResponse() {
        attachments = new ArrayList<>();
    }

    public SlackResponse(String text) {
        this.text = text;
        attachments = new ArrayList<>();
    }

    public List getAttachments() {
        return attachments;
    }

    public void setAttachments(List attachments) {
        this.attachments = attachments;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getResponseType() {
        return responseType;
    }

    public void setResponseType(String responseType) {
        this.responseType = responseType;
    }
}

And now let’s create a response using those new informations:

@RestController
public class SlackController {
    @RequestMapping(value = "/slack/slash",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public SlackResponse onReceiveSlashCommand(@RequestParam("team_id") String teamId,
                                               @RequestParam("team_domain") String teamDomain,
                                               @RequestParam("channel_id") String channelId,
                                               @RequestParam("channel_name") String channelName,
                                               @RequestParam("user_id") String userId,
                                               @RequestParam("user_name") String userName,
                                               @RequestParam("command") String command,
                                               @RequestParam("text") String text,
                                               @RequestParam("response_url") String responseUrl) {
        SlackResponse response = new SlackResponse();
        response.setText("This is the response text");
        response.setResponseType("in_channel");

        Attachment attachment = new Attachment();
        attachment.setText("This is the attachment text");
        attachment.setColor("#0000ff");

        response.attachments.add(attachment);

        return response;
    }
}

Tadaa! We created more complex answer. There are also many more fields for attachments that you can add. It is very flexible. You can learn more from Message Attachments section of Slack documentation and play with their widget in there to see how will the message look like. For example the response we created above will look like:

As I said, this is very powerful tool, you can add interactive buttons and many more. This tutorial is more like an entrance to the Slack API, but you can always check the whole application I have developed to see more complex use-cases.
This is not a Java tutorial so whatever the business logic you want to develop behind is up to you. When you receive a command you can go to another service and ask something there and then use it in your response, like weather application!

Step 3: Deploying the Java Application

Anyway, let’s deploy our application. Heroku is great for beginners. Go create a free tier and deploy your java application there. But of course you can deploy your application anywhere you want. Then you will have a url that looks like: https://example-slack.herokuapp.com.
You can also connect your Github repo to Heroku and whenever you make changes on your code, Heroku will re-deployed it automatically, cool!

Step 4: Deploying the Slack App

Now let’s go to Slack Apps, and choose the app you created. Then go into Slash Commands and edit the request url with the new url you get from Heroku or wherever you deployed your application. So it will be something like: https://example-slack.herokuapp.com/slack. I added /slack at the end because that’s the path our controller is listening.
Now let’s deploy the Slack App on the workspace. Go to Install App section from the left panel. If you are not the admin, you will need a permission and after that you can install the app on Slack and start using the slash command. You can change your Java code without touching anything on Slack side, but whenever you change something about your application from Slack dashboard, you have to re-install it so that effects will take place.

Thanks for reading so far and I hope it was somehow useful! Happy hacking!

If you liked the content please share it!

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.