eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Introduction

Slack is a popular chat system used by people and companies around the world. One of the things that makes it so popular is the ability to write our own custom plugins that can interact with people and channels within a single slack. This uses their HTTP API.

Slack doesn’t offer an official SDK for writing plugins with Java. However, there is an officially endorsed community SDK that we are going to use. This gives us access to almost all of the Slack API from a Java codebase without our needing to concern ourselves with the exact details of the API.

We’ll make use of this to build a small system monitoring bot. This will periodically retrieve the disk space for the local computer and alert people if any drives are getting too full.

2. Obtaining API Credentials

Before we can do anything with Slack, we need to create a new App and a Bot and connect it to our channels.

Firstly, let’s visit https://api.slack.com/apps. This is the base from where we manage our Slack apps. From here we can create a new app.

Screenshot-2020-01-31-at-21.37.19

When we do this, we need to enter a name for the app and a Slack workspace to create it.

Screenshot-2020-01-31-at-21.39.37

Once we’ve done this, the app has been created and is ready for us to work with. The next screen allows us to create a Bot. This is a fake user that the plugin will be acting as.

Screenshot-2020-01-31-at-21.40.38

As with any normal user, we need to give this a display name and a username. These are the settings that other users in the Slack workspace will see for this bot user if they ever interact with it.

Screenshot-2020-01-31-at-21.40.59

Now that we’ve done this, we can select “Install App” from the side menu and add the App to our Slack workspace. Once we’ve done this, the app can interact with our workspace.

Screenshot-2020-01-31-at-21.41.47

This will then give us the tokens that we need for our plugin to communicate with Slack.

Screenshot-2020-01-31-at-21.45.00

 

Each bot interacting with a different Slack workspace will have a different set of tokens. Our application needs the “Bot User OAuth Access Token” value for when we run it.

Finally, we need to invite the bot to any channels it should be involved in. This works by simply messaging it from the channel — @system_monitoring in this case.

3. Adding Slack to Our Project

Before we can use it, we first need to add the Slack SDK dependencies to our pom.xml file:

<dependency>
    <groupId>com.hubspot.slack</groupId>
    <artifactId>slack-base</artifactId>
    <version>${slack.version}</version>
</dependency>
<dependency>
    <groupId>com.hubspot.slack</groupId>
    <artifactId>slack-java-client</artifactId>
    <version>${slack.version}</version>
</dependency>

3. Application Structure

The core of our application is the ability to check for errors in the system. We’ll represent this with the concept of an Error Checker. This is a simple interface with a single method, triggered to check for errors and report them:

public interface ErrorChecker {
    void check();
}

We also want to have the means to report any errors that have been found. This is another simple interface that will take a problem statement and report it appropriately:

public interface ErrorReporter {
    void reportProblem(String problem);
}

The use of an interface here allows us to have different ways of reporting problems. For example, we might have one that sends emails, contacts an error reporting system, or sends messages to our Slack system for people to get an immediate notification.

The design behind this is that each ErrorChecker instance is given its own ErrorReporter to use. This gives us the flexibility to have different error reporters for different checkers to use because some errors might be more important than others. For example, if the disks are over 90% full that may require a message to a Slack channel, but if they are over 98% full then we might instead want to send private messages to specific people instead.

4. Checking Disk Space

Our error checker will check the amount of disk space on the local system. Any file system that has less than a particular percentage free is considered to be an error and will be reported as such.

We’ll make use of the NIO2 FileStore API introduced in Java 7 to obtain this information in a cross-platform manner.

Now, let’s take a look at our error checker:

public class DiskSpaceErrorChecker implements ErrorChecker {
    private static final Logger LOG = LoggerFactory.getLogger(DiskSpaceErrorChecker.class);

    private ErrorReporter errorReporter;

    private double limit;

    public DiskSpaceErrorChecker(ErrorReporter errorReporter, double limit) {
        this.errorReporter = errorReporter;
        this.limit = limit;
    }

    @Override
    public void check() {
        FileSystems.getDefault().getFileStores().forEach(fileStore -> {
            try {
                long totalSpace = fileStore.getTotalSpace();
                long usableSpace = fileStore.getUsableSpace();
                double usablePercentage = ((double) usableSpace) / totalSpace;

                if (totalSpace > 0 && usablePercentage < limit) {
                    String error = String.format("File store %s only has %d%% usable disk space",
                        fileStore.name(), (int)(usablePercentage * 100));
                    errorReporter.reportProblem(error);
                }
            } catch (IOException e) {
                LOG.error("Error getting disk space for file store {}", fileStore, e);
            }
        });
    }
}

