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