This starter project provides auto-configuration support classes for building event-driven Spring Data applications.
- Uses a familiar Spring Data repository pattern for creating an
EventRepository<T, ID>
- The
EventRepository
provides trait specific features for managing an event log that is attached to an existing domain entity - Provides a set of event abstractions that can be extended to use any Spring Data repository (JPA, Mongo, Neo4j, Redis..)
- Provides an
EventService
bean that can be used to publish events to a Spring Cloud Stream output channel
In your Spring Boot project, add the starter project dependency to your class path. For Maven, add the following dependency to your pom.xml
.
<dependencies>
<dependency>
<groupId>org.kbastani</groupId>
<artifactId>spring-boot-starter-data-events</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>
Next, configure your Spring Cloud Stream output bindings. Add the following snippet to the application.properties|yaml
file of your Spring Boot application. Replace the destination value with the name of your message channel for the event stream.
spring:
cloud:
stream:
bindings:
output:
destination: payment
Next, you'll need to create a custom Event
entity. The snippet below extends the provided Event<T, E, ID>
interface. This example uses Spring Data JPA, but you can use any Spring Data project for implementing your event entities.
@Entity
@EntityListeners(AuditingEntityListener.class)
public class PaymentEvent extends Event<Payment, PaymentEventType, Long> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long eventId;
@Enumerated(EnumType.STRING)
private PaymentEventType type;
@OneToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
@JsonIgnore
private Payment entity;
@CreatedDate
private Long createdAt;
@LastModifiedDate
private Long lastModified;
...
}
To start managing events you'll need to extend the EventRepository<T, ID>
interface. The PaymentEvent
is the JPA entity we defined in the last snippet.
public interface PaymentEventRepository extends EventRepository<PaymentEvent, Long> {
}
That's it! You're ready to start sending domain events to the stream binding's output channel using the auto-configured EventService
. The example snippet below shows how to create and append a new PaymentEvent
to a Payment
entity before publishing the event over AMQP to the configured event stream's output channel.
@Service
public class PaymentService {
private final EventService<PaymentEvent, Long> eventService;
public PaymentController(EventService<PaymentEvent, Long> eventService) {
this.eventService = eventService;
}
public PaymentEvent appendCreateEvent(Payment payment) {
PaymentEvent paymentEvent = new PaymentEvent(PaymentEventType.PAYMENT_CREATED);
paymentEvent.setEntity(payment);
paymentEvent = eventService.save(event);
// Send the event to the Spring Cloud stream binding
eventService.sendAsync(paymentEvent);
}
...
}
A default EventController
is also provided with the starter project. The EventController
provides a basic REST API with hypermedia resource support for managing the Event
log of a domain entity over HTTP. The following cURL snippet gets the PaymentEvent
we created in the last example from the EventController
.
curl -X GET "http://localhost:8082/v1/events/1"
Response:
{
"eventId": 1,
"type": "PAYMENT_CREATED",
"createdAt": 1482749707006,
"lastModified": 1482749707006,
"_links": {
"self": {
"href": "http://localhost:8082/v1/events/1"
},
"payment": {
"href": "http://localhost:8082/v1/payments/1"
}
}
}
In the snippet above we can see the EventController
responded with a hal+json
formatted resource. Since the PaymentEvent
has a reference to the Payment
entity, we see a payment link is available to fetch the related resource.