Skip to content

Commit 1f613c8

Browse files
committed
fix: review and restructure the roadmap
1 parent a90e80e commit 1f613c8

12 files changed

Lines changed: 1080 additions & 267 deletions

File tree

  • 02 - Configurando o Ambiente/2.2 - Maven e Gradle
  • 03 - Dominando o Java/3.1 - Recursos Modernos do Java 21 e 25
  • 04 - Intermediário/4.2 - JSON com Jackson
  • 05 - Frameworks
  • 06 - Deploy e DevOps
  • 07 - Aprendizado Contínuo/7.1 - Padrões de Projeto
  • 08 - Tópicos Avançados/8.3 - Otimização de Performance e JVM

02 - Configurando o Ambiente/2.2 - Maven e Gradle/readme.md

Lines changed: 3 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -554,129 +554,11 @@ zipStorePath=wrapper/dists
554554

555555
> **Regra prática:** em projeto legado, siga o que já existe. Em projeto novo, use Gradle com Kotlin DSL se a equipe topar a curva de aprendizado; caso contrário, Maven é sempre uma escolha segura.
556556
557+
557558
---
558559

559560
## GraalVM Native Image
560561

561-
O **GraalVM Native Image** compila sua aplicação Java para um **executável nativo** usando AOT (Ahead-of-Time compilation), eliminando a JVM em tempo de execução.
562-
563-
### O que é compilação AOT
564-
565-
Compilação tradicional Java:
566-
```
567-
Código .java → Bytecode .class → JVM interpreta/JIT compila → Execução
568-
```
569-
570-
Compilação AOT com GraalVM:
571-
```
572-
Código .java + Análise estática de tudo → Executável nativo binário → Execução direta
573-
```
574-
575-
**Resultado:** startup em ~50ms (vs ~3s com JVM), uso de memória 10x menor, binário único sem dependências externas — ideal para **serverless, containers, microsserviços**.
576-
577-
### Configurar no pom.xml
578-
579-
```xml
580-
<!-- Adicionar o perfil native -->
581-
<profiles>
582-
<profile>
583-
<id>native</id>
584-
<build>
585-
<plugins>
586-
<plugin>
587-
<groupId>org.graalvm.buildtools</groupId>
588-
<artifactId>native-maven-plugin</artifactId>
589-
<version>0.10.3</version>
590-
<extensions>true</extensions>
591-
<executions>
592-
<execution>
593-
<id>build-native</id>
594-
<goals>
595-
<goal>compile-no-fork</goal>
596-
</goals>
597-
<phase>package</phase>
598-
</execution>
599-
<execution>
600-
<id>test-native</id>
601-
<goals>
602-
<goal>test</goal>
603-
</goals>
604-
<phase>test</phase>
605-
</execution>
606-
</executions>
607-
<configuration>
608-
<!-- Nome do executável gerado -->
609-
<imageName>sistema-financeiro</imageName>
610-
<!-- Argumentos para o compilador nativo -->
611-
<buildArgs>
612-
<buildArg>--no-fallback</buildArg>
613-
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
614-
<!-- Otimização máxima (build mais lento, binário menor) -->
615-
<buildArg>-O3</buildArg>
616-
</buildArgs>
617-
</configuration>
618-
</plugin>
619-
620-
<!-- Spring Boot 3+ tem suporte nativo integrado -->
621-
<plugin>
622-
<groupId>org.springframework.boot</groupId>
623-
<artifactId>spring-boot-maven-plugin</artifactId>
624-
<configuration>
625-
<image>
626-
<!-- Gerar imagem Docker nativa com Buildpacks -->
627-
<name>minha-empresa/sistema-financeiro:native</name>
628-
<builder>paketobuildpacks/builder-jammy-tiny</builder>
629-
<env>
630-
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
631-
</env>
632-
</image>
633-
</configuration>
634-
</plugin>
635-
</plugins>
636-
</build>
637-
</profile>
638-
</profiles>
639-
```
640-
641-
### Build nativo
642-
643-
```bash
644-
# Compilar para executável nativo (requer GraalVM instalado)
645-
mvn -Pnative package
646-
647-
# O executável estará em:
648-
ls -lh target/sistema-financeiro
649-
# -rwxr-xr-x 1 user group 52M sistema-financeiro
650-
651-
# Executar — sem JVM, startup em ~50ms
652-
./target/sistema-financeiro
653-
654-
# Gerar imagem Docker nativa (não precisa GraalVM local)
655-
mvn spring-boot:build-image -Pnative
656-
docker run --rm minha-empresa/sistema-financeiro:native
657-
```
658-
659-
### Instalar GraalVM
660-
661-
```bash
662-
# Via SDKMAN (recomendado)
663-
sdk install java 21.0.4-graal
664-
sdk use java 21.0.4-graal
665-
666-
# Verificar
667-
java -version
668-
# java version "21.0.4" 2024-07-16 LTS
669-
# Java(TM) SE Runtime Environment GraalVM EE 21.0.4+8.1-LRE (build 21.0.4+8-jvmci-23.1-b41)
670-
671-
# Instalar native-image (necessário para compilação AOT)
672-
gu install native-image
673-
```
674-
675-
### Limitações do Native Image
676-
677-
- **Reflexão precisa ser declarada:** código que usa `Class.forName()` ou frameworks que usam reflexão extensivamente (como Spring) precisam de hints
678-
- **Build demora muito:** um build nativo pode levar 5-15 minutos vs 30 segundos com JVM
679-
- **Sem hot reload:** não é possível modificar e recarregar código em runtime
680-
- **Spring Boot 3+ mitiga a maioria:** com AOT hints gerados automaticamente
562+
GraalVM Native Image usa AOT (Ahead-of-Time compilation) para transformar sua aplicação em um executável nativo, sem JVM em runtime. O resultado é startup em ~50ms, consumo de memória dramaticamente menor e um binário único — características valiosas para serverless e microsserviços com muitas instâncias.
681563

