Getting started
This walks you through adding notify4j to a Spring Boot app and sending your first notification. For the engine without Spring, see Architecture.
2. 1. Add the dependency
The starter transitively pulls in notify4j-core:
<dependency>
<groupId>org.alexmond</groupId>
<artifactId>notify4j-spring-boot-starter</artifactId>
<version>4.1.1.1</version>
</dependency>
The starter is released per Spring Boot line from the notify4j-spring-boot
repo. Its version tracks the Spring Boot version it is built against
(<boot-version>.<revision>), so it differs from the notify4j version. Pick the line that
matches your application from the compatibility table.
3. 2. Provide a NotificationAdapter
notify4j is domain-agnostic: it never references your event type directly. You supply one
NotificationAdapter<E> bean that maps your event to the three things every channel needs —
a stable id (used to detect status transitions), a status, and a human message.
@Bean
NotificationAdapter<BuildEvent> buildAdapter() {
return new NotificationAdapter<>() {
public Object id(BuildEvent e) { return e.getBuildId(); }
public String status(BuildEvent e) { return e.getStatus(); } // e.g. "FAILED"
public String message(BuildEvent e) { return e.describe(); }
};
}
Once this bean exists, the starter auto-configures a Notifications<BuildEvent> facade.
4. 3. Declare channels
List channels as Apprise-style URLs in
application.yml:
notify4j:
urls:
- slack://hooks.slack.com/services/T000/B000/XXXX
- pagerduty://<routing-key>?tags=failed
5. 4. Send
Inject the facade and call send:
@Service
class BuildListener {
private final Notifications<BuildEvent> notifications;
BuildListener(Notifications<BuildEvent> notifications) {
this.notifications = notifications;
}
void onBuild(BuildEvent event) {
notifications.send(event); // all untagged channels
// or route to a subset by tag:
notifications.send(event, List.of("failed")); // only channels tagged "failed"
}
}
By default notify4j only fires on meaningful status transitions and skips intermediate
states (PENDING/RUNNING/ASSIGNED) — so a build that goes RUNNING → FAILED notifies
once, on FAILED. See transition filtering.
In the starter, send is also non-blocking by default: each channel is delivered on a
shared pool (so a slow channel can’t block the caller or its siblings) and transient HTTP
failures are retried. Both are configurable — see Configuration
(notify4j.async.*, notify4j.http.max-attempts).
6. Try the sample
The notify4j-sample module in the notify4j-spring-boot repo is a runnable
Spring Boot app wired exactly as above; its application.yml ships a commented example of
every channel. From a checkout of that repo, run it with:
./mvnw -Pdefault -pl notify4j-sample spring-boot:run
With no channels configured it still fans the demo event out to the always-on logging sink.
7. Beyond the single facade
Building one facade per tenant (or wiring notify4j without the starter)? See
Multi-tenant: async, retry & metrics without the starter
for how to get async delivery, retry, and metrics on a programmatic NotificationsFactory.