Spring Events

Overview

Spring events provides event handling mechanism in spring.

Github: https://github.com/gitorko/project73

Spring Events

Spring events lets you create and consume events within an application thus providing loose coupling. Let's say you have 2 async functions that needs co-ordinate. When async1 is complete you need async2 to pick up the processed data and process it. You could use an external queue like rabbitmq, or you could write a producer consumer. Spring events lets you handle such a task easily. Do note that this will be in-memory so if the server restarts all events will be lost.

Code

 1package com.demo.project73;
 2
 3import lombok.extern.slf4j.Slf4j;
 4import org.springframework.boot.context.event.ApplicationReadyEvent;
 5import org.springframework.context.event.EventListener;
 6import org.springframework.scheduling.annotation.Async;
 7import org.springframework.scheduling.annotation.EnableAsync;
 8import org.springframework.stereotype.Service;
 9
10@Slf4j
11@EnableAsync
12@Service
13public class CustomEventListener {
14
15    /**
16     * When the application is ready it triggers this event
17     */
18    @EventListener(ApplicationReadyEvent.class)
19    public void onStart() {
20        log.info("Triggered when application ready!");
21    }
22
23    /**
24     * Processes the custom event
25     */
26    @Async
27    @EventListener
28    public void processEvent(CustomEvent myEvent) {
29        log.info("Received event {}", myEvent);
30        if (myEvent.getEntity() instanceof Project) {
31            log.info("Project Name: {}", ((Project) myEvent.getEntity()).getName());
32        }
33        if (myEvent.getEntity() instanceof Audit) {
34            log.info("Audit Message: {}", ((Audit) myEvent.getEntity()).getMessage());
35        }
36    }
37
38}
 1package com.demo.project73;
 2
 3import org.springframework.context.ApplicationEvent;
 4
 5public class CustomEvent<T> extends ApplicationEvent {
 6
 7    private T entity;
 8
 9    public CustomEvent(Object source, T entity) {
10        super(source);
11        this.entity = entity;
12    }
13
14    public T getEntity() {
15        return entity;
16    }
17}
 1package com.demo.project73;
 2
 3import java.time.LocalDateTime;
 4import java.util.concurrent.TimeUnit;
 5import java.util.stream.IntStream;
 6
 7import lombok.RequiredArgsConstructor;
 8import lombok.SneakyThrows;
 9import lombok.extern.slf4j.Slf4j;
10import org.springframework.context.ApplicationEventPublisher;
11import org.springframework.scheduling.annotation.Async;
12import org.springframework.scheduling.annotation.EnableAsync;
13import org.springframework.stereotype.Service;
14
15@Service
16@EnableAsync
17@Slf4j
18@RequiredArgsConstructor
19public class CustomAsync {
20
21    private final ApplicationEventPublisher applicationEventPublisher;
22
23    /**
24     * Runs the job in async thread
25     */
26    @Async
27    public void doSomeAsyncTask1() {
28        log.info("Running task!");
29        IntStream.range(0, 5).forEach(i -> {
30            Project project = new Project(i, "Project_" + i);
31            Audit audit = new Audit("Audit Message " + i, LocalDateTime.now());
32            log.info("Trigger event: {}", project);
33            CustomEvent<Project> projectEvent = new CustomEvent(this, project);
34            CustomEvent<Audit> auditEvent = new CustomEvent(this, audit);
35            applicationEventPublisher.publishEvent(projectEvent);
36            sleep(1);
37            applicationEventPublisher.publishEvent(auditEvent);
38        });
39    }
40
41    @SneakyThrows
42    public void sleep(int seconds) {
43        TimeUnit.SECONDS.sleep(seconds);
44    }
45
46}

Run the project

1./gradlew bootRun

The doSomeAsyncTask1 posts 2 events on the async thread. Both these events are then processed on different async threads.

References

https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2

comments powered by Disqus