> For the complete documentation index, see [llms.txt](https://wirebox.ortusbooks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wirebox.ortusbooks.com/advanced-topics/object-persistence-and-thread-safety.md).

# Object Persistence & Thread Safety

While the injector can help in many ways to secure the creation of your objects, it is ultimately up to you to create code that is both thread safe and tested. It is always a great idea to design your objects without the injector in mind for threading and concurrency.

**Dependency Injection** is not a silver bullet, but a tool to relieve object creation and not to relieve the burden of good object design. Thread safety is much more complex and can be compromised when using persistent scopes like singleton, session, server, application and cachebox, as more than one thread will be trying to access your code and dependencies.

By default, WireBox locks object creation and constructor dependency resolution. Persistent scopes store an instance before setter and property wiring so circular dependencies can resolve. Since ColdBox 8.3.0, a single wiring lock per injector prevents other threads from receiving singleton, engine-scoped (application, session, or server), and CacheBox-scoped objects until wiring completes. The thread building the object can still resolve circular dependencies, and circular partners remain marked as wiring until the outermost build completes.

This is a safe-publication guarantee, not a general lock around an object's methods or mutable state after wiring. Marking a class as thread safe locks its full construction and wiring, but circular dependencies are not supported in that mode unless you use providers. (See [Providers Section](/advanced-topics/providers.md).)

Constructor injection is locked by the injector during construction. The following class uses constructor injection:

{% tabs %}
{% tab title="BoxLang" %}

```js
class{

     /**
     * Constructor injection is locked during construction. For persistent scopes, other threads wait until dependency wiring completes (ColdBox 8.3.0+); this does not lock later method calls.
     */
    @log.inject( "logbox:logger:{this}" )
    @dao.inject( "id:MyDAO" )
     function init( required log, required dao ){
          variables.log = arguments.log;
          variables.dao = arguments.dao;
          return this;
     }

}
```

{% endtab %}

{% tab title="CFML" %}

```cfscript
component{

     /**
     * Constructor injection is locked during construction. For persistent scopes, other threads wait until dependency wiring completes (ColdBox 8.3.0+); this does not lock later method calls.
     */
     function init( required log, required dao ) log.inject="logbox:logger:{this}" dao.inject="id:MyDAO" {
          variables.log = arguments.log;
          variables.dao = arguments.dao;
          return this;
     }

}
```

{% endtab %}
{% endtabs %}

An example of a flawed object could be the following:

{% tabs %}
{% tab title="BoxLang" %}

```js
class{

     @inject( "id:MyDAO" )
     property name="dao";

     @inject( "logbox:logger:{this}" )
     property name="log";

     function init(){
          return this;
     }
}
```

{% endtab %}

{% tab title="CFML" %}

```cfscript
component{

     property name="dao" inject="id:MyDAO";
     property name="log" inject="logbox:logger:{this}";

     function init(){
          return this;
     }
}
```

{% endtab %}
{% endtabs %}

Why is this object flawed? In a persistent scope, it is mutable and may be used by multiple request threads. WireBox stores it before setter and property wiring to support circular dependencies, then completes its injections and `onDiComplete()` method. Since ColdBox 8.3.0, other threads requesting the same scoped object wait until that wiring completes, so they do not receive a half-wired instance. This does not serialize later reads and writes: mutable state accessed concurrently still needs its own synchronization or an immutable design.

> "The subtle reason has to do with the way Java Virtual Machines (JVM) are designed to manage threads. Threads may keep local, cached copies of non-volatile fields that can quickly get out of sync with one another unless they are synchronized correctly."\
> From Dependency Injection by Dhanji R. Prasanna **Note** This side effect of concurrency will only occur on objects that are singletons or persisted in scopes like session, server, application, server or cachebox. It does not affect transient or request scoped objects.

WireBox, can help you lock and provide thread safety to setter and property injections by providing you with the `ThreadSafe` annotation or our binder `threadSafe()` tagging method. So if we wanted to make the last example thread safe for property and setter wiring then we would do the following:

{% tabs %}
{% tab title="BoxLang" %}

```js
@threadSafe
class{

     @inject( "id:MyDAO" )
     property name="dao";

     @inject( "logbox:logger:{this}" )
     property name="log";

     function init(){
          return this;
     }
}
```

{% endtab %}

{% tab title="CFML" %}

```cfscript
component threadsafe{

     property name="dao" inject="id:MyDAO";
     property name="log" inject="logbox:logger:{this}";

     function init(){
          return this;
     }
}
```

{% endtab %}
{% endtabs %}

Or you can map the object as thread safe via the binder:

```js
// or you can bind it as a thread safe component
map("MyObject").to("path.model.MyObject").asSingleton().threadSafe();
```

> **Note** All objects are marked as non thread safe for dependency wiring by default in order to allow for circular dependencies. Please note that if you mark an object as `threadSafe`, then it will not be able to support circular dependencies unless it uses WireBox providers. ( See [Providers Section](https://github.com/ortus/wirebox-documentation/tree/b9a6ae3e91f7dcb74ec7e900e27243e19824cf27/object_persistence_&_thread_safety/providers/README.md) )

Our `threadSafe` annotation and binder tagging property will allow for these objects to be completely locked and synchronized for object creation, wiring and `onDiComplete()`. However, circular dependencies will now fail as persistence cannot be guaranteed for the setter or property dependencies. However, since WireBox is so awesome, you can still use circular dependencies by wiring instead our object providers. (Please see providers section). In conclusion, constructing and designing a class that is thread safe is often a very arduous process. It is also very difficult to test and recreate threading issues in your objects and applications. So don't feel bad, as even the best of us can get into some nasty wormholes when dealing with concurrency and thread safety. However, always try to design for as much concurrency as possible and test test test!

## Transient Request Persistence

This feature is one of the most impactful for applications that leverage DI on transient objects, especially ORM-related applications. WireBox caches the signatures of the injections and delegations for you, so they are only computed once per instance type per request. This yields dramatic performance improvements (over 585% in real-world ORM-heavy apps). The best part: it is on by default. Install and run it.

### Configuration

If this is not for you or it causes issues in your system, disable it globally via the WireBox binder:

```javascript
// Config DSL
wirebox = {
     transientInjectionCache : false
};

// Binder call
binder.transientInjectionCache( false );
```

You can also disable the cache on a per-class basis:

{% tabs %}
{% tab title="BoxLang" %}

```js
class transientCache="false"{
}
```

{% endtab %}

{% tab title="CFML" %}

```cfscript
component transientCache="false"{
}
```

{% endtab %}
{% endtabs %}

### Known Issues

Because the cache reuses injection and delegation results per Class definition, injected transients can effectively behave like singletons within the request. If you inject transients that must remain unique per instance, use one of the following approaches:

1. Disable the cache entirely (heavy-handed approach)
2. Disable the cache on that specific Class via `transientCache` (surgical approach)
3. Inject the dependency as a provider (ninja approach)
4. Make the property lazy and build it on demand (Jedi approach)

{% tabs %}
{% tab title="BoxLang" %}

```js
class name="Transient" transientCache="false"{
     // This will become a singleton within the request if caching is enabled
     property name="transient2" inject="t2";
     // Provider injection
     property name="transient2" inject="provider:t2";
     // Lazy property
     property name="transient2" lazy;

     function buildTransient2(){
          return variables.wirebox.getInstance( "t2" );
     }
}
```

{% endtab %}

{% tab title="CFML" %}

```cfscript
component name="Transient" transientCache="false"{
     // This will become a singleton within the request if caching is enabled
     property name="transient2" inject="t2";
     // Provider injection
     property name="transient2" inject="provider:t2";
     // Lazy property
     property name="transient2" lazy;

     function buildTransient2(){
          return variables.wirebox.getInstance( "t2" );
     }
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://wirebox.ortusbooks.com/advanced-topics/object-persistence-and-thread-safety.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
