Pousse-Café Framework

Efficient and scalable implementation of complex business processes with the Java Language

Efficient
Process Design

  • Reason and communicate
    at domain process level
  • Design using EMIL
  • Implement using Java

Scalable Implementation

  • Leverage DDD
  • Adopt event-based processing
  • Write applications ready for distributed processing

Pluggable
Storage & Messaging

  • Cleanly separate business logic and data
  • Be flexible in your technology choices
  • Reduce risk upon technology change

Efficient Process Design and Communication

EMIL process representation

  • While EMIL helps for high level design, the Java code remains the single source of truth (i.e. EMIL only provides a partial view of the actual implementation)
  • Pousse-Café comes with tools enabling a smooth "communication" between EMIL and Java
@MessageListener(processes = OrderPlacement.class)
@ProducesEvent(OrderCreated.class)
public Root buildPlacedOrder(OrderPlaced event) {
    OrderDescription description = event.description().value();
    OrderId id = new OrderId(event.productId().value(),
        description.customerId(), description.reference());
    Root order = newAggregateWithId(id);
    order.attributes().units().value(description.units());
    return order;
}

Message listener implementation

  • EMIL and Java are generally not suitable for communication with the business
  • Pousse-Café comes with a tool which generates expert-readable documentation based on the code
  • Documentation is produced both in HTML and PDF (see this sample project)
  • This enables quick feedback from experts on the model
  • Documentation can be generated using the Maven plug-in
process graph example

Process graph

Scalable Implementation

  • Processes are executed by asynchronously handling messages
  • Messages are submitted by external actors (commands) or issued by the system itself (events)
  • Aggregates are first-class citizens
  • Messages are handled by message listeners which create, update or delete aggregates
message handling illustration

Message handling in a Pousse-Café runtime

  • In order to follow DDD principles, Pousse-Café automatically creates/updates/deletes a single aggregate per transaction
  • Transactions are automatically started by Pousse-Café upon execution of message listeners
  • Developers only have to write the listeners and their container
"Compute aggregate identifiers to update"; // Code actually written
while("all identifiers are not handled") {
    "Start transaction";
    "Fetch aggregate to update";
    "Execute update listener"; // Code actually written
    "Update aggregate;"
    "End transaction";
}

Algorithm describing aggregate(s) update upon message consumption

  • With parallel processing, the same aggregate may be updated at the same time by different execution threads: this is a "collision"
  • On a single machine, Pousse-Café uses multi-threading while guaranteeing the absence of collision
  • When the same application is executed by several machines, collisions cannot be avoided in general
  • Pousse-Café handles collisions by automatically retrying message consumptions causing one
collision illustration

Collision handling

Pluggable Storage & Messaging

  • Model code is written against an abstract data model
  • The actual implementation of the abstract data model depends on the storage technology
  • The amount of implementation code is small compared to model code
  • Changing storage technology only impacts a limited part of the code base
  • Support for a storage technology is achieved by writing a storage extension
root storage class diagram

Static class diagram for a sample aggregate root

  • Messages have an abstract definition
  • Their implementation depends on the messaging technology
  • The amount of implementation code is small compared to model code
  • Changing messaging technology only impacts a limited part of the code base
  • Support for a messaging technology is achieved by writing a messaging extension
messaging class diagram

Static class diagram for sample command and domain event

Get started!

  1. Generate your first Pousse-Café project (do not forget to replace archetype version with the latest latest version):

    mvn archetype:generate -B -DarchetypeGroupId=org.pousse-cafe-framework -DarchetypeArtifactId=pousse-cafe-sample-app-archetype -DarchetypeVersion=$ARCHETYPE_VERSION -DgroupId=test -DartifactId=test -Dversion=0.0.0-SNAPSHOT
  2. Follow the README
  3. Open the project in your favorite IDE and explore

OR...

  1. Clone this sample project
  2. Explore it with your favorite IDE
  3. Follow the README to execute the app and interact with it