---
title: Store values in shared tree state
description: Tree state exists for the lifetime of the journey session. When the tree has completed, the journey session is terminated and an authenticated session is created. The purpose of tree state is to hold state between the nodes.
component: pingam
version: 8.1
page_id: pingam:auth-nodes:store-values-shared-state
canonical_url: https://docs.pingidentity.com/pingam/8.1/auth-nodes/store-values-shared-state.html
keywords: ["Extensibility", "Nodes &amp; Trees"]
section_ids:
  store-values-in-transient-state: Store values in a tree's node states
  set-get-values-in-tree-state: Get and set values stored in tree state
  nodestate-naming: NodeState key naming
  set-values-in-tree-state: Set values in the tree state
  get-values-from-tree-state: Get values in the tree state
  combine_objects: Combine objects
  merge_keys: Merge keys
---

# Store values in shared tree state

Tree state exists for the lifetime of the *journey session*. When the tree has completed, the journey session is terminated and an *authenticated session* is created. The purpose of tree state is to hold state between the nodes.

A good example is the [Username Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/username-collector.html), which gets the username from the user and stores it in the shared tree state. Later, the [Data Store Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/data-store-decision.html) can pull this value from the shared tree state and use it to authenticate the user.

Authentication trees can be *stateful* or *stateless*. When they are stateful, the AM server that starts the authentication flow mustn't change. A load balancer cookie is set on the responses to the user to ensure the same AM server is used. When they are stateless, any AM instance in a deployment can proceed with the journey session.

You can find more information on configuring sessions in [Sessions](../am-sessions/preface.html).

## Store values in a tree's node states

Always store the authentication state in the `NodeState` object that AM lets you access from the `TreeContext` object passed to the node's `process` method. AM ensures the node state is made available to downstream nodes:

* Store non-sensitive information with the `NodeState.putShared(String key, Object value)` method.

* Store sensitive information, such as passwords, with the `NodeState.putTransient(String key, Object value)` method.

  AM encrypts values in transient state using the key mapped to the `am.authn.trees.transientstate.encryption` secret label. When a journey resumes after a callback, AM decrypts this transient state into secure state to let downstream nodes read and, if necessary, persist the data. All AM instances that participate in the journey must share the same secret to decrypt this state.

  Limit what you store with the `putShared` and `putTransient` methods to make sure the authentication flow isn't bloated with calls to encrypt or decrypt data, and the journey session size stays small. This is especially true when the realm is configured for client-side journey sessions.

## Get and set values stored in tree state

Internally, AM distinguishes the following node state data:

* Shared state, where nodes store non-sensitive information that needs to be available during the authentication flow.

  You store this with the `NodeState.putShared(String key, Object value)` method.

* Transient state, where nodes store sensitive information that AM encrypts on round trips to the client.

  You store this with the `NodeState.putTransient(String key, Object value)` method.

* Secure state, where nodes store decrypted transient state.

Learn more in [NodeState](../_attachments/apidocs/org/forgerock/openam/auth/node/api/NodeState.html).

### NodeState key naming

Follow these naming guidelines when specifying the `key` string in the `putShared` and `putTransient` methods:

* Keep the key name short. It should be less than 20 characters (excluding the prefix) to reduce what's sent to the client.

  If you include a prefix, keep it under 15 characters.

* Use camel case for the key name, starting with a lowercase letter. For example, `myKey`.

* Don't use periods (`.`) as separators. Only use a hyphen (`-`) as a separator between the prefix and name.

* Don't use a class name as the prefix.

* Don't change the key name once you have released the node.

### Set values in the tree state

To set node state values, get the `NodeState` using the `TreeContext.getStateFor(Node node)` method. Then, use the `NodeState.putShared(String key, Object value)` and `NodeState.putTransient(String key, Object value)` methods as described above.

For example:

```java
// Setting values in NodeState
public Action process(TreeContext context) {
  String username;
  String password;
  // ...
  NodeState state = context.getStateFor(this);
  state.putShared(username, username);      // Non-sensitive information
  state.putTransient(password, password);   // Sensitive information
  if (!state.isDefined(optionalNumeric)) { // Check before updating
    state.putShared(optionalNumeric, 42);
  }
  goToNext().build();
}
```

### Get values in the tree state

To read node state values, use the `NodeState.isDefined(String key)` and `NodeState.get(String key)` methods.

For example:

```java
// Getting values from NodeState
public Action process(TreeContext context) {
  NodeState state = context.getStateFor(this);
  String username;
  if (state.isDefined(username)) {
      username = state.get(username);
  } else {
    throw new NodeProcessException("Username is required");
  }
  // ...
  goToNext().build();
}
```

The `get(String key)` method retrieves the state for the key from `NodeState` states in the following order:

1. transient

2. secure

3. shared

For example, if the same property is stored in the transient and shared states, the method returns the value of the property in the transient state first.

#### Combine objects

To combine objects from shared, transient and secure state, use the `getObject` method.

For example, if the following `objectAttributes` value exists in shared state:

```java
"objectAttributes": { "sharedKey": "value" }
```

and the following `objectAttributes` value exists in transient state:

```java
"objectAttributes": { "transientKey": "value" }
```

when you call `nodeState.getObject("objectAttributes");`, the combined result is as follows:

```java
{
   "sharedKey": "value",
   "transientKey": "value"
}
```

This object is read-only.

#### Merge keys

To merge keys in an object, use the `mergeShared` and `mergeTransient` methods.

Learn more in [Access shared state data](../am-scripting/scripting-api-node.html#scripting-api-node-nodeState).