682-
> **Quando usar:** lambdas, functions serverless, CLIs, microsserviços com muitas instâncias (para reduzir custo de memória em Kubernetes). Para aplicações monolíticas com tempo de startup irrelevante, a JVM ainda é mais vantajosa.
564+
Entender por que o Native Image existe e por que ele tem limitações específicas com reflexão requer compreender o que o ClassLoader faz, o ciclo de JIT compilation e por que um fat JAR do Spring Boot pode levar vários segundos para inicializar. Esse contexto está coberto no módulo 8.3 (Otimização de Performance e JVM), que inclui os detalhes completos de configuração, hints de reflexão, instalação do GraalVM e a decisão de quando o custo de build de 5-15 minutos compensa.

03 - Dominando o Java/3.1 - Recursos Modernos do Java 21 e 25/readme.md

Lines changed: 4 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -584,131 +584,15 @@ mapa.forEach((_, valor) -> processar(valor));
584584

585585
---
586586

587-
## Virtual Threads (Java 21)
588-
589-
Virtual Threads são threads "leves" gerenciadas pela JVM, criadas em milhares sem o custo das threads de sistema operacional.
590-
591-
**Problema que resolve:** escalabilidade de I/O bloqueante sem precisar de programação reativa complexa.
592-
593-
### O problema que Virtual Threads resolvem
594-
595-
```
596-
Thread de S.O. tradicional:
597-
- ~1MB de memória de stack
598-
- Custo alto de criação e troca de contexto
599-
- Servidor com 16GB de RAM: máximo ~16.000 threads simultâneas
600-
601-
Virtual Thread:
602-
- ~few KB de memória
603-
- Gerenciada pela JVM sobre um pool de carrier threads
604-
- Servidor com 16GB de RAM: milhões de virtual threads simultâneas
605-
```
606-
607-
### Como criar Virtual Threads
608-
609-
```java
610-
// Forma 1: Thread.ofVirtual()
611-
Thread vt = Thread.ofVirtual()
612-
.name("vt-processamento")
613-
.start(() -> {
614-
// Código que pode fazer I/O bloqueante com segurança
615-
var resultado = repositorio.buscarDados(id); // bloqueia, mas não desperdiça
616-
processar(resultado);
617-
});
618-
619-
// Forma 2: ExecutorService com virtual threads (mais comum)
620-
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
621-
for (var pedido : listaDePedidos) {
622-
executor.submit(() -> processarPedido(pedido));
623-
}
624-
} // aguarda todas terminarem ao fechar o try
625-
626-
// Forma 3: com structured concurrency (Java 21+)
627-
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
628-
var futuroPagamento = scope.fork(() -> verificarPagamento(pedidoId));
629-
var futuroEstoque = scope.fork(() -> verificarEstoque(pedidoId));
630-
var futuroFraude = scope.fork(() -> analisarFraude(pedidoId));
631-
632-
scope.join().throwIfFailed(); // aguarda todos e propaga erros
633-
634-
var pagamento = futuroPagamento.get();
635-
var estoque = futuroEstoque.get();
636-
var fraude = futuroFraude.get();
637-
638-
return new ResultadoVerificacao(pagamento, estoque, fraude);
639-
}
640-
```
641587

