# Why can't Builders be reused after being build()-t

**URL:** <https://discuss.elastic.co/t/why-cant-builders-be-reused-after-being-build-t/367999>\
**Category:** Elasticsearch\
**Tags:** language-clients\
**Created:** [September 30, 2024, 8:34am UTC](https://discuss.elastic.co/t/why-cant-builders-be-reused-after-being-build-t/367999 "2024-09-30T08:34:49Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ndtreviv](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ndtreviv/32/22494_2.png) [@ndtreviv](https://discuss.elastic.co/u/ndtreviv)\
**Post date:** [September 30, 2024, 8:34am UTC](https://discuss.elastic.co/t/why-cant-builders-be-reused-after-being-build-t/367999/1 "2024-09-30T08:34:49Z")

</div>

I keep getting caught out by `Error: java.lang.IllegalStateException: Object builders can only be used once` errors.  
This is my fault for creating a builder outside of the query lambda and then calling `builder.build()` inside the lambda, eg:

```java
BoolQuery.Builder bool = new BoolQuery.Builder().filter(....);
if (someCondition) {
    bool.filter(f -> another conditional filter);
}
SearchResponse<ModeClass> response = elasticsearchService.search(s -> s
    .query(q -> q.bool(bool.build())), ModelClass.class)
    ...     

```

I was going to change code like this to call `build()` outside of the lambda and pass it in, like so:

```java
BoolQuery.Builder bool = new BoolQuery.Builder().filter(....);
if (someCondition) {
    bool.filter(f -> another conditional filter);
}
Bool.Query boolQuery = bool.build();
SearchResponse<ModelClass> response = elasticsearchService.search(s -> s
    .query(q -> q.bool(boolQuery)), ModelClass.class)
    ...     

```

This way, if the lamda is re-executed (by a resilience4j Retry, for example), we're not calling `build()` multiple times on the builder.

BUT I notice the docs state:

> Builders are transient objects that should not be reused after calling `build()`

Does this mean this is a bad idea? Why?  
Once a builder is built, why can't it be used multiple times?

---

<div class="post-metadata">

**Author:** ![DavidTurner](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/davidturner/32/22453_2.png) [@DavidTurner](https://discuss.elastic.co/u/DavidTurner)\
**Post date:** [September 30, 2024, 9:18am UTC](https://discuss.elastic.co/t/why-cant-builders-be-reused-after-being-build-t/367999/2 "2024-09-30T09:18:23Z")

</div>

> [@ndtreviv](#):
>
> Does this mean this is a bad idea? Why?

AFAICT in the latter code you're not using the builder after calling `build()` so it looks ok to me.

It's a bad idea (and forbidden) to re-use builders because they may share their underlying data structures with the object that is eventually built, so mutating the builder may also inadvertently mutate any previously-built requests too.

---

<div class="post-metadata">

**Author:** ![ltrotta](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ltrotta/32/124003_2.png) [@ltrotta](https://discuss.elastic.co/u/ltrotta)\
**Post date:** [September 30, 2024, 1:15pm UTC](https://discuss.elastic.co/t/why-cant-builders-be-reused-after-being-build-t/367999/3 "2024-09-30T13:15:59Z")

</div>

Hello!

~~To further elaborate on @DavidTurner's reply, every builder that includes a Collection creates that as Immutable, so reusing the same builder in that case would result in an exception.~~

Nevermind, even the Collections of an output object can be edited through the builder, so it's really safer to use them just once.
