Pular para o conteúdo principal

Aula 1: Jakarta EE e Desenvolvimento Cloud-Native

Objetivos

  • Compreender a evolução histórica do Java corporativo (J2EE → Java EE → Jakarta EE)
  • Explicar os pilares fundamentais do Jakarta EE: padrão, ubiquidade, continuidade e inovação
  • Identificar os desafios que a computação em nuvem impõe a aplicações Java tradicionais
  • Descrever a filosofia de otimização build-time do Quarkus e seus benefícios mensuráveis
  • Criar uma primeira aplicação cloud-native com Quarkus 3.31

Conteúdo

Bem-vindos ao curso de Jakarta EE e Quarkus! Nesta primeira aula, vamos estabelecer os fundamentos conceituais que guiarão todo nosso aprendizado. Não se trata apenas de aprender mais uma tecnologia, mas de compreender como o ecossistema Java evoluiu para atender às demandas da computação moderna e como você, como desenvolvedor, pode aproveitar essa evolução para construir aplicações robustas, escaláveis e prontas para a nuvem.

O desenvolvimento corporativo Java passou por uma transformação profunda nos últimos anos. O que antes era visto como pesado e complexo agora é sinônimo de produtividade, performance e modernidade. Esta jornada de transformação é exatamente o que exploraremos juntos.

Por que utilizar Jakarta EE?

Jakarta EE é mais do que um conjunto de tecnologias; é uma fundação para o desenvolvimento de aplicações Java robustas, padronizadas e modernas. Entender seus pilares é essencial para qualquer desenvolvedor corporativo.

Quando falamos de desenvolvimento corporativo, estamos nos referindo a aplicações que precisam atender a requisitos rigorosos: alta disponibilidade, escalabilidade, segurança, manutenibilidade e integração com sistemas legados. Jakarta EE foi construído especificamente para atender a esses requisitos, e suas características fundamentais refletem décadas de experiência em projetos de grande escala.

Standard (Padrão)

Jakarta EE oferece um conjunto de especificações padronizadas que definem como diferentes aspectos de uma aplicação corporativa devem funcionar. Essa padronização traz benefícios tangíveis e mensuráveis para organizações e desenvolvedores.

  • Redução de Risco Tecnológico: Quando você domina JAX-RS (especificação para APIs REST), esse conhecimento é transferível entre diferentes implementações como RESTEasy (usado pelo Quarkus), Jersey, ou Apache CXF. Isso significa que sua equipe não fica "refém" de um fornecedor específico.
  • Flexibilidade Arquitetural: A natureza modular permite que você use apenas as especificações necessárias. Para uma API simples, você pode usar apenas JAX-RS e CDI. Para uma aplicação complexa, pode adicionar JPA para persistência, JMS para mensageria, e Bean Validation para validações.
  • Evolução Controlada: As especificações evoluem de forma cuidadosa e retrocompatível. Uma aplicação escrita com JAX-RS 2.1 continuará funcionando com JAX-RS 3.0, mas você poderá aproveitar as novas funcionalidades quando necessário.

Exemplo prático: Uma empresa que desenvolveu uma API REST usando Spring pode migrar gradualmente para Jakarta EE simplesmente trocando as anotações @RestController por @Path, mantendo a lógica de negócio intacta.

Ubíquo (Onipresente)

A ubiquidade do Jakarta EE não é apenas uma questão de popularidade, mas de ecossistema. Essa característica impacta diretamente na viabilidade de longo prazo dos seus projetos.

  • Governança Independente: Mantido pela Eclipse Foundation, uma organização sem fins lucrativos, Jakarta EE não está sujeito às mudanças estratégicas de uma única empresa. Isso garante estabilidade e continuidade para investimentos de longo prazo.
  • Implementações Diversas: Desde servidores completos como WildFly e TomEE até runtimes otimizados como Quarkus e Helidon, você tem opções para diferentes cenários: monólitos tradicionais, microsserviços, containers, ou até mesmo compilação nativa.
  • Ecossistema Maduro: Ferramentas de desenvolvimento (IDEs, profilers, monitoring), bibliotecas complementares, e uma vasta comunidade de desenvolvedores experientes facilitam o desenvolvimento e a manutenção.

