ScopedValue: O Sucessor Moderno do ThreadLocal no Java 21+
Com a chegada das Virtual Threads no Java 21, a escalabilidade atingiu um novo patamar, permitindo que aplicações gerenciem milhões de threads simultaneamente. No entanto, essa nova densidade expôs fraquezas em ferramentas veteranas, como o ThreadLocal. Para resolver esses problemas, o Java introduziu o ScopedValue (finalizado no Java 25 via JEP 506), uma funcionalidade fundamental para a concorrência moderna.
Neste artigo, vamos explorar por que o ThreadLocal se tornou um gargalo, como o ScopedValue oferece uma alternativa mais segura e eficiente, e como ele se integra ao ecossistema de Virtual Threads e Structured Concurrency.
📦 Repositório de referência: github.com/guigomes91/virtual-threads
O Problema: As Deficiências do ThreadLocal
O ThreadLocal permite que dados sejam armazenados localmente em uma thread, mas possui três falhas críticas de design que se agravam com Virtual Threads:
- Mutabilidade Descontrolada: Qualquer componente com acesso à variável pode chamar
set(), tornando o rastreio de alterações e o debug extremamente complexos. - Vazamentos de Memória (Memory Leaks): Os dados persistem enquanto a thread estiver viva, a menos que
remove()seja chamado explicitamente. Em ambientes de longa duração, esquecer de limpar essas variáveis causa vazamentos graves. - Herança Cara: Quando uma thread pai cria threads filhas, todas as variáveis
ThreadLocalsão copiadas para as novas threads. Com milhões de Virtual Threads, essa duplicação de dados esgota rapidamente o heap da JVM.
Exemplo do problema com ThreadLocal
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// ⚠️ Padrão problemático com ThreadLocal&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;RequestContext&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ThreadLocal&amp;amp;lt;String&amp;amp;gt; USER_ID = &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;ThreadLocal&amp;lt;/span&amp;gt;&amp;amp;lt;&amp;amp;gt;();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;handleRequest&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(String userId)&amp;lt;/span&amp;gt; {
USER_ID.set(userId);
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">try</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; {
processRequest();
} &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">finally</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; {
USER_ID.remove(); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// esqueceu isso? -&amp;amp;gt; memory leak&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
}
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;processRequest&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Qualquer código pode chamar set() e corromper o estado&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
USER_ID.set(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;hacker&amp;amp;quot;&amp;lt;/span&amp;gt;); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// ⚠️ mutação silenciosa e perigosa&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
System.out.println(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;Processando para: &amp;amp;quot;&amp;lt;/span&amp;gt; + USER_ID.get());
}
}
A Solução: ScopedValue
O ScopedValue surge como uma alternativa de "via de mão única" para compartilhar dados imutáveis entre componentes e suas sub-tarefas de forma segura.
Os Pilares do ScopedValue
| Característica | ThreadLocal | ScopedValue |
|---|---|---|
| Mutabilidade | set() livre |
Imutável após where() |
| Tempo de vida | Lifetime da thread | Escopo da tarefa |
| Herança | Cópia completa (cara) | Referência compartilhada (grátis) |
| Compatibilidade | Pool de threads | Virtual Threads nativas |
| Risco de leak | Alto | Nenhum |
- Imutabilidade: Não existe o método
set(). Uma vez vinculado viawhere(), o valor permanece constante durante todo o escopo de execução. - Tempo de Vida Delimitado: O valor é vinculado apenas à execução de um método específico. Assim que a tarefa termina, o valor é invalidado automaticamente, eliminando o risco de memory leaks.
- Eficiência de Memória: Threads filhas (especialmente dentro de um
StructuredTaskScope) compartilham a mesma referência do valor da thread pai, sem cópias custosas.
Como Implementar na Prática
1. Declaração
Geralmente declarado como campo estático e final, com acesso restrito para garantir encapsulamento.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;SecurityContext&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// private: apenas esta classe pode fazer bind e leitura&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;String&amp;amp;gt; USER_ID = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// public: expõe acesso de leitura para outros componentes de forma controlada&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; String &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;currentUserId&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; USER_ID.get();
}
}
2. Vinculação e Execução (Binding)
A vinculação define onde e por quanto tempo o valor estará disponível. É possível encadear múltiplos valores.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Vinculando um único valor&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
ScopedValue.where(USER_ID, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;getcaramelo&amp;amp;quot;&amp;lt;/span&amp;gt;)
.run(() -&amp;amp;gt; processarRequisicao());
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Encadeando múltiplos valores&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
ScopedValue.where(USER_ID, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;getcaramelo&amp;amp;quot;&amp;lt;/span&amp;gt;)
.where(REQUEST_ID, UUID.randomUUID().toString())
.where(TENANT_ID, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;acme-corp&amp;amp;quot;&amp;lt;/span&amp;gt;)
.run(() -&amp;amp;gt; processarRequisicao());
3. Recuperação Segura
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Verificação antes do acesso&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">if</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; (USER_ID.isBound()) {
System.out.println(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;Usuário atual: &amp;amp;quot;&amp;lt;/span&amp;gt; + USER_ID.get());
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Valor padrão caso não esteja vinculado (Java 25: orElse não aceita null)&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;String&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;userId&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; USER_ID.orElse(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;anonimo&amp;amp;quot;&amp;lt;/span&amp;gt;);
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Lança exceção se não estiver vinculado&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">try</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;String&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;id&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; USER_ID.get();
} &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">catch</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; (NoSuchElementException e) {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// ScopedValue não foi vinculado neste escopo&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
}
4. Retornando valores com call()
Além de run() (que retorna void), use call() quando precisar de um resultado:
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// run() -&amp;amp;gt; void&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
ScopedValue.where(USER_ID, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;getcaramelo&amp;amp;quot;&amp;lt;/span&amp;gt;)
.run(() -&amp;amp;gt; salvarAuditoria());
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// call() -&amp;amp;gt; retorna valor&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;String&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;resultado&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; ScopedValue.where(USER_ID, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;getcaramelo&amp;amp;quot;&amp;lt;/span&amp;gt;)
.call(() -&amp;amp;gt; buscarPerfil());
ScopedValue em Fluxos Reais
Exemplo 1: TravelApp com Structured Concurrency
No cenário de um sistema de viagens, o ScopedValue organiza o fluxo de dados entre microserviços concorrentes de forma limpa, sem passar parâmetros por toda a pilha de chamadas.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;TravelService&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;String&amp;amp;gt; LOC = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;String&amp;amp;gt; DEST = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; TravelOffer &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;fetchTravelOffers&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(String origem, String destino)&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">throws</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; Exception {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue.where(LOC, origem)
.where(DEST, destino)
.call(() -&amp;amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">try</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; (&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">var</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;scope&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;StructuredTaskScope&amp;lt;/span&amp;gt;.ShutdownOnFailure()) {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// As sub-tarefas herdam LOC e DEST automaticamente&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// sem nenhuma cópia de memória&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">var</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;ridesharing&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; scope.fork(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-built_in&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-built_in&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">this</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt;::fetchRidesharing);
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">var</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;publicTransport&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; scope.fork(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-built_in&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-built_in&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">this</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt;::fetchPublicTransport);
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">var</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;taxi&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; scope.fork(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-built_in&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-built_in&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">this</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt;::fetchTaxi);
scope.join().throwIfFailed();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; buildOffer(
ridesharing.get(),
publicTransport.get(),
taxi.get()
);
}
});
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; RidesharingQuote &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;fetchRidesharing&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// LOC e DEST disponíveis sem parâmetros!&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;String&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;from&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; LOC.get();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;String&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;to&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; DEST.get();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ridesharingApi.quote(from, to);
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; TransportQuote &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;fetchPublicTransport&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; transitApi.routes(LOC.get(), DEST.get());
}
}
Exemplo 2: Segurança em APIs Web (contexto de autenticação)
Padrão comum em frameworks web para propagar o usuário autenticado sem injeção de dependência manual.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;SecurityFilter&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;Principal&amp;amp;gt; PRINCIPAL = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;doFilter&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(HttpRequest request, FilterChain chain)&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;Principal&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;principal&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; authenticate(request);
ScopedValue.where(PRINCIPAL, principal)
.run(() -&amp;amp;gt; chain.doFilter(request));
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Após o run(), PRINCIPAL é automaticamente invalidado&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
}
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;OrderService&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; Order &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;createOrder&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(OrderRequest req)&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Acessa o principal sem receber por parâmetro&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;Principal&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;user&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; SecurityFilter.PRINCIPAL.get();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">if</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; (!user.hasRole(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;CUSTOMER&amp;amp;quot;&amp;lt;/span&amp;gt;)) {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">throw</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;AccessDeniedException&amp;lt;/span&amp;gt;(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;Acesso negado para: &amp;amp;quot;&amp;lt;/span&amp;gt; + user.getName());
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; orderRepository.save(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;Order&amp;lt;/span&amp;gt;(req, user.getName()));
}
}
Exemplo 3: Rastreamento distribuído (Tracing)
Propagação de traceId para logs estruturados em sistemas distribuídos.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;TracingContext&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;String&amp;amp;gt; TRACE_ID = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;String&amp;amp;gt; SPAN_ID = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;withNewTrace&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(Runnable task)&amp;lt;/span&amp;gt; {
ScopedValue.where(TRACE_ID, UUID.randomUUID().toString())
.where(SPAN_ID, UUID.randomUUID().toString())
.run(task);
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; String &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;currentTraceId&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; TRACE_ID.orElse(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;sem-trace&amp;amp;quot;&amp;lt;/span&amp;gt;);
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; String &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;currentSpanId&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; SPAN_ID.orElse(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;sem-span&amp;amp;quot;&amp;lt;/span&amp;gt;);
}
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Uso em qualquer camada da aplicação&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;PaymentService&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;Logger&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;log&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; LoggerFactory.getLogger(PaymentService.class);
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;processPayment&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(Payment payment)&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Log automaticamente enriquecido com o trace&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
log.info(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;[traceId={}] [spanId={}] Processando pagamento de {}&amp;amp;quot;&amp;lt;/span&amp;gt;,
TracingContext.currentTraceId(),
TracingContext.currentSpanId(),
payment.amount());
}
}
Exemplo 4: Rebinding - Sobrescrita Controlada de Escopo
Em alguns cenários, uma chamada aninhada precisa de um valor diferente no mesmo ScopedValue. O rebinding cria um novo escopo sem afetar o escopo externo.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;String&amp;amp;gt; ROLE = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;demonstrate&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
ScopedValue.where(ROLE, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;USER&amp;amp;quot;&amp;lt;/span&amp;gt;).run(() -&amp;amp;gt; {
System.out.println(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;Escopo externo: &amp;amp;quot;&amp;lt;/span&amp;gt; + ROLE.get()); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// &amp;amp;quot;USER&amp;amp;quot;&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Rebinding: cria um escopo interno com valor diferente&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
ScopedValue.where(ROLE, &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;ADMIN&amp;amp;quot;&amp;lt;/span&amp;gt;).run(() -&amp;amp;gt; {
System.out.println(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;Escopo interno: &amp;amp;quot;&amp;lt;/span&amp;gt; + ROLE.get()); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// &amp;amp;quot;ADMIN&amp;amp;quot;&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
});
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Escopo externo é restaurado automaticamente&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
System.out.println(&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-string&amp;quot;&lt;/span&gt;&amp;gt;&amp;amp;quot;Escopo externo restaurado: &amp;amp;quot;&amp;lt;/span&amp;gt; + ROLE.get()); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// &amp;amp;quot;USER&amp;amp;quot;&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
});
}
Conexão com Virtual Threads: Por Que Isso Importa
O repositório guigomes91/virtual-threads demonstra como evitar thread pinning usando ReentrantLock em vez de synchronized. O ScopedValue é o par natural dessa estratégia: enquanto o ReentrantLock libera a carrier thread durante bloqueios, o ScopedValue garante que o contexto seja propagado corretamente para os milhões de Virtual Threads sem explosão de memória.
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// ✅ Padrão completo: Virtual Thread + ReentrantLock + ScopedValue&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;ModernRequestHandler&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">static</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; ScopedValue&amp;amp;lt;RequestContext&amp;amp;gt; CTX = ScopedValue.newInstance();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">final</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;Lock&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;lock&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">new</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title class_&amp;quot;&lt;/span&gt;&amp;gt;ReentrantLock&amp;lt;/span&amp;gt;();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">public</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;handle&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;(HttpRequest request)&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">var</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;context&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; RequestContext.from(request);
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// 1. Propaga contexto imutável via ScopedValue&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
ScopedValue.where(CTX, context).run(() -&amp;amp;gt; {
lock.lock(); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// 2. ReentrantLock evita pinning da Virtual Thread&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">try</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; {
processWithContext(); &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// carrier thread é liberada durante I/O&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
} &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">finally</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; {
lock.unlock();
}
});
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// 3. Contexto invalidado automaticamente após o run()&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
}
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">private</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-keyword&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">void</span></span>&lt;/span&gt;&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-title function_&amp;quot;&lt;/span&gt;&amp;gt;processWithContext&amp;lt;/span&amp;gt;&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-params&amp;quot;&lt;/span&gt;&amp;gt;()&amp;lt;/span&amp;gt; {
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-type&amp;quot;&lt;/span&gt;&amp;gt;RequestContext&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-variable&amp;quot;&lt;/span&gt;&amp;gt;ctx&amp;lt;/span&amp;gt; &amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-operator&amp;quot;&lt;/span&gt;&amp;gt;=&amp;lt;/span&amp;gt; CTX.get();
&amp;lt;span class=&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-string&quot;</span>&gt;&amp;quot;hljs-comment&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=<span class=<span class="hljs-string">"hljs-string"</span>>&quot;hljs-comment&quot;</span>&gt;<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// ... lógica de negócio usando o contexto&amp;lt;/span&amp;gt;&lt;/span&gt;</span></span>
}
}
Histórico de Evolução e Status no Java 25
| Java | JEP | Status |
|---|---|---|
| 20 | 429 | Incubator |
| 21 | 446 | 1º Preview |
| 22 | 464 | 2º Preview |
| 23 | 481 | 3º Preview |
| 24 | 487 | 4º Preview |
| 25 (LTS) | 506 | ✅ Finalizado |
A única mudança na finalização: ScopedValue.orElse() não aceita mais null como argumento. A API chegou estável, sem flags de preview.
Quando NÃO usar ScopedValue
ScopedValue não é um substituto direto para todo caso de ThreadLocal. Há cenários em que ThreadLocal ainda é apropriado:
- Estado mutável por design: Se você precisa acumular dados ao longo de uma thread (ex.: contadores, listas que crescem),
ThreadLocalainda faz sentido. - Integração com código legado: Frameworks como Spring e Hibernate usam
ThreadLocalinternamente. A migração deve ser gradual. - Escopos verdadeiramente abertos: Se o valor precisa sobreviver além do escopo da chamada de método (ex.: dados mantidos entre requisições na mesma thread de um pool),
ScopedValuenão é a ferramenta certa.
Conclusão
O ScopedValue não é apenas uma melhoria incremental, é um componente fundamental para a arquitetura de sistemas modernos em Java. Ao forçar a imutabilidade e restringir o tempo de vida dos dados ao escopo da tarefa, ele oferece a segurança e a leveza necessárias para que as Virtual Threads alcancem seu potencial máximo de vazão sem comprometer a estabilidade da memória.
Com o Java 25 (LTS) finalizando a API, não há mais razão para usar --enable-preview. É hora de considerar o ScopedValue como o padrão para propagação de contexto em qualquer código novo.
Referências
- JEP 506: Scoped Values (Final)
- JEP 444: Virtual Threads
- JEP 505: Structured Concurrency (Final)
- Repositório: guigomes91/virtual-threads
- Java Coding Problems, Second Edition — Anghel Leonard
Publicado por: Guilherme Gomes - 24/05/2026 17:27
Caramelo.dev