Domain events
- Add next dependency to gradle.build file of your microservice
implementation "com.icthh.xm.commons:xm-commons-domainevent:{version}"
- This lib uses xm-commons-migration-db so make sure you have this file in your resources folder:
/META-INF/services/org.hibernate.boot.spi.SessionFactoryBuilderFactory
and this file contains following line:
com.icthh.xm.commons.migration.db.jsonb.JsonbTypeRegistrator
- Create configuration file in your configuration repository project
/config/tenants/<tenant>/<microservice-name>/domainevent.yml
with the next structure:
enabled: true
sources:
DB:
enabled: true
transport: outboxTransport
where
- enabled - is domainevent feature enabled, if enabled initialization will be started
- sources - all listed configurations for each source will be supported
- DB - example name of the domain event source (database)
- enabled (under sources) - is this source enabled
- transport - name of spring bean (implementation of Transport interface) that will be used for the source
To use outbox extension (store domain events in database table), you need to add next dependency to gradle.build file of your microservice
implementation "com.icthh.xm.commons:xm-commons-domainevent-outbox:{version}"
With it you will be able to use outboxTransport implementation of transport, build domain events with prefilled current database transaction id, use OutboxTransportService to manage outbox table, etc...
- Autowire com.icthh.xm.commons.domain.event.service.builder.DomainEventFactory
- Build prefilled domain event:
DomainEvent domainEvent = domainEventFactory.build();
domainEvent will be prefilled with next fields:
- msName - microservice name
- tenant - current tenant where domain event was created
- eventDate - creation date
- clientId - client id from jwt Access Token
- userKey - user key from jwt Access Token
- You can build domainEvent with id of the current database transaction:
To make this feature supported, you need to add next dependency to gradle.build file of your microservice:
implementation "com.icthh.xm.commons:xm-commons-domainevent-db:{version}"
Or any dependency that extends xm-commons-domainevent-db (for example xm-commons-domainevent-outbox).
Usage example:
DomainEvent domainEvent = domainEventFactory.withTransaction().build();
domain event will be prefilled with all mentioned above fields and txId. withTransaction() factory will retrieve current transaction id from database and insert it into txId field. Additional database query will be executed. If creating multiple domain events for the same transaction, query will be run only once, next build calls will set cached transaction id.
4. More examples of domainEventFactory usage:
build domain event with minimum fields (msName, tenant, eventDate, clientId, userKey are already inserted):
DomainEvent event = domainEventFactory
.build();
assertEquals(MS_NAME, event.getMsName());
assertEquals(TENANT_KEY, event.getTenant());
assertNotNull(event.getEventDate());
assertEquals(CLIENT_ID, event.getClientId());
assertEquals(USER_KEY, event.getUserKey());
build domain event with operation, aggregateId and aggregateType (msName, tenant, eventDate, clientId, userKey are already inserted):
DomainEvent event = domainEventFactory
.build(CREATE, "aggregateId", "aggregateType");
assertEquals(MS_NAME, event.getMsName());
assertEquals(TENANT_KEY, event.getTenant());
assertNotNull(event.getEventDate());
assertEquals(CLIENT_ID, event.getClientId());
assertEquals(USER_KEY, event.getUserKey());
assertEquals("aggregateType", event.getAggregateType());
assertEquals("aggregateId", event.getAggregateId());
assertEquals(CREATE.name(), event.getOperation());
get lombok builder and set custom fields that we need (in this case withTransaction() is used, so current transaction id will be retrieved from database and inserted into txId field, to use it you need xm-commons-domainevent-db dependency)
(msName, tenant, eventDate, clientId, userKey, txId are already inserted):
DomainEvent event = domainEventFactory
.withTransaction()
.builder()
.aggregateType("aggregateType")
.aggregateId("aggregateId")
.build();
assertEquals(TX_ID, event.getTxId());
assertEquals(MS_NAME, event.getMsName());
assertEquals(TENANT_KEY, event.getTenant());
assertNotNull(event.getEventDate());
assertEquals(CLIENT_ID, event.getClientId());
assertEquals(USER_KEY, event.getUserKey());
assertEquals("aggregateId", event.getAggregateId());
assertEquals("aggregateType", event.getAggregateType());
build domain event with operation, aggregateId and aggregateType (in this case withTransaction() is used, so current transaction id will be retrieved from database and inserted into txId field, to use it you need xm-commons-domainevent-db dependency)
(msName, tenant, eventDate, clientId, userKey are already inserted):
DomainEvent event = domainEventFactory
.withTransaction()
.build(CREATE, "aggregateId", "aggregateType");
assertEquals(TX_ID, event.getTxId());
assertEquals(MS_NAME, event.getMsName());
assertEquals(TENANT_KEY, event.getTenant());
assertNotNull(event.getEventDate());
assertEquals(CLIENT_ID, event.getClientId());
assertEquals(USER_KEY, event.getUserKey());
assertEquals("aggregateType", event.getAggregateType());
assertEquals("aggregateId", event.getAggregateId());
assertEquals(CREATE.name(), event.getOperation());
DomainEvent domainEvent = new DomainEvent();
domainEvent.setAggregateId("aggregateId");
etc...
domainEvent = DomainEvent
.builder()
.aggregateId("aggregateId")
etc...
.build();
- autowire com.icthh.xm.commons.domain.event.service.EventPublisher bean
- use it to publish domain event with source defined in your configuration:
eventPublisher.publish("DB", domainEvent);
where "DB" is source enabled in your domainevent.yml file
you can use com.icthh.xm.commons.domain.event.domain.enums.DefaultDomainEventSource enum if you use default sources:
eventPublisher.publish(DB, domainEvent);