Na prática, isso significa que o conhecimento que você adquire não se torna obsoleto quando uma empresa muda sua estratégia ou quando você muda de emprego.

Continuidade

A continuidade vai além da simples compatibilidade — é sobre preservar investimentos e conhecimento ao longo do tempo.

  • Compatibilidade de Longo Prazo: Java mantém compatibilidade retroativa de forma quase religiosa. Código escrito há 20 anos ainda compila e executa em JVMs modernas. Jakarta EE segue a mesma filosofia.
  • Evolução Natural: Jakarta EE é a continuação natural do Java EE. Não é uma reescrita ou uma nova tecnologia, mas uma evolução cuidadosa que preserva investimentos existentes enquanto adiciona capacidades modernas.
  • Ecossistema Estabelecido: Milhões de aplicações já rodam em produção usando tecnologias baseadas em especificações Jakarta EE. Isso significa documentação abundante, problemas conhecidos e solucionados, e uma base sólida de conhecimento.

Inovação

Paradoxalmente, a estabilidade do Jakarta EE não impede a inovação — na verdade, ela a facilita.

  • Base Sólida para Inovação: Quando você tem APIs estáveis e bem definidas, pode focar na inovação na implementação. O Quarkus é o exemplo perfeito: ele implementa as mesmas APIs que você já conhece, mas com otimizações revolucionárias para performance e uso de memória.
  • Desenvolvimento Orientado pela Comunidade: O processo aberto de desenvolvimento de especificações permite que a comunidade contribua com casos de uso reais e requisitos emergentes. Features como Virtual Threads no Java 21 são rapidamente incorporadas às especificações.
  • Resposta às Demandas da Nuvem: Jakarta EE 10 introduziu o Core Profile especificamente para microsserviços e deployment em containers. Jakarta EE 11 foca em performance e integração com recursos modernos do Java.

Um Pouco de História: A Evolução do Java Corporativo

Compreender a história do Java corporativo é fundamental para entender por que Jakarta EE existe na sua forma atual e para onde ele está indo. Essa evolução reflete não apenas mudanças tecnológicas, mas também mudanças na forma como pensamos sobre arquitetura de software, deployment e operações.

Era J2EE (1999-2006): Início Poderoso, mas Complexo

1999 (J2EE 1.2): O Nascimento do Java Corporativo

O J2EE 1.2 foi revolucionário para sua época. Antes dele, não existia um padrão unificado para desenvolvimento de aplicações empresariais em Java.

  • Tecnologias Introduzidas: Servlets (para web), JSP (para interfaces dinâmicas), EJB 1.0 (para lógica de negócio distribuída), e JMS (para mensageria assíncrona).
  • Impacto: Pela primeira vez, era possível construir aplicações corporativas completas usando apenas tecnologias padronizadas do Java.
  • Limitações: A implementação era extremamente complexa. Um simples EJB exigia múltiplas interfaces e arquivos de configuração XML verbosos.

2003 (J2EE 1.4): O Auge da Complexidade

O J2EE 1.4 representou tanto o ápice da funcionalidade quanto da complexidade.

  • Funcionalidades Avançadas: Web Services com JAX-RPC, conectores JCA para integração com sistemas legados, e um modelo de segurança robusto.
  • Problema Central: A curva de aprendizado era íngreme demais. Desenvolvedores passavam mais tempo lutando com a configuração do que resolvendo problemas de negócio.
  • Consequência Histórica: Foi exatamente em resposta a essa complexidade que Rod Johnson criou o Spring Framework em 2003, oferecendo uma alternativa mais simples e produtiva.

Era Java EE (2006-2018): A Revolução da Simplicidade

2006 (Java EE 5): A Grande Revolução

O Java EE 5 representou uma completa reimaginação de como o desenvolvimento corporativo Java deveria funcionar.

  • Introdução Massiva de Anotações: Anotações como @Stateless, @Entity, e @WebService eliminaram a necessidade de XML verboso.
  • JPA (Java Persistence API): Substituiu o complexo Entity Beans 2.x por um modelo muito mais simples e intuitivo, inspirado no Hibernate.
  • EJB 3.0: Uma reescrita completa que transformou EJBs de monstros de complexidade em POJOs anotados.
  • Impacto na Produtividade: Estudos da época mostraram que a produtividade dos desenvolvedores aumentou em 40-60% com Java EE 5 comparado ao J2EE 1.4.

