@Autowired private App app; is not listening the events in Spring Boot, it says No BoltEventHandler registered for event: app_mention
mallik30 opened this issue · 9 comments
Autowiring the App in the spring boot is not listening to Slack events
Reproducible in: https://github.com/mallik30/actionbot/tree/slack-autowired-not-listening
mvn dependency:tree | grep com.slack.api
gradle dependencies | grep com.slack.api
java -version
sw_vers && uname -v # or `ver`
The Slack SDK version
(Paste the output of mvn dependency:tree | grep com.slack.api
or gradle dependencies | grep com.slack.api
)
attached actual github codebase url above
Java Runtime version
(Paste the output of java -version
)
java version "13" 2019-09-17
OS info
(Paste the output of sw_vers && uname -v
on macOS/Linux or ver
on Windows OS)
ProductName: macOS
ProductVersion: 13.3.1
ProductVersionExtra: (a)
BuildVersion: 22E772610a
Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17 PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64
Steps to reproduce:
(Share the commands to run, source code, and project settings (e.g., pom.xml/build.gradle))
- add tokens in the application.properties
- run as a Java application
- and trigger the flow using @MYBOT create
Expected result:
expected to listen the events from @Autowired private App app dependency injection
as its a bad practice to code inside a @bean in configuration class
Actual result:
it throws the following error
No BoltEventHandler registered for event: app_mention
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.
Hi @mallik30, thanks for writing in!
It seems that these listener registration methods (https://github.com/mallik30/actionbot/blob/4e9bc923e654bcb096998494d46a7c514d781c0b/src/main/java/com/arjun/slack/api/ActionBotManager.java#L39-L71) are not called in your app. In this case, the event handling error can arise as expected becuse your app does not have corresponding listeners for it.
This is our recommendation to register listeners to your App
instance (as a Spring bean component): https://github.com/slackapi/java-slack-sdk/blob/v1.29.2/bolt-spring-boot-examples/spring-boot-3/src/main/java/example/SlackApp.java#L36-L46 It is the same way with this disabled code in your app.
If you're exploring a different way to initialize the App
instnace, please consult Sping Boot community and/or their documents. We are a small team, so we don't provide supports for general Spring Boot questions.
I hope this helps and you'll find a viable solution for you!
Hi @seratch with the way Bean is defined in config class
i have to do this to listen to multiple events, which will make the method way big, I think there should be another way to listen the bean from slack side
public App appMention(/* App app */) {
//AppMentionEvent event
app.event(AppMentionEvent.class, (payload, ctx) -> {
return ctx.ack();
});
//ReactionAddedEvent event
app.event(ReactionAddedEvent.class, (payload, ctx) -> {
return ctx.ack();
});
return app;
// other events
// other events
}
@mallik30 You don't need to consolidate all the code into a single method. Our recommendation is to divide the code into separate files, as shown in this example: https://github.com/slack-samples/bolt-java-starter-template/blob/main/src/main/java/Main.java This approach is entirely independent from the Spring Boot bean registration. Concurrently, you can still inject other bean components into listener functions if you define the listener classes as beans.
@mallik30 Sorry for the confusion, but you can ignore the line new SocketModeApp(app).start();
.
I meant you can go with the example app's approach to organize listeners: https://github.com/slack-samples/bolt-java-starter-template/tree/main/src/main/java/listeners You don't need to use static methods like the app does. Instead, you can have a bean component that manages listeners.
@seratch still a lot of unnecessary changes, something simple like the below would beneficial
config class
@Configuration
public class SlackConfig {
@Value("${SLACK_BOT_TOKEN}")
private String botToken;
@Value("${SLACK_SIGNING_SECRET}")
private String signingSecret;
@Bean
AppConfig appConfig() {
return AppConfig.builder().singleTeamBotToken(botToken).signingSecret(signingSecret).build();
}
@Bean
App app(AppConfig appConfig) {
return new App(appConfig);
}
}
manager class
@Service
public class Manager {
@Value("${SLACK_BOT_TOKEN}")
private String botToken;
@Value("${SLACK_USER_TOKEN}")
private String userToken;
@Autowired
private App app;
public App reactionAdded() {
return app.event(ReactionAddedEvent.class, (payload, ctx) -> {
return ctx.ack();
});
}
public App appMention() {
return app.event(AppMentionEvent.class, (payload, ctx) -> {
return ctx.ack();
});
}
}
@mallik30 If you prefer the approach, calling these listener registraton methods in the serivce/bean initialization method would be a good option. You can go with either @Bean(initMethod="initMethodNameHere")
or adding @PostConstruct
to the initMethod. Inside the init method, you can call reactionAdded
, appMention
, and many more you'll add in the future.
We don't have plans to provide anything specific to Spring Boot (because it can bring extra maintenance cost to our small SDK maintainer team). Please consider any of the suggestions I provided here.
@seratch am moving forward with the below approach
@Service
public class Manager {
@Autowired
private App app;
@PostConstruct
public void init() {
reactionAdded();
appMention();
}
public void reactionAdded() {
app.event(ReactionAddedEvent.class, (payload, ctx) -> {
return ctx.ack();
});
}
public void appMention() {
app.event(AppMentionEvent.class, (payload, ctx) -> {
return ctx.ack();
});
}
}
Thank you for your assistance.
also, I have another question, I got stuck on the threaded approach and am unable to find the relevant events to listen for user responses in threads will you be able to assist with this one?
You can subscribe message events for it: https://api.slack.com/events/message With bolt-java, you can add a new listener like app.event(MessageEvent.class, ...
.
Since I've provided an answer to your original question here, let me close this thread. Whenever you have a new question, you can create a new issue for it. Thanks again for writing in!