13. Untanglingthespaghetti
• Domain complexity at the heart of the application
• Domain logic abstracted from APIs, storage and
integration
• Process capability with the business logic
• CQRS: separate actions from views
2019|MakingWorkFlow|TieseBarrell
15. Designing
• Event storming: structure & understanding
• Prototype domain and process
• Contextual diagram: process and domain in one view
2019|MakingWorkFlow|TieseBarrell
19. Executingcommands
@ApplicationScoped
public class RegistrationDelegate() {
@Inject
private Registrations registrations;
@Transactional(TxType.MANDATORY)
public void confirmRegistration(String registrationId) {
Registration.Id id = new Registration.Id(registrationId);
Registration registration = registrations.get(id); // get
registration.confirm(LocalDateTime.now()); // execute
registrations.update(registration); // update
};
}
2019|MakingWorkFlow|TieseBarrell
20. Reactingtoevents
@ApplicationScoped
public class RegistrationCancelledProcessor {
@Inject
private RuntimeService runtimeService;
@Transaction(TxType.MANDATORY)
public void process(
@Observes(during = TransactionPhase.BEFORE_COMPLETION) Registration.Cancelled event) {
this.runtimeService.startProcessInstanceByMessage(
"registration-cancelled",
event.getRegistrationId());
}
}
2019|MakingWorkFlow|TieseBarrell
21. Baseclasses
public abstract class SynchronousEventProcessor<E extends DomainEvent> {
@Transactional(TxType.MANDATORY)
public void processSynchronous(@Observes(during = TransactionPhase.BEFORE_COMPLETION) E event) {
this.process(event);
}
protected abstract void process(E event);
}
2019|MakingWorkFlow|TieseBarrell
22. Baseclasses
public interface DomainEvent {
default void fire() {
// ...
}
}
public abstract class Repository<A extends AggregateRoot<I>, I> {
// add, update...
}
public abstract class Entity<I> {
public abstract I identity();
// equals, hashCode based on identity()
}
2019|MakingWorkFlow|TieseBarrell
23. Multi-Tenancy
• Several contexts in the same application
• Domain is agnostic
• Process records tenancy
• Propagate (user) context to process
• Propagate context from process to domain
2019|MakingWorkFlow|TieseBarrell
24. Contexttoprocessengine
@ApplicationScoped
public class MyTenantIdProvider implements TenantIdProvider {
@Inject
private Tenants tenants; // repository view of thread-local tenants
@Override
public String provideTenantIdForProcessInstance(
TenantIdProviderProcessInstanceContext context) {
this.tenants.current()
.map(t -> t.identity().getTenant())
.orElse(null);
}
// forCaseInstance, forDecisionInstance...
}
2019|MakingWorkFlow|TieseBarrell
25. Contextfromprocessinstance
public class ProcessApplication extends AbstractProcessApplication {
@Inject
private Tenants tenants;
@Override
public <T> T execute(Callable<T> callable, InvocationContext context) {
Execution execution = (Execution) context.getExecution();
String tenantId = execution.getTenantId(); // tenant context from process engine
if (tenantId == null) {
this.tenants.reset();
} else {
this.tenants.selectTenant(new Tenant.Id(tenantId));
}
}
}
2019|MakingWorkFlow|TieseBarrell
26. Hexagonalpitfalls
• Executing a technical model
http://airlink.cloud/nem
• A process sub domain (service)
• Interaction between adapter hexagons
• Everything is a domain action
2019|MakingWorkFlow|TieseBarrell
27. Userinteraction
• Task specific screens
• Screen populates itself (data)
• Task specific view models and commands
• Generic endpoints on process hexagon
2019|MakingWorkFlow|TieseBarrell
29. Conclusion
• Combine DDD, Hexagonal and Embeddable process engine
• Create flow in your process and processes
!
• Work however you want
• Just the right tools for process automation
2019|MakingWorkFlow|TieseBarrell