CloudEvents
The module sda-commons-cloudevents
provides some glue code to work with
CloudEvents on top of Apache Kafka.
Introduction
CloudEvents is a general standard that can be used in combination with your favourite eventing tool
like ActiveMQ or Kafka.
The CloudEvents specification defines concrete bindings to define how the general specification
should be applied to a specific tool.
This module provides POJOs to use CloudEvent's structured content mode.
Producing CloudEvents
For simplicity, we recommend to extend our base class and add your own class for the data
property.
Additional documentation can be added at class level and for the data type.
Custom event
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | /*
* Copyright 2022- SDA SE Open Industry Solutions (https://www.sda.se)
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package org.sdase.commons.spring.boot.cloudevents.app.partner;
import com.fasterxml.jackson.annotation.JsonClassDescription;
import io.swagger.v3.oas.annotations.media.Schema;
import java.net.URI;
import org.sdase.commons.spring.boot.cloudevents.CloudEventV1;
@JsonClassDescription("An event that is published when a partner has been created.")
public class PartnerCreatedEvent extends CloudEventV1<PartnerCreatedEvent.PartnerCreated> {
private static final String DEFAULT_SOURCE = "/SDA-SE/partner/partner-stack/partner-service";
private static final String DEFAULT_TYPE = "com.sdase.partner.ods.partner.created";
public PartnerCreatedEvent() {
super();
super.setSource(URI.create(DEFAULT_SOURCE));
super.setType(DEFAULT_TYPE);
}
@JsonClassDescription("Details about the created partner.")
public record PartnerCreated(
@Schema(
description = "The unique id of a partner.",
example = "FF427BC8-B38F-43CC-8AAB-512843808A18")
String id) {}
}
|
You can use a standard org.springframework.kafka.support.serializer.JsonSerializer
to publish the
event.
Consuming CloudEvents
You can use org.springframework.kafka.support.serializer.JsonDeserializer
to consume CloudEvents.
Polymorphism
Usually, an eventing API consists of multiple events related to one aggregate.
You can use Jacksons subtype features to define multiple events in one model.
Multiple events in one API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 | /*
* Copyright 2022- SDA SE Open Industry Solutions (https://www.sda.se)
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package org.sdase.commons.spring.boot.cloudevents.app.polymorphism;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.As.EXISTING_PROPERTY;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME;
import static org.sdase.commons.spring.boot.cloudevents.app.polymorphism.CarLifecycleEvents.MANUFACTURED;
import static org.sdase.commons.spring.boot.cloudevents.app.polymorphism.CarLifecycleEvents.SCRAPPED;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.sdase.commons.spring.boot.cloudevents.CloudEventV1;
@JsonTypeInfo(use = NAME, property = "type", visible = true, include = EXISTING_PROPERTY)
@JsonSubTypes({
@Type(value = CarLifecycleEvents.CarManufactured.class, name = MANUFACTURED),
@Type(value = CarLifecycleEvents.CarScrapped.class, name = SCRAPPED)
})
public abstract class CarLifecycleEvents<T> extends CloudEventV1<T> {
static final String MANUFACTURED = "se.sda.car.manufactured";
static final String SCRAPPED = "se.sda.car.scrapped";
public static class CarManufactured
extends CarLifecycleEvents<CarManufactured.CarManufacturedData> {
public CarManufactured() {
super();
super.setType(MANUFACTURED);
}
public record CarManufacturedData(String brand, String model) {}
}
public static class CarScrapped extends CarLifecycleEvents<CarScrapped.CarScrappedData> {
public CarScrapped() {
super();
super.setType(SCRAPPED);
}
public record CarScrappedData(ScrapReason reason) {
public enum ScrapReason {
ACCIDENT,
TECHNICAL_DAMAGE
}
}
}
}
|
Note: If such a model grows, you may want to extract the data types as top level classes.