2009 (Java EE 6): Foco na Coesão e Leveza

  • CDI (Contexts and Dependency Injection): Unificou os diferentes modelos de injeção de dependência.
  • Web Profile: Uma versão mais leve da plataforma, ideal para aplicações web que não precisam de funcionalidades como EJB ou JMS.
  • Bean Validation: Padronizou a validação de dados através de anotações.

2017 (Java EE 8): O Último Grande Lançamento da Oracle

  • Suporte a HTTP/2, JSON-B, Security API, Reactive Programming.
  • O Grande Evento: Em setembro de 2017, a Oracle doou toda a propriedade intelectual do Java EE para a Eclipse Foundation. A transferência envolveu 13,5 milhões de linhas de código em 95 mil arquivos.
observação

A transferência envolveu 13,5 milhões de linhas de código em 95 mil arquivos. Foi como doar a planta completa de uma cidade, com toda a sua engenharia e história, para que a comunidade pudesse mantê-la e expandi-la de forma independente.

Era Jakarta EE (2019 — Hoje): Renascimento para a Nuvem

2019 (Jakarta EE 8): Transição de governança — tecnicamente idêntico ao Java EE 8, mas sob novo modelo de governança.

2020 (Jakarta EE 9): O "Big Bang" — mudança do namespace javax.* para jakarta.*, rompendo amarras legais e permitindo inovação.

2022 (Jakarta EE 10): Core Profile ultra-leve para microsserviços, CDI Lite para compilação AOT.

2025 (Jakarta EE 11): Jakarta Data, Virtual Threads nativas, observabilidade aprimorada.

O Cenário Mudou: O Desafio da Nuvem

A computação em nuvem não é apenas uma mudança de onde as aplicações rodam — é uma mudança fundamental em como elas devem ser projetadas, desenvolvidas e operadas.

O Dilema do Java Tradicional em Contêineres:

  • Startup Lento (Cold Start): Servidores de aplicação tradicionais podem levar 30 segundos a vários minutos para iniciar completamente. Em ambientes de auto-scaling, isso é proibitivo.
  • Alto Consumo de Memória: Um servidor de aplicação tradicional consome tipicamente 200-500MB de RAM apenas para estar disponível.
  • Modelo de Deploy Desalinhado: O modelo de "deploy de WAR" foi projetado para servidores long-running, não para containers imutáveis e descartáveis.
important

Aplicações em nuvem precisam ser leves e rápidas. O conceito de "lightweight" não é apenas sobre usar menos recursos — é sobre ser responsivo às demandas dinâmicas do ambiente cloud.

O Novo Paradigma — Aplicações Cloud-Native:

  • Startup Rápido (< 1 segundo): Para responder rapidamente a mudanças de demanda
  • Baixo Uso de Memória (< 100MB): Para maximizar densidade de deployment
  • Otimização Build-Time: Mover processamento do runtime para build-time
  • Stateless: Para permitir scaling horizontal sem complexidade

A Resposta: Quarkus, o Java Supersonic Subatomic

Quarkus representa uma reimaginação fundamental de como aplicações Java podem ser otimizadas para a nuvem, mantendo a produtividade e familiaridade que os desenvolvedores Java valorizam.

A Filosofia da Otimização em Tempo de Compilação

A "magia" do Quarkus está em sua filosofia: mover o máximo de processamento do runtime para o build time.

Java Tradicional (JIT — Just In Time):

  • Carregamento dinâmico de classes, reflection em runtime, configuração dinâmica, otimização JIT gradual.

Quarkus (AOT — Ahead of Time):

  • Análise estática completa durante a compilação, pre-boot de frameworks, configuração estática resolvida em build-time, suporte a compilação nativa via GraalVM.
dica