642-
### Quando usar Virtual Threads
643-
644-
```java
645-
// IDEAL: operações de I/O bloqueante
646-
// - Chamadas HTTP a APIs externas
647-
// - Consultas ao banco de dados
648-
// - Leitura/escrita de arquivos
649-
// - Chamadas a filas de mensagens (Kafka, RabbitMQ)
650-
651-
@GetMapping("/pedido/{id}/detalhes")
652-
public PedidoDetalhes obterDetalhes(@PathVariable UUID id) {
653-
// Com Virtual Threads no Spring Boot 3.2+, cada request já roda em uma virtual thread
654-
// Não precisa de WebFlux/Reactive — código imperativo simples
655-
var pedido = pedidoRepo.findById(id).orElseThrow(); // I/O bloqueante — OK
656-
var pagamento = pagamentoClient.buscar(id); // HTTP bloqueante — OK
657-
var rastreio = logisticaClient.buscar(id); // HTTP bloqueante — OK
658-
659-
return new PedidoDetalhes(pedido, pagamento, rastreio);
660-
}
661-
```
662-
663-
### Quando NÃO usar Virtual Threads
664-
665-
```java
666-
// NÃO USAR 1: operações CPU-bound (não há benefício)
667-
// Virtual threads não ajudam quando o CPU está ocupado, não esperando I/O
668-
public BigDecimal calcularSimulacaoMonteCarlo(int iteracoes) {
669-
// Isso vai no pool de threads tradicional (ForkJoinPool)
670-
return IntStream.range(0, iteracoes)
671-
.parallel()
672-
.mapToDouble(i -> simular())
673-
.average()
674-
.orElse(0);
675-
}
676-
677-
// NÃO USAR 2: synchronized com monitor (causa "pinning" da carrier thread)
678-
// PROBLEMÁTICO com virtual threads:
679-
public synchronized void processarComSynchronized() {
680-
// A virtual thread "prega" (pins) a carrier thread durante todo o bloqueio
681-
buscarDoBanco(); // I/O aqui bloqueia a carrier thread inteira — perde o benefício
682-
}
588+
## Virtual Threads (Java 21)
683589

684-
// CORRETO: usar ReentrantLock em vez de synchronized quando há I/O interno
685-
private final ReentrantLock lock = new ReentrantLock();
590+
Virtual Threads são o mecanismo que permite escrever código I/O bloqueante com a escalabilidade de código reativo, sem a complexidade de Mono/Flux. Criadas em milhões com custo de memória de poucos kilobytes cada, elas mudam a relação entre concorrência e simplicidade de código.
686591

687-
public void processarComLock() {
688-
lock.lock();
689-
try {
690-
buscarDoBanco(); // Virtual thread pode ser suspensa aqui — OK
691-
} finally {
692-
lock.unlock();
693-
}
694-
}
695-
```
592+
O funcionamento interno — carrier threads, mounting/unmounting, o problema de pinning com synchronized — está coberto no módulo 3.4, onde o tema é tratado junto com ExecutorService, race conditions e as demais ferramentas de concorrência. A configuração do Spring Boot para habilitar virtual threads por request também está lá.
696593

697-
### Habilitando no Spring Boot 3.2+
594+
Para referência rápida: `spring.threads.virtual.enabled=true` em `application.properties` é suficiente no Spring Boot 3.2+.
698595

699-
```java
700-
// application.properties
701-
// spring.threads.virtual.enabled=true
702-
703-
// Ou via código
704-
@Bean
705-
public TomcatProtocolHandlerCustomizer<?> virtualThreadsCustomizer() {
706-
return protocolHandler ->
707-
protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
708-
}
709-
```
710-
711-
---
712596

713597
## Resumo visual das features por versão
714598

04 - Intermediário/4.2 - JSON com Jackson/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 4.2 — JSON com Jackson
22

3-
Jackson é a biblioteca de serialização/desserialização JSON mais usada no ecossistema Java. É a padrão do Spring Boot e suporta desde casos simples até cenários complexos com tipos genéricos, customizações e módulos de extensão.
3+
Jackson é a biblioteca que o Spring Boot usa para converter objetos Java em JSON e vice-versa. Na maioria dos projetos, ela funciona transparentemente — até o dia em que não funciona. `UnrecognizedPropertyException` quando o JSON de entrada tem um campo que seu DTO não mapeia. `InvalidDefinitionException` porque o `ObjectMapper` não sabe serializar `LocalDateTime` sem o `JavaTimeModule`. `MismatchedInputException` ao deserializar um array para um tipo genérico sem `TypeReference`. Este guia cobre o suficiente para você entender o que está acontecendo quando essas exceções aparecem, e como configurar o Jackson corretamente desde o início.
44

55
---
66

05 - Frameworks/5.3 - Spring Security/readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ Spring Security é o framework de segurança padrão para aplicações Java. Ele
6464

6565
A partir do Spring Security 5.7+, não se usa mais `extends WebSecurityConfigurerAdapter`. Toda a configuração é feita via `SecurityFilterChain` bean.
6666

67+
Vale notar: o `SecurityFilterChain` é uma aplicação direta do padrão Chain of Responsibility da GoF. Cada `Filter` na cadeia decide se processa a requisição e a passa adiante ou a intercepta. Quando você implementa `OncePerRequestFilter` para validar o JWT, está adicionando um elo concreto nessa cadeia. Esse padrão e sua estrutura formal estão documentados no módulo 7.1.
68+
6769
### `SecurityFilterChain`
6870

6971
```java

0 commit comments

Comments
 (0)