Skip to content

botMessage handler in Assistant middleware does not work when other event listeners do not exist #1414

@rbioteau

Description

@rbioteau

When implementing the following example provided in the documentation an NPE prevent the proper execution of the use case.

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 I 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<String, Object> 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<String> 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);

In the above example we register a botMessage and a userMessage on the Assistant. However, when executing this simple app, these messages are never returned to my chat.

The problem occurs in the com.slack.api.bolt.util.EventsApiPayloadParser#buildEventPayload method where my eventClass is null. It seems to rely on a cache to retrieve a given Event class for an event name. The is cache is empty in my case and I need to explicitly call EventsApiPayloadParser.getEventTypeAndSubtype(MessageEvent.class) in my code to initialize the map.

Reproducible in:

[INFO] com.bonitasoft:my-slackbot:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:3.4.1:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:3.4.1:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:3.4.1:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:3.4.1:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:3.4.1:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.5.12:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.5.12:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.24.3:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.24.3:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:2.0.16:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:2.3:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:3.4.1:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.18.2:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.18.2:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.18.2:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.18.2:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.18.2:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.18.2:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.4.1:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.34:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.34:compile
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.34:compile
[INFO] |  +- org.springframework:spring-web:jar:6.2.1:compile
[INFO] |  |  +- org.springframework:spring-beans:jar:6.2.1:compile
[INFO] |  |  \- io.micrometer:micrometer-observation:jar:1.14.2:compile
[INFO] |  |     \- io.micrometer:micrometer-commons:jar:1.14.2:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:6.2.1:compile
[INFO] |     +- org.springframework:spring-aop:jar:6.2.1:compile
[INFO] |     +- org.springframework:spring-context:jar:6.2.1:compile
[INFO] |     \- org.springframework:spring-expression:jar:6.2.1:compile
[INFO] +- com.slack.api:bolt-jakarta-servlet:jar:1.45.0:compile
[INFO] |  +- com.slack.api:slack-api-model:jar:1.45.0:compile
[INFO] |  |  \- com.google.code.gson:gson:jar:2.11.0:compile
[INFO] |  |     \- com.google.errorprone:error_prone_annotations:jar:2.27.0:compile
[INFO] |  +- com.slack.api:slack-api-client:jar:1.45.0:compile
[INFO] |  |  +- com.squareup.okhttp3:okhttp:jar:4.12.0:compile
[INFO] |  |  |  +- com.squareup.okio:okio:jar:3.6.0:compile
[INFO] |  |  |  |  \- com.squareup.okio:okio-jvm:jar:3.6.0:compile
[INFO] |  |  |  |     \- org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.9.25:compile
[INFO] |  |  |  \- org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.9.25:compile
[INFO] |  |  |     +- org.jetbrains.kotlin:kotlin-stdlib:jar:1.9.25:compile
[INFO] |  |  |     |  \- org.jetbrains:annotations:jar:13.0:compile
[INFO] |  |  |     \- org.jetbrains.kotlin:kotlin-stdlib-jdk7:jar:1.9.25:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:2.0.16:compile
[INFO] |  +- com.slack.api:slack-app-backend:jar:1.45.0:compile
[INFO] |  \- com.slack.api:bolt:jar:1.45.0:compile
[INFO] |     \- org.apache.commons:commons-text:jar:1.13.0:compile
[INFO] |        \- org.apache.commons:commons-lang3:jar:3.17.0:compile
[INFO] \- org.springframework.boot:spring-boot-starter-test:jar:3.4.1:test
[INFO]    +- org.springframework.boot:spring-boot-test:jar:3.4.1:test
[INFO]    +- org.springframework.boot:spring-boot-test-autoconfigure:jar:3.4.1:test
[INFO]    +- com.jayway.jsonpath:json-path:jar:2.9.0:test
[INFO]    +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.2:test
[INFO]    |  \- jakarta.activation:jakarta.activation-api:jar:2.1.3:test
[INFO]    +- net.minidev:json-smart:jar:2.5.1:test
[INFO]    |  \- net.minidev:accessors-smart:jar:2.5.1:test
[INFO]    |     \- org.ow2.asm:asm:jar:9.6:test
[INFO]    +- org.assertj:assertj-core:jar:3.26.3:test
[INFO]    |  \- net.bytebuddy:byte-buddy:jar:1.15.11:test
[INFO]    +- org.awaitility:awaitility:jar:4.2.2:test
[INFO]    +- org.hamcrest:hamcrest:jar:2.2:test
[INFO]    +- org.junit.jupiter:junit-jupiter:jar:5.11.4:test
[INFO]    |  +- org.junit.jupiter:junit-jupiter-api:jar:5.11.4:test
[INFO]    |  |  +- org.opentest4j:opentest4j:jar:1.3.0:test
[INFO]    |  |  +- org.junit.platform:junit-platform-commons:jar:1.11.4:test
[INFO]    |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO]    |  +- org.junit.jupiter:junit-jupiter-params:jar:5.11.4:test
[INFO]    |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.11.4:test
[INFO]    |     \- org.junit.platform:junit-platform-engine:jar:1.11.4:test
[INFO]    +- org.mockito:mockito-core:jar:5.14.2:test
[INFO]    |  +- net.bytebuddy:byte-buddy-agent:jar:1.15.11:test
[INFO]    |  \- org.objenesis:objenesis:jar:3.3:test
[INFO]    +- org.mockito:mockito-junit-jupiter:jar:5.14.2:test
[INFO]    +- org.skyscreamer:jsonassert:jar:1.5.3:test
[INFO]    |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO]    +- org.springframework:spring-core:jar:6.2.1:compile
[INFO]    |  \- org.springframework:spring-jcl:jar:6.2.1:compile
[INFO]    +- org.springframework:spring-test:jar:6.2.1:test
[INFO]    \- org.xmlunit:xmlunit-core:jar:2.10.0:test

The Slack SDK version

[INFO] +- com.slack.api:bolt-jakarta-servlet:jar:1.45.0:compile
[INFO] | +- com.slack.api:slack-api-model:jar:1.45.0:compile
[INFO] | +- com.slack.api:slack-api-client:jar:1.45.0:compile
[INFO] | +- com.slack.api:slack-app-backend:jar:1.45.0:compile
[INFO] | - com.slack.api:bolt:jar:1.45.0:compile

Java Runtime version

openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode, sharing)

OS info

Distributor ID: Ubuntu
Description: Ubuntu 24.04.1 LTS
Release: 24.04
Codename: noble

Steps to reproduce:

Run the springboot example with the code sample for Agent & Assistant from the documentation, See snippet above.

Expected result:

The botMessage handler should be executed.

Actual result:

The botMessage handler is not executed due to a NPE when retrieving the botId in the Assistant#apply method.

Requirements

Please make sure if this topic is specific to this SDK. For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. 🙇

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you agree to those rules.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugM-T: confirmed bug report. Issues are confirmed when the reproduction steps are documentedproject:bolt

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions