Skip to content

Concepts

In Baker, you declare orchestration logic as a Recipe. A recipe consists of three main building blocks: Ingredients, Interactions, and Events.

Ingredient

An ingredient is a combination of a name and type. Similar to how a variable declaration in your codebase is a combination of a name and type. For example, you can have an ingredient with the name iban and type string. Types are expressed via the Baker type system.

Ingredients are pure pieces of data. They are immutable, meaning they do not change once they enter the process or workflow. There is no support for hierarchy. Expressing a relationship like Animal -> Dog -> Labrador is not possible.

Ingredients serve as input for interactions and are carried through the process via events.

Event

Events represent something that has happened in your process. Most of the time, events are outputs of interactions. We refer to outputs of interactions as internal events. Sometimes events come from outside the process. we refer to events from outside the process as sensory events. Sensory events start/trigger the process.

Note

Under the hood internal events and sensory events are identical. The naming distinction exists for practical reasons only.

An event has a name and (optionally) provides ingredients. In the end, events and ingredients are just data structures that describe your process data. A good example would be an OrderPlaced event which carries two ingredients: the orderId and a list of products.

Interaction

Interactions resemble functions. They require input (ingredients) and provide output (events). An interaction can do many things. For example, fetch data from another service, do some complex calculation, send a message to an event broker, etc.

Recipe

A recipe is the blueprint of your business process. You define this process by combining ingredients, events, and interactions. Baker provides a recipe DSL, allowing you to define your recipe in Java, Kotlin, or Scala. The example below displays a (naive) recipe implementation to ship orders from a web-shop.

package examples.java.recipes;

import com.ing.baker.recipe.javadsl.InteractionDescriptor;
import com.ing.baker.recipe.javadsl.Recipe;
import examples.java.events.OrderPlaced;
import examples.java.interactions.ShipOrder;

public class SimpleRecipe {

    public final static Recipe recipe = new Recipe("example recipe")
        .withSensoryEvent(OrderPlaced.class)
        .withInteractions(
            InteractionDescriptor.of(ShipOrder.class)
        );
}
package examples.kotlin.recipes

import com.ing.baker.recipe.kotlindsl.ExperimentalDsl
import com.ing.baker.recipe.kotlindsl.recipe
import examples.kotlin.events.OrderPlaced
import examples.kotlin.interactions.ShipOrder

@ExperimentalDsl
object SimpleRecipe {
    val recipe = recipe("example recipe") {
        sensoryEvents {
            event<OrderPlaced>()
        }
        interaction<ShipOrder>() 
    }
}
package examples.scala.recipes

import com.ing.baker.recipe.scaladsl.{Event, Recipe}
import examples.scala.events.OrderPlaced
import examples.scala.interactions.ShipOrder

object SimpleRecipe {
  val recipe: Recipe = Recipe("example recipe")
    .withSensoryEvent(Event[OrderPlaced])
    .withInteraction(ShipOrder.interaction)
}