Here, we’re obtaining the list of all file stores on the local system and then checking each one individually. Any that has less than our defined limit as usable space will generate an error using our error reporter.

5. Sending Errors to Slack Channels

We now need to be able to report our errors. Our first reporter will be one that sends messages to a Slack channel. This allows anyone in the channel to see the message, in the hope that somebody will react to it.

This uses a SlackClient, from the Slack SDK, and the name of the channel to send the messages to. It also implements our ErrorReporter interface so that we can easily plug it into whichever error checker wants to use it:

public class SlackChannelErrorReporter implements ErrorReporter {
    private SlackClient slackClient;

    private String channel;

    public SlackChannelErrorReporter(SlackClient slackClient, String channel) {
        this.slackClient = slackClient;
        this.channel = channel;
    }

    @Override
    public void reportProblem(String problem) {
        slackClient.postMessage(
          ChatPostMessageParams.builder()
            .setText(problem)
            .setChannelId(channel)
            .build()
        ).join().unwrapOrElseThrow();
    }
}

6. Application Wiring

We are now in a position to wire up the application and have it monitor our system. For the sake of this tutorial, we’re going to use the Java Timer and TimerTask that are part of the core JVM, but we could just as easily use Spring or any other framework to build this.

For now, this will have a single DiskSpaceErrorChecker that reports any disks that are under 10% usable to our “general” channel, and which runs every 5 minutes:

public class MainClass {
    public static final long MINUTES = 1000 * 60;

    public static void main(String[] args) throws IOException {
        SlackClientRuntimeConfig runtimeConfig = SlackClientRuntimeConfig.builder()
          .setTokenSupplier(() -> "<Your API Token>")
          .build();

        SlackClient slackClient = SlackClientFactory.defaultFactory().build(runtimeConfig);

        ErrorReporter slackChannelErrorReporter = new SlackChannelErrorReporter(slackClient, "general");

        ErrorChecker diskSpaceErrorChecker10pct = 
          new DiskSpaceErrorChecker(slackChannelErrorReporter, 0.1);

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                diskSpaceErrorChecker10pct.check();
            }
        }, 0, 5 * MINUTES);
    }
}

We need to replace “<Your API Token>” with the token that was obtained earlier, and then we’re ready to run. As soon as we do, if everything is correct, our plugin will check the local drives and message Slack if there are any errors.

Screenshot-2020-01-31-at-21.42.55

7. Sending Errors as Private Messages

Next, we’re going to add an error reporter that sends private messages instead. This can be useful for more urgent errors since it will immediately ping a specific user instead of relying on someone in the channel to react.

Our error reporter here is more complicated because it needs to interact with a single, targeted user:

public class SlackUserErrorReporter implements ErrorReporter {
    private SlackClient slackClient;

    private String user;

    public SlackUserErrorReporter(SlackClient slackClient, String user) {
        this.slackClient = slackClient;
        this.user = user;
    }

    @Override
    public void reportProblem(String problem) {
        UsersInfoResponse usersInfoResponse = slackClient
            .lookupUserByEmail(UserEmailParams.builder()
              .setEmail(user)
              .build()
            ).join().unwrapOrElseThrow();

        ImOpenResponse imOpenResponse = slackClient.openIm(ImOpenParams.builder()
            .setUserId(usersInfoResponse.getUser().getId())
            .build()
        ).join().unwrapOrElseThrow();

        imOpenResponse.getChannel().ifPresent(channel -> {
            slackClient.postMessage(
                ChatPostMessageParams.builder()
                  .setText(problem)
                  .setChannelId(channel.getId())
                  .build()
            ).join().unwrapOrElseThrow();
        });
    }
}

What we have to do here is to find the user that we are messaging — looked up by email address, since this is the one thing that can’t be changed. Next, we open an IM channel to the user, and then we post our error message to that channel.

This can then be wired up in the main method, and we will alert a single user directly:

ErrorReporter slackUserErrorReporter = new SlackUserErrorReporter(slackClient, "[email protected]");

ErrorChecker diskSpaceErrorChecker2pct = new DiskSpaceErrorChecker(slackUserErrorReporter, 0.02);

timer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        diskSpaceErrorChecker2pct.check();
    }
}, 0, 5 * MINUTES);

Once done, we can run this up and get private messages for errors as well.

Screenshot-2020-01-31-at-21.44.01

8. Conclusion

We’ve seen here how we can incorporate Slack into our tooling so that we can have feedback sent to either the entire team or to individual members. There’s much more we can do with the Slack API, so why not see what else we can incorporate?

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LS – NPI (cat=Java)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)