> For the complete documentation index, see [llms.txt](https://docs.rumi.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rumi.systems/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/embedded-entities.md).

# Embedded Entities

Embedded entities are lifecycle-managed objects that enable zero-garbage composition of complex messages. They are reusable, pooled objects embedded within messages or state objects.

## Overview

Embedded entities allow you to compose complex, nested data structures within messages and state while maintaining zero-garbage characteristics. Instead of allocating new objects for each nested structure, embedded entities are pooled and reused across message processing cycles.

## Declaring Embedded Entities

Embedded entities are declared in ADM using the `entity` type with the `embedded="true"` attribute:

```xml
<entity name="OrderLine" embedded="true">
  <string name="symbol"/>
  <int name="quantity"/>
  <double name="price"/>
</entity>

<message name="Order">
  <string name="orderId"/>
  <OrderLine name="line"/>
</message>
```

## Lifecycle Management

Embedded entities have a strict lifecycle that must be managed correctly to achieve zero-garbage operation. The ADM code generator produces methods to manage this lifecycle:

| Method           | Description                                                                                                                        | Returns             |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `getXXX()`       | Returns a reference to the embedded entity. Object remains owned by the parent.                                                    | Read-only reference |
| `takeXXX()`      | Removes the embedded entity from the parent and transfers ownership to the caller. The parent's field becomes null.                | Transferred entity  |
| `lendXXX()`      | Returns a reference for modification. Object ownership remains with the parent.                                                    | Mutable reference   |
| `setXXX(Entity)` | Sets the embedded entity. If a non-null entity already exists, it is disposed. The provided entity is copied if not already owned. | void                |

## Using getXXX()

The `getXXX()` accessor returns a read-only reference to the embedded entity. The parent retains ownership and the returned object should not be modified:

```java
@EventHandler
public void onOrder(Order order) {
    OrderLine line = order.getLine();
    if (line != null) {
        String symbol = line.getSymbol();
        // Read fields, but don't modify
    }
}
```

**Important**: The returned entity may be reset or reused after the message handler returns. Do not hold references to embedded entities beyond the scope of the handler.

## Using takeXXX()

The `takeXXX()` method transfers ownership of the embedded entity from the parent to the caller:

```java
@EventHandler
public void onOrder(Order order) {
    // Take ownership of the line
    OrderLine line = order.takeLine();

    // Parent's line field is now null
    assert order.getLine() == null;

    // We now own the line and can modify it
    line.setQuantity(100);

    // Must dispose when done to return to pool
    line.dispose();
}
```

After calling `takeXXX()`, the parent's field becomes null, and the caller is responsible for disposing the entity when finished.

## Using lendXXX()

The `lendXXX()` method returns a reference for modification while the parent retains ownership:

```java
@EventHandler
public void onOrder(Order order) {
    // Get a mutable reference
    OrderLine line = order.lendLine();
    if (line == null) {
        // Create if doesn't exist - parent creates and owns
        line = order.setLine(new OrderLineXbufEntity());
    }

    // Modify directly - parent still owns
    line.setQuantity(100);
    line.setPrice(150.25);

    // No dispose needed - parent still owns
}
```

The `lendXXX()` pattern is the most common for zero-garbage updates to embedded entities.

## Using setXXX()

The `setXXX()` method sets the embedded entity value:

```java
@EventHandler
public void onOrder(Order order) {
    // Create a new line
    OrderLine line = new OrderLineXbufEntity();
    line.setSymbol("AAPL");
    line.setQuantity(100);

    // Set on parent - parent takes ownership
    order.setLine(line);

    // Parent now owns it, no dispose needed
}
```

If an entity already exists in the parent when `setXXX()` is called, the old entity is automatically disposed.

## Serialization and Deserialization

Embedded entities are automatically serialized and deserialized with their parent message. When a message containing embedded entities is sent, the entities are serialized as part of the message payload. When received, they are deserialized and populated from the message content.

## Pass-Through Fields

Embedded entities support "pass-through" behavior where incoming message entities can be efficiently transferred to outbound messages without deep copying:

```java
@EventHandler
public void onOrder(Order incomingOrder, MessageView view) {
    // Create outbound order
    OrderAck ack = new OrderAckXbufMessage();

    // Take from incoming (transfers ownership)
    OrderLine line = incomingOrder.takeLine();

    // Set on outgoing (transfers ownership again)
    ack.setLine(line);

    // Send ack
    view.send(ack);
}
```

This pattern avoids copying the embedded entity's data, achieving zero-garbage pass-through.

## Common Patterns

**Creating if Null**:

```java
OrderLine line = order.lendLine();
if (line == null) {
    order.setLine(new OrderLineXbufEntity());
    line = order.lendLine();
}
line.setQuantity(100);
```

**Clearing an Embedded Entity**:

```java
OrderLine line = order.takeLine();
if (line != null) {
    line.dispose(); // Returns to pool
}
// order.getLine() is now null
```

**Updating Multiple Fields**:

```java
OrderLine line = order.lendLine();
if (line != null) {
    line.setSymbol("AAPL");
    line.setQuantity(100);
    line.setPrice(150.25);
}
```

## See Also

* [Coding for Zero Garbage](/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage.md) - Overview of zero garbage techniques
* [XStrings](/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/xstrings.md) - Zero garbage string handling
* [Array Accessors](/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/array-accessors.md) - Allocation-free array iteration