Benefícios Mensuráveis:

  1. Startup: De 30-60 segundos para 0.05 segundos (99% de redução)
  2. Memória: De 200-500MB para 20-50MB (80-90% de redução)
  3. Throughput: Performance comparável ou superior mesmo com menos recursos
  4. Densidade: 5-10x mais instâncias por máquina virtual

Comparativo de Performance (REST + CRUD com Banco de Dados):

MétricaQuarkus NativoQuarkus JVMStack Tradicional
Startup0.042s2.033s9.5s
Memória (RSS)28 MB145 MB209 MB
Throughput25,000+ RPS23,000+ RPS20,000 RPS

Quarkus e Jakarta EE: O Melhor dos Dois Mundos

O Quarkus implementa as especificações Jakarta EE com otimizações revolucionárias:

  • Jakarta REST (JAX-RS): REST com RESTEasy Reactive otimizado para non-blocking I/O
  • Jakarta Persistence (JPA): Hibernate ORM pré-configurado e otimizado em build-time
  • Jakarta CDI: ArC container otimizado para build-time analysis
// Este código funciona identicamente em qualquer runtime Jakarta EE
@Path("/products")
@ApplicationScoped
public class ProductResource {

@Inject
ProductService productService; // CDI padrão

@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Product> getProducts() { // JAX-RS padrão
return productService.findAll(); // JPA padrão por baixo
}
}

A diferença está na implementação: o mesmo código que leva 30 segundos para estar disponível em um servidor tradicional fica pronto em 0.1 segundos no Quarkus.

O conhecimento em Jakarta EE é seu investimento de longo prazo. Quarkus é simplesmente uma forma moderna e otimizada de executá-lo com performance revolucionária.

A Estratégia de Extensões

O Quarkus organiza funcionalidades através de "extensões" — cada uma otimizada para build-time processing:

  • quarkus-resteasy-reactive — Jakarta REST otimizado para performance
  • quarkus-hibernate-orm-panache — JPA com Active Record pattern
  • quarkus-smallrye-openapi — Documentação automática de APIs
  • quarkus-micrometer — Métricas e observabilidade
  • quarkus-kafka — Messaging assíncrono otimizado

Arquitetura: Tradicional vs. Quarkus

AspectoArquitetura TradicionalArquitetura Quarkus
DeployWAR/EAR implantado em servidor de aplicaçãoJAR executável autocontido
ResponsabilidadesContainers lógicos separados (Web, EJB, Persistence)Arquitetura unificada com CDI gerenciando lifecycle
OtimizaçãoGrandes monólitos long-runningMicrosserviços cloud-native com lifecycle dinâmico
VantagensFuncionalidades ricas e madurasStartup ultra-rápido, baixa memória, cloud-ready
DesvantagensStartup lento, alta memóriaEcossistema mais novo, requer mudança de mindset

Laboratório 1 — Nosso Primeiro Projeto Cloud-Native

Vamos criar nossa primeira aplicação e experimentar a produtividade do Quarkus.

Objetivo: Criar uma API REST em menos de 5 minutos e experimentar o ciclo de desenvolvimento rápido com live coding (hot reload).

Pré-requisitos:

  • JDK 21 ou superior instalado e configurado
  • Quarkus CLI instalada (recomendado) ou Maven/Gradle — A instalação da Quarkus CLI pode ser feita seguindo as instruções em Quarkus - Get Started.
  • IDE de sua preferência (IntelliJ IDEA, VS Code, Eclipse)
  • Conexão com internet para download de dependências

Passo 1: Criando a Aplicação

Use a Quarkus CLI para criar um novo projeto:

quarkus create app br.upf.ads175:lab01-hello-quarkus \
--extension='rest,rest-jackson' \
--java=21
  • br.upf.ads175:lab01-hello-quarkus — GroupId e ArtifactId do projeto
  • --extension='rest,rest-jackson' — Adiciona suporte a REST APIs e JSON binding
  • --java=21 — Especifica Java 21 como versão target

Se você não tem a CLI instalada, pode usar Maven:

mvn io.quarkus.platform:quarkus-maven-plugin:3.31.0:create \
-DprojectGroupId=br.upf.ads175 \
-DprojectArtifactId=aula1-hello-quarkus \
-Dextensions='rest,rest-jackson' \
-DjavaVersion=21

Passo 2: Explorando a Estrutura do Projeto

aula1-hello-quarkus/
├── pom.xml # Configuração Maven
├── src/main/
│ ├── docker/ # Dockerfiles para deployment
│ ├── java/br/upf/ads175/
│ │ └── GreetingResource.java # Seu primeiro REST endpoint
│ └── resources/
│ └── application.properties # Configurações da aplicação
└── src/test/
└── java/br/upf/ads175/
└── GreetingResourceTest.java # Testes automatizados

Passo 3: Experimentando o Live Coding

# Com Maven Wrapper
./mvnw quarkus:dev

# Ou com Quarkus CLI
quarkus dev

Saída esperada:

__  ____  __  _____   ___  __ ____  ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/

INFO [io.quarkus] aula1-hello-quarkus 1.0.0-SNAPSHOT on JVM started in 1.234s.
INFO [io.quarkus] Profile dev activated. Live Coding activated.

Teste: abra http://localhost:8080/hello no navegador.

Passo 4: Experimentando Live Reload

Com a aplicação rodando, modifique GreetingResource.java:

@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Olá de Jakarta EE com Quarkus! Live coding funcionando!";
}

Salve o arquivo e atualize a página do navegador. A mudança aparecerá instantaneamente — sem compilação manual, sem reinicialização.

Sem compilar, sem empacotar, sem reiniciar. Apenas salve e atualize o navegador. Este é o Developer Joy que o Quarkus oferece.

Passo 5: Adicionando uma API JSON

Crie uma classe ProdutoResource.java:

package br.upf.ads175;

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.math.BigDecimal;
import java.util.List;

@Path("/produtos")
public class ProdutoResource {

@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Produto> listarProdutos() {
return List.of(
new Produto(1L, "Notebook", new BigDecimal("2500.00")),
new Produto(2L, "Mouse", new BigDecimal("50.00")),
new Produto(3L, "Teclado", new BigDecimal("150.00"))
);
}

@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Produto buscarProduto(@PathParam("id") Long id) {
return new Produto(id, "Produto " + id, new BigDecimal("100.00"));
}
}

record Produto(Long id, String nome, BigDecimal preco) {}

Teste: http://localhost:8080/produtos e http://localhost:8080/produtos/1.

Passo 6: Testando Performance de Startup

Pare (Ctrl+C) e reinicie. Note o tempo de startup — tipicamente entre 1-3 segundos, comparado aos 30-60 segundos de um servidor tradicional.

Passo 7: Explorando o Dev UI

Acesse http://localhost:8080/q/dev-ui para Configuration, Extensions, Health Checks, Metrics e OpenAPI.

E o Spring?

A visão moderna não é de rivalidade, mas de coexistência produtiva e inovação através da competição saudável.

  • Spring: Excelente para equipes que valorizam convenção sobre configuração e ecossistema altamente integrado.
  • Jakarta EE/Quarkus: Ideal para equipes que preferem padrões abertos, performance máxima em nuvem e compatibilidade de longo prazo.

Especificações Compartilhadas:

// Este código funciona tanto em Spring quanto em Jakarta EE
@Entity
@Table(name = "produtos")
public class Produto {
@Id
@GeneratedValue
private Long id;

@NotBlank // Bean Validation
private String nome;
}
dica

Foque em dominar os conceitos fundamentais (injeção de dependência, arquitetura web, padrões de persistência, testing) que são transferíveis entre ecossistemas. A sintaxe específica é secundária ao entendimento profundo dos princípios.

Exercícios (Checkpoints)

  1. Explique com suas palavras por que a mudança de namespace javax.* para jakarta.* foi necessária na evolução do Java corporativo.
  2. Compare os tempos de startup e consumo de memória entre Java tradicional e Quarkus. O que possibilita essa diferença?
  3. Crie um novo endpoint REST no projeto do Laboratório 1 que retorne uma lista de categorias com id e nome.
  4. Descreva três cenários onde Jakarta EE/Quarkus seria preferível ao Spring, e três cenários onde Spring seria preferível.
  5. Pesquise e liste três extensões do Quarkus que seriam úteis para uma aplicação de e-commerce.

Referências