Mostrando postagens com marcador Java. Mostrar todas as postagens
Mostrando postagens com marcador Java. Mostrar todas as postagens

terça-feira, 27 de janeiro de 2026

🗂️ Acessando Arquivos Usando Java com Samba JCIFS

1. Introdução

Capacidades de intercâmbio de arquivos entre plataformas são cruciais para a operação de redes de computadores. Podemos fornecê-las com o protocolo Server Message Block (SMB) e sua implementação de código aberto amplamente difundida, o Samba.

Neste tutorial, aprenderemos como acessar recursos Samba a partir do Java, sem a necessidade de montar ou mapear uma unidade de rede.


2. A biblioteca JCIFS

O Common Internet File System (CIFS) é um dialeto do SMB. Usaremos a implementação codelibs JCIFS, que suporta o mais recente protocolo SMB3.

Vamos adicioná-la com a dependência do Maven:

<dependency>
    <groupId>org.codelibs</groupId>
    <artifactId>jcifs</artifactId>
    <version>3.0.1</version>
</dependency>

3. Configurando um Servidor Samba

💻 Ao longo deste tutorial, usaremos o servidor Samba configurado em uma máquina convidada do VirtualBox. Como convidado, escolhemos o servidor Ubuntu.

Em seguida, vamos configurar o adaptador de rede somente hospedeiro do VirtualBox. Então, estreitamos o intervalo de endereços DHCP para um único endereço IP: 192.168.56.101. Este truque nos poupa uma configuração de IP estático mais sofisticada.

Durante a instalação do sistema convidado, vamos adicionar o usuário `jane`. Depois, precisamos instalar o Samba e adicionar `jane` aos usuários do Samba:

$ sudo smbpasswd -a jane

Precisamos de duas pastas para os compartilhamentos:

$ mkdir /srv/samba/public /srv/samba/sambashare

Para expor as pastas, definimos a permissão 777 nelas:

$ sudo chmod 777 /srv/samba/public /srv/samba/sambashare

Agora, vamos editar o arquivo `/etc/samba/smb.conf`:

$ sudo nano /etc/samba/smb.conf

Então adicionamos duas seções para compartilhamentos:

[publicshare]
   comment = Anonymous Samba share
   path = /srv/samba/public
   read only = no
   guest ok = yes
   guest only = yes

[sambashare]
   comment = Samba on Ubuntu
   path = /srv/samba/sambashare
   read only = no
   browsable = yes

Desta forma, criamos dois compartilhamentos Samba: um `publicshare` anônimo e um `sambashare` protegido por senha.


4. Exemplo Simples

🔍 Vamos executar um código simples para ver o básico de alcançar um compartilhamento Samba. Verificaremos um arquivo localizado no `publicshare`:

// Contexto padrão
CIFSContext context = SingletonContext.getInstance();

LOGGER.info("#  Verificando se o arquivo existe");
try (SmbFile file = new SmbFile("smb://192.168.56.101/publicshare/test.txt", context)) {
    if (file.exists()) {
        LOGGER.info("Arquivo " + file.getName() + " encontrado!");
    } else {
        LOGGER.info("Arquivo " + file.getName() + " não encontrado!");
    }
}

Podemos notar os elementos necessários para estabelecer a comunicação:

  • CIFSContext mantém a configuração do cliente, credenciais e outras informações relacionadas. Aqui, é uma instância de `SingletonContext`, que fornece credenciais adequadas para uma conta anônima.
  • SmbFile, que representa qualquer tipo de recurso Samba. No nosso caso, este é um arquivo. Podemos colocá-lo em um bloco try-with-resource.

Finalmente, usamos o método `exists()` no objeto de arquivo.


5. Autenticação

🔐 Podemos criar o objeto `CIFSContext` com credenciais. Vamos listar os elementos no compartilhamento protegido por senha `sambashare`:

NtlmPasswordAuthenticator credentials = new NtlmPasswordAuthenticator(
    "WORKGROUP",    // Nome do domínio
    "jane",         // Nome de usuário
    "Test@Password" // Senha
);

// Contexto com autenticação
CIFSContext authContext = context.withCredentials(credentials);

LOGGER.info("# Fazendo login com usuário e senha");
try (SmbFile res = new SmbFile("smb://192.168.56.101/sambashare/", authContext)) {
    for (String element : res.list()) {
        LOGGER.info("Elemento encontrado " + element);
    }
}

Primeiro, criamos o objeto `NtlmPasswordAuthenticator` para armazenar as credenciais. Em seguida, chamamos o método `withCredentials()` no objeto de contexto existente. Como resultado, obtivemos um `authContext` filho com nossas credenciais. Finalmente, a função `list()` mostrou todos os componentes do compartilhamento.


6. Trabalhando com Arquivos e Diretórios

📂 O JCIFS fornece um conjunto abrangente de funções para operar em arquivos e pastas. Vamos dar uma olhada em algumas delas.

6.1. Listando e Verificando Arquivos

Com `listFiles()`, podemos listar arquivos e pastas. Ele retorna um objeto `SmbFile`, que permite o uso de muitas funções de verificação:

LOGGER.info("# Listar arquivos e pastas no compartilhamento Samba");
try (SmbFile res = new SmbFile("smb://192.168.56.101/publicshare/", context)) {
    for (SmbFile element : res.listFiles()) {
        LOGGER.info("Elemento Samba encontrado de nome: " + element.getName());
        LOGGER.info("    O elemento é arquivo ou pasta: " + (element.isDirectory() ? "pasta" : "arquivo"));
        LOGGER.info("    Tamanho: " + element.length());
        LOGGER.info("    Última modificação: " + new Date(element.lastModified()));
    }
}

Neste exemplo, iteramos por todos os itens na pasta pública. Determinamos se é um arquivo ou um diretório usando o método `isDirectory()`. Em seguida, recuperamos seu tamanho e tempo de modificação com os métodos `length()` e `getLastModified()`, respectivamente.

6.2. Criando e Excluindo Arquivos

A biblioteca JCFIS permite a criação e exclusão de arquivos e diretórios. Primeiro, vamos trabalhar com arquivos. Vamos criar e imediatamente excluir o arquivo `New_file.txt`:

LOGGER.info("# Criando e excluindo um arquivo");
String fileName = "New_file.txt";
try (SmbFile file = new SmbFile("smb://192.168.56.101/publicshare/" + fileName, context)) {
    LOGGER.info("Prestes a criar o arquivo " + file.getName() + "!");
    file.createNewFile();

    LOGGER.info("Prestes a excluir o arquivo " + file.getName() + "!");
    file.delete();
}

Criamos um objeto `SmbFile` para um arquivo ainda não existente. Em seguida, chamamos seu método `createNewFile()`. Finalmente, aplicamos a função `delete()` para remover o arquivo. Notavelmente, `createNewFile()` ignora arquivos existentes sem notificação.

6.3. Criando e Excluindo Pastas

Podemos lidar com pastas de maneira semelhante:

LOGGER.info("# Criando e excluindo uma pasta");
String newFolderName = "New_folder/";
try (SmbFile newFolder = new SmbFile("smb://192.168.56.101/publicshare/" + newFolderName, context)) {
    LOGGER.info("Prestes a criar a pasta " + newFolder.getName() + "!");
    newFolder.mkdir();

    LOGGER.info("Prestes a excluir a pasta " + newFolder.getName() + "!");
    newFolder.delete();
}

Usamos o método `mkdir()` para criar a pasta e o método `delete()` para removê-la. No caso da pasta, devemos garantir que a pasta não exista; caso contrário, `mkdir()` falhará.

👀 Vamos notar que devemos ter muito cuidado ao remover uma pasta com `delete()`. Este método percorre e exclui toda a árvore de pastas, com todos os arquivos. Além disso, ele é capaz de remover a permissão somente leitura em arquivos.

Além disso, podemos criar uma árvore de diretórios inteira com o método `mkdirs()`:

LOGGER.info("# Criando e excluindo uma subpasta com pai");
newFolderName = "New_folder/";
String subFolderName = "New_subfolder/";
try (SmbFile newSubFolder = new SmbFile("smb://192.168.56.101/publicshare/" + newFolderName + subFolderName, context)) {
    LOGGER.info("Prestes a criar a pasta " + newSubFolder.getName() + "!");
    newSubFolder.mkdirs();
}

Criamos um novo diretório, `New_subfolder`, juntamente com a pasta pai anteriormente inexistente, `New_folder`.

6.4. Copiando Arquivos

O método `copyTo()` facilita a cópia de arquivos e diretórios. Podemos usá-lo em um único arquivo ou em uma pasta. Vamos copiar todo o conteúdo do `sambashare` para o `publicshare`:

LOGGER.info("# Copiando arquivos com copyTo");
try (SmbFile source = new SmbFile("smb://192.168.56.101/sambashare/", authContext); //precisa de autenticação
    SmbFile dest = new SmbFile("smb://192.168.56.101/publicshare/", context)) { //compartilhamento público
    source.copyTo(dest);
}

Copiamos chamando `copyTo()` no recurso Samba de origem e passando o recurso de destino `dest` para este método. Notavelmente, esses recursos são compartilhamentos Samba diferentes.

Também podemos copiar arquivos entre servidores diferentes. No entanto, não podemos copiar do sistema de arquivos local, apenas entre recursos gerenciados pelo Samba.


7. Trabalhando com Fluxos (Streams)

🔄 A biblioteca fornece `SmbFileInputStream` e `SmbFileOutputStream`, que substituem as classes abstratas padrão `InputStream` e `OutputStream` do Java, respectivamente. Vamos copiar um arquivo local para o compartilhamento Samba:

LOGGER.info("# Copiando arquivos com fluxos");
try (InputStream is = new FileInputStream("/home/joe/test.txt"); //Arquivo local
     SmbFile dest = new SmbFile("smb://192.168.56.101/publicshare/test_copy.txt", context); //Recurso Samba
     OutputStream os = dest.getOutputStream()) {

    byte[] buffer = new byte[65536]; // usando buffer de 64KB
    int bytesRead;
    while ((bytesRead = is.read(buffer)) != -1) {
        os.write(buffer, 0, bytesRead);
    }
}

Lemos o arquivo local com `FileInputStream`. Em seguida, copiamos o conteúdo usando um buffer interno. Este método complementa o método `copyTo()` quando arquivos locais estão em jogo.


8. Conclusão

🎯 Neste artigo, aprendemos como acessar recursos Samba com a biblioteca JCIFS. Para testes, configuramos um servidor Samba simples. Em seguida, examinamos um recurso compartilhado e aprendemos brevemente sobre autenticação Samba.

Depois, focamos nas operações de arquivos. Primeiro, listamos arquivos e pastas e verificamos suas propriedades. Em seguida, realizamos operações de criação, cópia e exclusão em arquivos e diretórios. Finalmente, usamos a implementação JCIFS dos fluxos de E/S do Java para ler e escrever arquivos Samba.

Como sempre, o código para os exemplos está disponível no GitHub.

📝 Mapeamento para String com MapStruct: Convertendo Enums, Datas e Objetos em Java

1. Visão Geral

Ao trabalhar com aplicações Java, muitas vezes precisamos converter objetos de dados complexos em representações mais simples. Por exemplo, é comum converter tipos de dados como enums, números ou objetos aninhados para seus equivalentes em String para exibição, registro em log (logging) ou respostas de API. Nesse cenário, podemos usar o MapStruct.

Neste tutorial, vamos mapear diferentes tipos de dados para uma String.


2. Configuração do Projeto

Para demonstrar o mapeamento para String no MapStruct, podemos criar um projeto Maven simples mapstructstringmapping.

No arquivo pom.xml, vamos navegar até o diretório mapstructstringmapping e atualizar:

<dependencies>
    <!-- MapStruct -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.6.3</version>
    </dependency>

    <!-- JUnit 5 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.14.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Acima, adicionamos mapstruct para mapeamento em tempo de compilação e JUnit 5 para testes.


3. Mapeamento Simples para String

Ao trabalhar em apresentações ou mesmo em respostas de API, podemos precisar converter valores numéricos ou booleanos em strings. Um bom exemplo é quando uma entidade de banco de dados armazena a idade de um usuário como um int, mas a camada de API precisa expô-la como uma String.

Vamos examinar um exemplo direto para mostrar como usar o MapStruct para mapear um campo int para uma String. Primeiro, definimos a classe Person:

public class Person {
    private String name;
    private int age;
}

Em seguida, vamos criar a segunda classe PersonDTO:

public class PersonDTO {
    private String name;
    private String age;
}

Nos exemplos acima, as classes possuem getters e setters padrão, que o MapStruct utilizará para o mapeamento.

Agora, vamos definir a interface do mapper PersonMapper.java:

@Mapper
public interface PersonMapper {

    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    PersonDTO toDTO(Person person);
}

Em tempo de compilação, o MapStruct cria a implementação de PersonMapper. Neste caso, o MapStruct automaticamente altera o valor int de age do objeto de origem para uma String no objeto de destino quando o método toDTO() é chamado.

Vamos criar o teste unitário PersonMapperUnitTest.java e garantir que o mapeamento funciona como pretendido:

public class PersonMapperUnitTest {

    @Test
    void givenPerson_whenMapsToPersonDTO_thenFieldsAreCorrect() {

        Person person = new Person();
        person.setName("Alice");
        person.setAge(30);

        PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);

        assertEquals("Alice", dto.getName());
        assertEquals("30", dto.getAge());
    }
}

O teste confirma que o valor int da idade é traduzido para sua representação em String e que o campo name é mapeado com sucesso.


4. Conversão de Enums para String

Em Java, enums são amplamente usados para definir conjuntos fixos de variáveis, incluindo funções de usuário, status de pedidos e estados do sistema. No entanto, quando os dados são mostrados em interfaces do usuário ou tornados acessíveis através de APIs, esses valores de enum geralmente são renderizados como strings.

4.1. Definindo o Enum e as Classes de Domínio

Vamos começar definindo um enum que representa o status de um usuário:

public enum Status {
    ACTIVE,
    INACTIVE,
    PENDING
}

Para seguir em frente, vamos criar um objeto de domínio que usa este enum:

public class User {
    private String username;
    private Status status;
}

Por fim, criamos um DTO onde o valor do enum é representado como uma String:

public class UserDTO {
    private String username;
    private String status;
}

Agora, a classe User usa um enum para o campo status, enquanto UserDTO espera o mesmo valor como uma String.

4.2. Definindo o Mapper

Vamos definir uma interface de mapper que converte um User em um UserDTO:

@Mapper
public interface UserMapper {

    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDTO toDto(User user);
}

Aqui, o MapStruct detecta automaticamente que o campo de origem é um enum e o campo de destino é uma String. Não precisamos definir nenhuma lógica de mapeamento personalizada. Ele invoca o método name() do enum durante o processo de mapeamento.

Na maioria das APIs do mundo real, esse comportamento padrão é suficiente, mas é importante estar ciente disso se os nomes dos enums não corresponderem aos valores esperados pelos clientes.

4.3. Verificando o Mapeamento

Vamos escrever um teste unitário que confirma que a conversão de enum para string funciona conforme o esperado:

public class UserMapperUnitTest {

    @Test
    void shouldMapEnumToString() {

        User user = new User();
        user.setUsername("Kevin");
        user.setStatus(Status.ACTIVE);

        UserDTO dto = UserMapper.INSTANCE.toDto(user);

        assertEquals("Kevin", dto.getUsername());
        assertEquals("ACTIVE", dto.getStatus());
    }
}

Isto é o que o teste verifica:

  • O campo username é mapeado corretamente
  • O valor do enum Status.ACTIVE é convertido para sua representação em String, “ACTIVE”

Notavelmente, este comportamento funciona "pronto para uso" com MapStruct e não requer configuração adicional.


5. Mapeando Datas para String

Ao trabalhar com campos de data, muitas vezes precisamos convertê-los em representações de string formatadas antes de expô-los através de APIs ou exibi-los em interfaces do usuário. O MapStruct suporta este caso de uso através do atributo dateFormat na anotação @Mapping.

Usando este atributo, podemos definir o padrão de data exato que queremos que o MapStruct aplique durante o processo de mapeamento.

5.1. Definindo as Classes de Domínio e DTO

Vamos começar definindo uma entidade de domínio simples que contém um campo LocalDate:

public class Event {
    private String name;
    private LocalDate eventDate;
}

Em seguida, vamos definir um DTO correspondente onde o campo eventDate é representado como uma String:

public class EventDTO {
    private String name;
    private String eventDate;
}

Aqui, a classe Event representa o modelo de domínio, enquanto EventDTO é o objeto de transferência de dados usado para saída. A diferença principal é que o campo eventDate é um LocalDate no objeto de origem e uma String formatada no objeto de destino.

5.2. Criando o Mapper

Agora, vamos definir uma interface de mapper para converter um Event em um EventDTO:

@Mapper
public interface EventMapper {

    EventMapper INSTANCE = Mappers.getMapper(EventMapper.class);

    @Mapping(source = "eventDate", target = "eventDate", dateFormat = "yyyy-MM-dd")
    EventDTO toEventDTO(Event event);
}

Aqui, @Mapping especifica que o campo eventDate deve ser formatado de acordo com o padrão "yyyy-MM-dd" (por exemplo, "2024-12-31"). O MapStruct cuida da conversão do objeto LocalDate para a representação de string correspondente.

5.3. Testando a Conversão de Data

Para garantir que o mapeamento e a formatação funcionam corretamente, podemos escrever um teste unitário:

public class EventMapperUnitTest {

    @Test
    void shouldMapLocalDateToStringUsingProvidedFormat() {

        Event event = new Event();
        event.setName("Conferência");
        event.setEventDate(LocalDate.of(2024, 12, 31));

        EventDTO dto = EventMapper.INSTANCE.toEventDTO(event);

        assertEquals("Conferência", dto.getName());
        assertEquals("2024-12-31", dto.getEventDate());
    }
}

O teste acima confirma que:

  • O campo name é mapeado sem alterações
  • O objeto LocalDate é formatado corretamente no padrão especificado "yyyy-MM-dd"

O uso do atributo dateFormat é particularmente útil para garantir a consistência dos formatos de data em diferentes pontos de extremidade da API ou componentes da interface do usuário.


6. Considerações Adicionais e Melhores Práticas

Lidando com Valores Nulos

Em cenários do mundo real, os dados de origem podem conter valores nulos. O MapStruct lida com eles de forma segura por padrão, mas é importante testar e documentar o comportamento esperado em seus mapeadores.

Customizando Conversões Complexas

Para cenários mais complexos (por exemplo, formatar números com casas decimais específicas, converter objetos aninhados em strings JSON), você pode usar métodos default dentro da interface do mapper ou definir um método de mapeamento personalizado usando a anotação @Named.

Testes Abrangentes

Sempre escreva testes para seus mapeadores, cobrindo casos de uso comuns, casos de borda (valores nulos, enums desconhecidos) e formatos específicos. Isso garante que as conversões de dados permaneçam confiáveis conforme sua aplicação evolui.


7. Conclusão

Neste tutorial, exploramos como usar o MapStruct para mapear vários tipos de dados para suas representações em String. Vimos como o mapeamento direto de tipos primitivos como int funciona automaticamente, como converter valores de enum usando o método name() e como formatar objetos LocalDate usando o atributo dateFormat na anotação @Mapping.

💡 O MapStruct simplifica significativamente a conversão de dados em aplicações Java, fornecendo mapeamento seguro de tipos em tempo de compilação. Ao utilizar esses padrões, podemos manter nosso código limpo, legível e fácil de manter ao lidar com diferentes representações de dados em nossas aplicações.

quinta-feira, 22 de janeiro de 2026

🔍 Visualizando o Código-Fonte de um Arquivo .class do Java: Como Descompilar Bytecode

🔍 Visualizando o Código-Fonte de um Arquivo .class do Java

No mundo Java, o código-fonte escrito em arquivos .java é compilado para um formato intermediário chamado bytecode, armazenado em arquivos com extensão .class. Esses arquivos não contêm o código-fonte original legível, mas instruções para a Java Virtual Machine (JVM). Então, como podemos "visualizar" o código original a partir de um arquivo .class? A resposta está na descompilação – processo de reconstruir o código-fonte a partir do bytecode.


🧠 O Que é Bytecode e Por Que Precisamos Descompilar?

O bytecode é uma representação compacta e otimizada do seu programa, projetada para ser executada pela JVM. Ele não é destinado à leitura humana. No entanto, situações como análise de bibliotecas de terceiros, debugging de problemas complexos, estudos de código legado sem fonte disponível ou até recuperação de código perdido podem exigir que você visualize algo próximo ao código original. É importante ressaltar que a descompilação para fins de engenharia reversa deve respeitar os termos de licença do software e os direitos autorais.


🛠️ Ferramentas Populares para Descompilar Arquivos .class

Existem várias ferramentas robustas que convertem bytecode Java em código legível. Aqui estão as principais:

1. JD-GUI

Uma ferramenta gráfica gratuita que permite abrir arquivos .class ou .jar e navegar pela estrutura descompilada como se fosse um projeto. Ela fornece uma visualização limpa e imediata, sendo excelente para análises rápidas.

2. Bytecode Viewer

Uma ferramenta mais avançada que mostra não apenas o código descompilado (usando motores como CFR, FernFlower ou Procyon), mas também o bytecode real e o código em hexa. É ideal para desenvolvedores que querem entender a relação entre o código-fonte e as instruções da JVM.

3. CFR

É um descompilador moderno e de alta qualidade, disponível como biblioteca ou via linha de comando. Ele lida bem com recursos mais novos da linguagem, como lambdas e switch expressions, gerando um código reconstruído muito fiel.


📝 Passo a Passo Prático com JD-GUI

  1. Baixe e execute o JD-GUI a partir do site oficial.
  2. Abra seu arquivo .class ou .jar através do menu "File > Open File...".
  3. Navegue pela árvore do projeto no lado esquerdo. Ao clicar em uma classe, o código descompilado aparecerá no painel principal.
  4. Exporte o código se necessário, usando "File > Save All Sources".

⚠️ Limitações e Considerações Importantes

A descompilação não é uma mágica perfeita. Nomes de variáveis locais são perdidos, sendo substituídos por nomes genéricos (var1, var2). Comentários e formatação original são completamente removidos. Estruturas como laços for-each podem aparecer como iteradores tradicionais. Além disso, código ofuscado propositalmente pode gerar uma saída ilegível. Do ponto de vista legal, usar código descompilado para criar uma obra derivada sem permissão viola licenças de software.


🔧 Visualizando Bytecode Puro (javap)

Às vezes, você não quer o código reconstruído, mas sim inspecionar as instruções reais do bytecode. Para isso, use a ferramenta javap, que vem com o JDK. Execute no terminal: javap -c -p NomeDaClasse.class. A flag -c exibe as instruções bytecode e -p mostra membros privados. É uma análise de baixo nível valiosa para otimização ou debugging profundo.


🎯 Conclusão

Descompilar arquivos .class é uma habilidade útil no arsenal de qualquer desenvolvedor Java, seja para aprender, solucionar problemas ou analisar dependências. Ferramentas como JD-GUI e Bytecode Viewer tornam o processo acessível. No entanto, use esse conhecimento com responsabilidade ética e legal, sempre respeitando a propriedade intelectual. Lembre-se: a descompilação é uma ferramenta de análise, não de cópia. Dominar tanto o código-fonte quanto o bytecode amplia significativamente sua compreensão da plataforma Java.

🚀 Avaje: O Guia Definitivo para Conjuntos de Bibliotecas Java que Aceleram seu Desenvolvimento

O Que é o Avaje? Entendendo a Revolução nas Bibliotecas Java

Se você é desenvolvedor Java, sabe que construir aplicativos do zero, embora educativo, muitas vezes implica retrabalho e perda de tempo com soluções para problemas comuns. É aqui que entra o Avaje (anteriormente conhecido como "Avaje Libs"). Não se trata de um framework monolítico, mas sim de um conjunto coeso e moderno de bibliotecas Java de código aberto, projetadas para trabalhar harmoniosamente e eliminar a complexidade desnecessária no desenvolvimento de aplicações server-side, especialmente APIs web e sistemas baseados em microsserviços.

O projeto Avaje nasceu com a filosofia de oferecer uma stack tecnológica mais leve, intuitiva e produtiva do que as opções tradicionais, mantendo o poder e a confiabilidade da JVM. Ele foca em injeção de dependência type-safe, APIs de banco de dados mais simples, validação, serialização JSON e muito mais, tudo com uma API fluente que prioriza a experiência do desenvolvedor.


Os Pilares do Avaje: Conhecendo as Principais Bibliotecas

O ecossistema Avaje é composto por várias bibliotecas especializadas. Vamos explorar as mais importantes.

1. Avaje Inject: Injeção de Dependência sem Anotações Mágicas

A biblioteca Avaje Inject revoluciona o conceito de Injeção de Dependência (DI) em Java. Diferente de outros frameworks que dependem pesadamente de anotações de reflexão em tempo de execução, o Avaje Inject utiliza processamento de anotações em tempo de compilação. Isso significa que a verificação de dependências, a geração do grafo de componentes e a descoberta de erros acontecem durante a compilação, não em produção. O resultado? Startup mais rápido, código mais seguro e previsível, e zero overhead de reflexão para a injeção.


2. Avaje JSON: Serialização Rápida e Type-Safe

Trabalhar com JSON em Java pode ser verboso. O Avaje JSON oferece uma API de serialização e desserialização que é ao mesmo tempo poderosa e simples. Ele gera código em tempo de compilação para converter seus objetos Java em JSON e vice-versa, garantindo alto desempenho e evitando os erros comuns de reflection. Sua API builder e de leitura também são extremamente intuitivas para manipulação dinâmica de documentos JSON.


3. JPA Alternativo: Avaje Database

Para muitos, o JPA (com Hibernate) pode ser complexo e gerar comportamentos inesperados. O Avaje Database (também conhecido como Ebean) é uma ORM (Object-Relational Mapper) diferente. Ele adota uma abordagem mais declarativa e menos intrusiva, com foco em consultas type-safe (usando Query Beans gerados em tempo de compilação), suporte nativo a migrações de banco de dados (via DbMigration) e um modelo de transação mais simples. É uma opção robusta para quem busca produtividade e controle.


Por Que Considerar o Avaje para seu Próximo Projeto?

Produtividade do Desenvolvedor

A integração perfeita entre as bibliotecas, a documentação clara e o foco em APIs intuitivas significam que você passa menos tempo configurando e lutando com o framework, e mais tempo implementando lógica de negócio.


Desempenho Superior

A estratégia agressiva de uso de processamento de anotações (annotation processing) em tempo de compilação elimina a maioria das reflexões, resultando em aplicativos que inicializam em milissegundos e consomem menos memória. Ideal para ambientes serverless e de containers.


Simplicidade e Clareza

O Avaje evita a "mágica" excessiva. O código gerado é visível e o funcionamento das bibliotecas é mais transparente, facilitando a depuração e a compreensão do fluxo da aplicação por toda a equipe.


Stack Moderna e Coesa

Ao invés de juntar dezenas de bibliotecas de provedores diferentes (com possíveis conflitos), você adota um conjunto integrado e testado para as necessidades centrais de uma aplicação backend, desde a injeção de dependência até a camada de persistência.


Como Começar com o Avaje? Primeiros Passos

Iniciar é simples, especialmente se você usar um gerenciador de dependências como Maven ou Gradle. Para um projeto web básico, você normalmente adicionaria as dependências do Avaje Inject, Avaje JSON e, opcionalmente, do Avaje Database. O site oficial (avaje.io) oferece guias de início rápido detalhados. A comunidade, embora em crescimento, é ativa e o criador do projeto (Rob Bygrave) é muito presente, garantindo um suporte de qualidade.


Conclusão: Uma Alternativa Sólida e Moderna

O Avaje representa um salto de qualidade no desenvolvimento Java moderno. Se você busca uma stack que prioriza desempenho, produtividade e simplicidade sem abrir mão do poder da JVM, vale a pena investir tempo para conhecê-lo. Ele é particularmente atraente para novos projetos, APIs REST/GraphQL e sistemas onde o tempo de startup e a eficiência de recursos são críticos. Experimente, e você pode descobrir uma forma mais prazerosa e eficiente de codar em Java. 🎯

segunda-feira, 5 de janeiro de 2026

🚀 Java 25: O Que Esperar da Próxima Grande Versão da Plataforma Java?

Java 25: Olhando Para o Horizonte da Plataforma

O mundo do desenvolvimento Java está sempre em evolução, e a comunidade já começa a especular e acompanhar os primeiros indícios do que será o JDK 25. Seguindo o ciclo de lançamentos semestrais estabelecido pela Oracle, o Java 25 promete trazer novas features, melhorias de performance e refinamentos nas APIs que sustentam milhões de aplicações em todo o mundo. Neste post, exploramos o que se pode esperar desta versão, baseado no processo de desenvolvimento aberto do OpenJDK.


📅 O Ciclo de Lançamentos e o Roadmap do JDK 25

Com o modelo de lançamento rápido (six-month release cadence), o Java 25 está previsto para ser lançado em março de 2025, como sucessor do JDK 24. É crucial entender que, nesta fase, as funcionalidades ainda estão em proposta e desenvolvimento ativo no Project Amber, Project Valhalla, Project Loom e outros incubator modules. As JEPs (JDK Enhancement Proposals) que integrarão oficialmente a versão 25 serão definidas e priorizadas ao longo dos próximos meses pela comunidade de desenvolvedores.


🔍 Possíveis Recursos e Melhorias em Discussão

Embora a lista final de JEPs para o Java 25 ainda não esteva fechada, podemos olhar para as propostas em estágio de preview, incubação ou discussão ativa nas versões anteriores (JDK 21 ao 24) para prever o que pode amadurecer e ser promovido. Algumas áreas de interesse incluem:

Continuidade das Inovações em Concorrência e Modelo de Threads

Os Virtual Threads (Project Loom), lançados de forma definitiva no Java 21, continuam recebendo refinamentos. No JDK 25, é possível esperar otimizações adicionais na performance, debugging e integração com frameworks e bibliotecas do ecossistema, consolidando ainda mais este modelo revolucionário para lidar com concorrência.

Evolução do Sistema de Tipos e Modelo de Memória

O Project Valhalla, que busca introduzir value objects e classes primitivas especializadas, pode dar mais um passo significativo. A introdução de primitive classes em estágio preview é uma possibilidade concreta, prometendo melhorias dramáticas de performance e uso de memória para tipos de dados simples.

Refinamentos na Sintaxe (Project Amber)

O Project Amber tem sido responsável por tornar o Java mais conciso e expressivo. Constructos como pattern matching para switch e registros (records) podem ganhar novas capacidades, como padrões aninhados mais poderosos ou a evolução dos sealed classes.


⚙️ Impacto para Desenvolvedores e Empresas

A adoção do Java 25, como qualquer nova versão, deve ser planejada. A boa notícia é que o modelo de lançamento semestral com LTS (Long-Term Support) a cada seis versões (sendo a próxima LTS o Java 27) oferece flexibilidade. Desenvolvedores podem testar as novas features em estágio preview sem comprometer a estabilidade de produção. Manter-se atualizado com as versões não-LTS, como a 25, permite experimentar inovações rapidamente, preparando a base de código para a futura migração para uma versão LTS.


🔧 Como Acompanhar o Desenvolvimento do Java 25

Para ficar por dentro das novidades em tempo real, a melhor fonte é o site oficial do OpenJDK. Lá você pode acompanhar o painel de JEPs destinadas ao JDK 25, acessar builds early-access e participar de listas de discussão. Outro canal valioso são as comunidades Java, como a Java Community Process (JCP) e fóruns de desenvolvedores, onde as propostas são debatidas.


🎯 Conclusão: Preparando-se para o Futuro

O Java 25 representa mais um capítulo na contínua modernização de uma das plataformas de desenvolvimento mais críticas do mundo. Embora suas features definitivas ainda estejam se moldando, uma coisa é certa: a linguagem continua evoluindo com foco em produtividade, performance e segurança. Para o desenvolvedor Java, acompanhar essas mudanças não é só sobre aprender uma nova sintaxe, mas sobre compreender as novas abstrações e paradigmas que estarão disponíveis para construir a próxima geração de aplicações escaláveis, eficientes e robustas. Fique de olho nas prévias e comece seus testes!

🚀 Novidades do Spring Boot 4 e Spring Framework 7 para Desenvolvedores

🌟 Introdução: A Nova Fase do Ecossistema Spring

Em 2025, o ecossistema Spring dá mais um passo significativo em sua jornada de modernização com o lançamento do Spring Boot 4 e do Spring Framework 7. Se a versão anterior representou uma mudança de pilar com a migração para o Jakarta EE, essas novas releases consolidam essa base, trazendo melhorias focadas em produtividade do desenvolvedor, suporte resiliente nativo e uma experiência ainda mais refinada para a construção de aplicações cloud-native.


📋 Atualizações da Base Técnica

Antes de explorar as novas funcionalidades, é crucial entender a nova fundação sobre a qual esses frameworks são construídos.

Versões Mínimas e Recomendadas

O Java 17 permanece como requisito mínimo. No entanto, para aproveitar ao máximo os novos recursos da JVM, como virtual threads, o uso do Java 21 ou Java 25 é fortemente recomendado.

Alinhamento com Jakarta EE 11

O Spring Framework 7 adota completamente o padrão Jakarta EE 11. Isso significa uma atualização para Servlet 6.1, JPA 3.2 e Bean Validation 3.1, garantindo melhor compatibilidade e suporte às especificações mais recentes da plataforma Enterprise Java.

Suporte ao Kotlin 2.2+

Para desenvolvedores Kotlin, o suporte foi elevado para a versão 2.2 e superiores, trazendo uma integração mais suave com corrotinas e tornando o trabalho com código reativo ainda mais natural.


⚙️ O que há de novo no Spring Boot 4

A quarta versão principal do Spring Boot aprimora seu papel como a base ideal para aplicações Java modernas, com foco em desempenho, observabilidade e manutenibilidade.

🔄 Melhorias em Imagens Nativas (GraalVM)

O suporte a imagens nativas do GraalVM foi significativamente aprimorado e está totalmente alinhado com a GraalVM 24. O processamento AOT (Ahead-of-Time) foi otimizado, resultando em tempos de construção mais rápidos e uma pegada de memória reduzida na inicialização. Um avanço notável são os AOT Repositories do Spring Data, que transformam métodos de consulta em código fonte durante a compilação.

📊 Observabilidade: Micrometer 2 e OpenTelemetry

A observabilidade é um pilar para aplicações cloud-native. O Spring Boot 4 faz upgrade para o Micrometer 2 e integra um starter do OpenTelemetry, fazendo com que traços, logs e métricas funcionem perfeitamente juntos, diretamente "out of the box".

🔒 Relatório de Saúde SSL Aprimorado

Para facilitar o monitoramento de certificados em ambientes de produção, o relatório de saúde de SSL agora inclui uma entrada expiringChains que lista certificados próximos da expiração. O status confuso WILL_EXPIRE_SOON foi removido; em vez disso, esses certificados são reportados simplesmente como VALID, evitando alarmes falsos.

🧩 Modularização Interna

Uma mudança arquitetural importante é a refatoração do código base em uma estrutura mais modular. Auto-configurações e códigos de suporte foram divididos em módulos menores e focados. Isso resulta em:

  • Construções e geração de imagens nativas mais rápidas.
  • Gerenciamento de dependências mais limpo.
  • Melhor capacidade de manutenção para a equipe do Spring.

Para a maioria dos desenvolvedores que usam starters (como spring-boot-starter-data-jpa), essa mudança é transparente e não exige alterações no pom.xml ou build.gradle.

🛠️ Nova Anotação @ConfigurationPropertiesSource

Para melhorar o suporte a projetos modulares, foi introduzida a anotação @ConfigurationPropertiesSource. Ela atua como uma dica para o spring-boot-configuration-processor em tempo de construção, garantindo que metadados completos sejam gerados para classes de propriedades de configuração, mesmo quando dependem de tipos base definidos em outros módulos.


⚡ Principais Funcionalidades do Spring Framework 7

O Spring Framework 7 chega com um mix de funcionalidades há muito solicitadas e refinamentos em testes, design de API e infraestrutura central.

🧪 Melhorias em Testes

Duas novidades se destacam:

  1. Pausa do Contexto de Teste: Agora é possível pausar e retomar contextos armazenados no cache, economizando memória e acelerando a execução de grandes suites de testes de integração.
  2. Novo RestTestClient: Um cliente para testar endpoints REST de forma semelhante ao WebTestClient, mas sem a necessidade de incluir infraestrutura reativa nas dependências, simplificando testes de controladores MVC.

🔢 Versionamento de API Nativo

Uma das funcionalidades mais aguardadas! O framework agora oferece suporte nativo para versionamento de APIs, eliminando a necessidade de soluções caseiras. É possível especificar a versão diretamente na anotação de mapeamento:

@GetMapping(version = "1", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV1() {
    return "Hello World";
}

O Spring pode resolver a versão automaticamente com base em diferentes estratégias configuráveis: por segmento do caminho (/api/v1/...), parâmetro de query, cabeçalho de requisição ou cabeçalho de media type.

🤝 Cliente HTTP Declarativo com @HttpServiceClient

Inspirado no Feign, mas mais leve e totalmente integrado, o @HttpServiceClient permite criar clientes HTTP declarativos. Basta definir uma interface com anotações como @GetExchange, e o Spring cuida da implementação.

@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
    @GetExchange("/greetings?random")
    String getRandomGreeting();
}

🛡️ Anotações de Resiliência Integradas

Padrões de resiliência agora são parte do framework. É possível anotar métodos com @Retryable (para novas tentativas) e @ConcurrencyLimit (para limitar concorrência) diretamente:

@GetExchange("/greetings?random")
@Retryable(maxAttempts = 3, delay = 100, multiplier = 2, maxDelay = 1000)
@ConcurrencyLimit(3)
String getRandomGreeting();

Essas anotações são ativadas ao adicionar @EnableResilientMethods em uma configuração, simplificando muito a adição de padrões de resiliência sem bibliotecas externas.

⛓️ Múltiplos Beans TaskDecorator

Para personalizar a execução de tarefas assíncronas (como propagar contexto de segurança ou logs), agora é possível declarar múltiplos beans do tipo TaskDecorator. O Spring os compõe automaticamente em uma cadeia, na ordem definida por @Order, eliminando a necessidade de criar um decorador composto manualmente.


🎯 Conclusão

O Spring Boot 4 e o Spring Framework 7 representam uma evolução consistente e poderosa do ecossistema. Eles não quebram paradigmas de forma abrupta, mas consolidam a fundação estabelecida nas versões anteriores (Java 17+, Jakarta EE) enquanto introduzem ferramentas práticas que resolvem dores reais dos desenvolvedores.

Desde a observabilidade integrada e os testes mais eficientes até o versionamento nativo de API e os clientes HTTP declarativos, essas releases são impulsionadas pela produtividade no dia a dia. Se você já está na jornada Spring Boot 3, a migração deve ser suave. Se ainda não deu o salto, agora é o momento perfeito para começar a construir no estado da arte do Java moderno.

O futuro do Spring continua brilhante, focado em ajudar desenvolvedores a criar aplicações robustas, observáveis e prontas para a nuvem com menos boilerplate e mais prazer em programar. 💻✨

🚀 Java 21: Guia Completo das Novidades e Como Migrar

Introdução: O Java 21 Chegou como um LTS Revolucionário

Lançada em setembro de 2023, a versão Java 21 não é apenas mais uma atualização. Ela marca um Long-Term Support (LTS), o que significa que é uma versão de suporte estendido, recomendada para produção por anos. A Oracle consolidou nela um conjunto de features preview que estavam em desenvolvimento, trazendo algumas das mudanças mais significativas e aguardadas pela comunidade desde o projeto Loom.


🌟 As Principais Inovações do Java 21

A versão 21 apresenta 15 JEPs (JDK Enhancement Proposals). Vamos mergulhar nas mais impactantes para o dia a dia do desenvolvedor.

🧵 Virtual Threads: Revolução na Concorrência

Finalmente saíram do modo preview! As Virtual Threads (projeto Loom) representam um novo modelo de concorrência leve. Diferente das platform threads (threads do sistema operacional), são threads gerenciadas pela JVM, extremamente leves e em grande número. Isso permite escrever código concorrente no estilo thread-per-request de forma eficiente, sem o overhead tradicional. Ideal para aplicações de alto throughput, como APIs e serviços web.

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> {
        System.out.println("Hello from a virtual thread!");
    });
}

🎭 Pattern Matching para Switch (Finalizado)

O Pattern Matching para switch foi finalizado, permitindo uma sintaxe muito mais limpa e expressiva. Agora é possível fazer a desestruturação de objetos diretamente na cláusula case.

String formatter(Object obj) {
    return switch (obj) {
        case Integer i -> String.format("int %d", i);
        case String s -> String.format("String %s", s);
        case null -> "Oops, null!"; // Guarda contra NullPointerException
        default -> obj.toString();
    };
}

📚 Sequenced Collections: Nova Interface para Ordem

Uma nova família de interfaces (SequencedCollection, SequencedSet, SequencedMap) foi introduzida para fornecer operações consistentes em coleções ordenadas. Métodos como getFirst(), getLast(), addFirst(), e reversed() agora têm um contrato claro.

SequencedCollection list = new ArrayList<>();
list.add("B");
list.addFirst("A"); // Adiciona no início
list.getLast(); // Retorna "B"

🛠️ Como Começar a Usar o Java 21

Migrar para o Java 21 é um processo geralmente simples, especialmente se você já está em uma versão LTS anterior (11 ou 17).

1. Baixar o JDK 21

Faça o download do JDK 21 diretamente do site da Oracle, da Adoptium (Eclipse Temurin) ou use gerenciadores como SDKMAN! (sdk install java 21-tem).

2. Atualizar seu Build Tool

No Maven ou Gradle, atualize a configuração do compilador para a versão 21 (<release>21</release> ou sourceCompatibility = JavaVersion.VERSION_21).

3. Testar as Novas Features

Comece implementando Virtual Threads em pontos de I/O da sua aplicação ou refatorando switches complexos com o novo Pattern Matching. A migração costuma ser incremental e não requer mudanças drásticas.


🔍 Benefícios de Longo Prazo e Conclusão

Adotar o Java 21 LTS vai além de usar features novas. É um investimento em performance (com as Virtual Threads), segurança (com atualizações de segurança garantidas) e legibilidade do código. A JVM continua evoluindo com melhorias de garbage collector (ZGC e Shenandoah) e desempenho.

O Java 21 solidifica a linguagem como uma plataforma moderna, ágil e preparada para os desafios de arquiteturas concorrentes e distribuídas da atualidade. A migração é altamente recomendada e representa o futuro do ecossistema Java.

E aí, preparado para atualizar seu projeto? 🚀

sábado, 3 de janeiro de 2026

☕ História do Java: todas as versões do Java (até Janeiro de 2026) e suas datas de lançamento

O Java é uma das linguagens de programação mais longevas e relevantes da história do software.

Desde seu lançamento em 1996, ele passou por diversas transformações — mantendo compatibilidade, evoluindo com o mercado e se adaptando a novos paradigmas como cloud, microsserviços e alta concorrência.

Neste post, você confere todas as versões do Java e suas datas oficiais de lançamento, organizadas cronologicamente.


📌 Quando o Java foi criado?

O Java foi lançado oficialmente em 23 de janeiro de 1996, marcando o início de uma plataforma multiplataforma baseada na JVM (Java Virtual Machine).

Desde então, o Java passou por diferentes fases, cada uma com características próprias.


🧱 Primeiras versões do Java

  • Java 1.0 – 23 de janeiro de 1996

  • Java 1.1 – 19 de fevereiro de 1997

Essas versões estabeleceram os conceitos fundamentais da linguagem e da JVM.


🚀 Java 2 (J2SE): consolidação da plataforma

  • Java 1.2 – 8 de dezembro de 1998

  • Java 1.3 – 8 de maio de 2000

  • Java 1.4 – 6 de fevereiro de 2002

Aqui surgiu o termo Java 2, marcando a maturidade inicial da plataforma.


☕ Java 5 até Java 8: evolução da linguagem

  • Java 5 (1.5) – 30 de setembro de 2004

  • Java 6 (1.6) – 11 de dezembro de 2006

  • Java 7 – 28 de julho de 2011

  • Java 8 (LTS) – 18 de março de 2014

O Java 5 trouxe generics e annotations.
O Java 8 foi um divisor de águas, introduzindo lambdas, streams e uma nova API de datas.


📦 Java 9 e o início da era modular

  • Java 9 – 21 de setembro de 2017

O Java 9 introduziu o JPMS (Java Platform Module System), a maior mudança estrutural da história da linguagem.


🔄 Novo ciclo de lançamentos do Java

A partir do Java 10, o Java passou a adotar lançamentos semestrais:

  • Java 10 – 20 de março de 2018

  • Java 11 (LTS) – 25 de setembro de 2018

O Java 11 se tornou o sucessor natural do Java 8 em produção.


✨ Java moderno (Java 12 em diante)

  • Java 12 – 19 de março de 2019

  • Java 13 – 17 de setembro de 2019

  • Java 14 – 17 de março de 2020

  • Java 15 – 15 de setembro de 2020

  • Java 16 – 16 de março de 2021

  • Java 17 (LTS) – 14 de setembro de 2021

  • Java 18 – 22 de março de 2022

  • Java 19 – 20 de setembro de 2022

  • Java 20 – 21 de março de 2023

  • Java 21 (LTS) – 19 de setembro de 2023

  • Java 22 – 19 de março de 2024

  • Java 23 – 17 de setembro de 2024

  • Java 24 – 18 de março de 2025

  • Java 25 (LTS) – 16 de setembro de 2025

Essa fase trouxe:


🔮 Próxima versão do Java

  • Java 26 (previsto) – março de 2026


📌 O que são versões LTS do Java?

As versões LTS (Long Term Support) são indicadas para:

Exemplos:

  • Java 8

  • Java 11

  • Java 17

  • Java 21

  • Java 25


📝 Conclusão

A história do Java mostra uma linguagem que:

  • Evolui sem quebrar o passado

  • Se adapta a novas demandas

  • Mantém relevância por décadas

Conhecer todas as versões do Java e suas datas ajuda a entender por que o Java continua sendo uma das plataformas mais importantes do mundo.

O The Dev Side segue acompanhando ☕📜
Porque entender o passado é essencial para programar o futuro.

🗄️ Hibernate ORM 7.2: principais melhorias da versão mais recente

O Hibernate é, há muitos anos, a implementação de ORM mais utilizada no ecossistema Java.

Ele está presente em aplicações corporativas, sistemas críticos e frameworks modernos como o Spring.

A versão mais recente estável é o Hibernate ORM 7.2, lançada no final de 2025, trazendo melhorias importantes em performance, alinhamento com Jakarta EE e qualidade geral da API 🚀

Neste post, vamos listar as principais melhorias dessa versão.


📌 Hibernate ORM 7.2: visão geral

O Hibernate 7.2 não é uma revolução, mas uma versão de amadurecimento.
O foco principal está em:

  • Estabilidade 🧱

  • Performance ⚡

  • Consistência da API 🧠

  • Melhor alinhamento com o Java moderno ☕

É uma versão pensada para produção.


🚀 Principais melhorias do Hibernate ORM 7.2

⚡ Melhor desempenho em consultas

O Hibernate 7.2 traz otimizações importantes no mecanismo interno de consultas:

  • Melhor geração de SQL

  • Execução mais eficiente de JPQL e Criteria

  • Redução de overhead em consultas repetidas

  • Melhor aproveitamento do cache

Resultado: menos custo no banco e mais desempenho na aplicação.


🧠 Alinhamento total com Jakarta Persistence

O Hibernate 7.2 está completamente alinhado com o Jakarta Persistence (antigo JPA):

  • Uso exclusivo de jakarta.persistence.*

  • Remoção definitiva de dependências legadas

  • Melhor compatibilidade com Jakarta EE moderno

Isso facilita a vida de quem já migrou (ou está migrando) de Java EE para Jakarta EE 🌍


🔄 Melhorias no gerenciamento de entidades

A versão 7.2 traz ajustes importantes em:

  • Ciclo de vida das entidades

  • Detecção de mudanças (dirty checking)

  • Sincronização com o banco de dados

  • Atualizações parciais mais eficientes

Essas melhorias reduzem efeitos colaterais e tornam o comportamento do ORM mais previsível.


🧩 Melhor suporte a tipos modernos

O Hibernate continua evoluindo no suporte a tipos:

  • Melhor mapeamento de tipos Java modernos

  • Melhor integração com tipos específicos de bancos de dados

  • Menos necessidade de custom types

Isso reduz código boilerplate e aumenta a clareza do modelo.


🛠️ Correções e refinamentos internos

Como toda versão madura, o Hibernate 7.2 também entrega:

  • Correções de bugs antigos

  • Refinamentos em APIs internas

  • Melhor estabilidade em cenários complexos

  • Menos comportamentos inesperados em produção

Essas melhorias silenciosas fazem grande diferença no longo prazo.


⚙️ Melhor integração com frameworks

O Hibernate 7.2 funciona muito bem com:

  • Spring Framework moderno

  • Spring Boot atual

  • Aplicações Jakarta EE

  • Arquiteturas cloud-native

Isso garante tranquilidade para quem mantém sistemas corporativos 🏢


🤔 Vale a pena atualizar para o Hibernate 7.2?

Sim ✅, especialmente se você:

  • Está iniciando um novo projeto

  • Já utiliza Jakarta Persistence

  • Trabalha com Java moderno

  • Quer mais desempenho e estabilidade

Para sistemas legados, a migração deve ser planejada, mas o caminho está cada vez mais claro.


📝 Conclusão

O Hibernate ORM 7.2 mostra que o projeto continua:

  • Vivo 💚

  • Maduro 🧠

  • Alinhado com o Java moderno ☕

Ele não tenta reinventar o ORM, mas aprimorar aquilo que já funciona, com foco em desempenho, previsibilidade e qualidade.

O The Dev Side segue acompanhando 🚀
Porque persistência de dados ainda é parte central da arquitetura Java.

☕ Por que a Oracle não oferece mais a certificação de Arquiteto Java

Durante muitos anos, a certificação de Arquiteto Java da Oracle foi considerada o auge da carreira técnica para desenvolvedores Java.

Não era uma prova simples: exigia análise, tomada de decisão, justificativas arquiteturais e visão de sistemas complexos.

Hoje, essa certificação não existe mais — e isso não aconteceu por acaso.

A decisão está diretamente ligada à mudança no papel da arquitetura, à evolução do ecossistema Java e, principalmente, ao fato de que Java EE agora é Jakarta EE.


📜 A certificação de Arquiteto Java no passado

A certificação de arquiteto fazia sentido em um contexto bem específico:

  • Sistemas monolíticos

  • Arquiteturas corporativas estáveis

  • Forte dependência de Java EE

  • Decisões centralizadas em um “arquiteto”

Além disso:

  • A correção era subjetiva

  • Envolvia avaliação humana

  • Tinha alto custo operacional

Esse modelo começou a perder aderência com o passar dos anos.


🔄 Arquitetura deixou de ser algo padronizável

Hoje, arquitetura de software é:

  • Evolutiva

  • Contextual

  • Influenciada por negócio, cloud e time

  • Resultado de trade-offs constantes

Não existe mais uma “arquitetura Java correta” universal.

Certificar arquitetura como se certifica:

  • Sintaxe da linguagem

  • APIs específicas

  • Conhecimento objetivo

simplesmente não funciona mais.


☁️ Cloud, microsserviços e mudança de paradigma

Com a popularização de:

  • Cloud computing

  • Containers

  • Microsserviços

  • DevOps

a arquitetura deixou de ser um documento estático e passou a ser um processo contínuo.

Decisões arquiteturais agora:

  • Evoluem com o sistema

  • São feitas em conjunto com o time

  • Dependem da infraestrutura e do ambiente

Isso torna uma prova formal de arquiteto cada vez menos representativa da realidade.


🌍 Java EE não existe mais — agora é Jakarta EE

Aqui entra um ponto crítico.

A Oracle doou o Java EE para a Eclipse Foundation, encerrando seu controle direto sobre a plataforma.

A partir disso:

  • O nome Java EE foi descontinuado

  • A plataforma passou a se chamar Jakarta EE

  • Os pacotes mudaram de javax.* para jakarta.*

  • O desenvolvimento se tornou totalmente comunitário

Ou seja: a Oracle deixou de ser a dona do Java corporativo.

Manter uma certificação de arquiteto baseada em Java EE deixou de fazer sentido técnico e institucional.


🎯 Novo foco da Oracle em certificações

A Oracle passou a priorizar certificações que:

  • São objetivamente avaliáveis

  • Possuem correção automática

  • Escalam globalmente

  • Têm baixo custo operacional

Certificações de arquiteto exigem:

  • Avaliação humana

  • Julgamento subjetivo

  • Alto custo

  • Baixa escalabilidade

Do ponto de vista da Oracle, o modelo deixou de ser viável.


🧠 Como o mercado valida arquitetos hoje

Atualmente, arquitetos são reconhecidos por:

  • Experiência prática

  • Histórico de projetos

  • Capacidade de decisão

  • Comunicação com o negócio

Muito mais do que por um certificado.

O mercado passou a valorizar:

  • Portfólio real

  • Vivência em produção

  • Responsabilidade técnica

Não uma prova isolada.


📚 Arquitetura ≠ Certificação

A indústria amadureceu e entendeu algo importante:

👉 Arquitetura não é um conjunto de respostas certas
👉 É um processo contínuo de decisões e adaptação

Isso é praticamente impossível de medir em um exame padronizado.


📝 Conclusão

A Oracle não deixou de oferecer a certificação de Arquiteto Java por acaso.

Os principais motivos foram:

  • Mudança no papel da arquitetura

  • Evolução do ecossistema Java

  • A transição de Java EE para Jakarta EE

  • A perda do controle direto da Oracle sobre o Java corporativo

Arquitetos Java hoje são formados pela prática, não por certificados.

O The Dev Side segue acreditando em escolhas técnicas conscientes ☕🏗️
Porque arquitetura começa na experiência — não na prova.

☕ Por que eu prefiro usar o Eclipse IDE em vez do IntelliJ IDEA

Quando o assunto é IDE para desenvolvimento Java, duas ferramentas quase sempre aparecem na conversa: Eclipse IDE e IntelliJ IDEA 🧠

Ambas são excelentes, maduras e amplamente utilizadas. Ainda assim, minha preferência pessoal continua sendo o Eclipse — e neste post explico o porquê.


📌 Antes de tudo: Eclipse e IntelliJ são ótimos

É importante deixar isso claro logo de início.

O IntelliJ IDEA é uma IDE extremamente poderosa, com muita inteligência embarcada e foco forte em produtividade.
Já o Eclipse IDE é uma ferramenta sólida, flexível e com uma longa história junto à comunidade Java.

Minha escolha não é sobre “qual é melhor”, mas sobre qual se encaixa melhor na minha forma de trabalhar.


🧠 Controle total do ambiente

Um dos principais motivos para eu preferir o Eclipse é o nível de controle que ele oferece.

No Eclipse:

  • Eu escolho exatamente quais plugins instalar

  • Posso manter a IDE leve, sem recursos que não utilizo

  • Tenho controle fino sobre comportamento, layout e desempenho

Essa flexibilidade faz muita diferença no dia a dia, especialmente em projetos grandes.


☕ Integração natural com o ecossistema Java

O Eclipse sempre teve uma relação muito próxima com o próprio Java.

Isso se reflete em:

  • Excelente suporte a Java puro

  • Ótima integração com Maven e Gradle

  • Ferramentas maduras para projetos corporativos

  • Facilidade para trabalhar com código legado

Para quem mantém sistemas Java há muitos anos, o Eclipse costuma “se sentir em casa”.


⚙️ Desempenho previsível

Outro ponto importante para mim é o comportamento previsível do Eclipse.

Depois de bem configurado:

  • A IDE se mantém estável

  • O consumo de recursos é controlável

  • Grandes projetos continuam utilizáveis

Isso é essencial quando se trabalha com aplicações grandes, antigas ou muito customizadas 🏗️


🧩 Plugins e customização

O ecossistema de plugins do Eclipse é um dos seus maiores pontos fortes:

  • Ferramentas específicas para nichos

  • Plugins corporativos e governamentais

  • Extensões para bancos de dados, servidores e cloud

Essa modularidade permite adaptar o Eclipse exatamente ao cenário do projeto.


🖥️ Multiplataforma real

O Eclipse funciona de forma muito consistente em:

Isso facilita o trabalho em equipes mistas e ambientes corporativos variados.


🤔 E o IntelliJ IDEA?

O IntelliJ IDEA é excelente — especialmente para quem:

  • Busca produtividade imediata

  • Prefere muitas decisões automáticas

  • Trabalha com projetos modernos desde o início

Para mim, porém, essa “inteligência extra” às vezes tira controle, e eu prefiro entender e decidir o que a IDE está fazendo.


📝 Conclusão

Minha preferência pelo Eclipse IDE não é nostalgia — é escolha técnica e prática.

O Eclipse me oferece:

  • Controle 🧠

  • Flexibilidade 🔧

  • Estabilidade 🧱

  • Forte integração com Java ☕

E isso, no meu contexto, pesa mais do que automações agressivas ou sugestões constantes.

No fim das contas, a melhor IDE é aquela que trabalha a seu favor, não contra você.

O The Dev Side segue acompanhando — Java, ferramentas e escolhas conscientes 🚀

☕ Eclipse IDE 2025-12: última versão do Eclipse para desenvolvimento Java

Se você trabalha com Java, acompanhar a evolução da IDE é tão importante quanto acompanhar a linguagem.
A última versão disponível do Eclipse IDE é o Eclipse IDE 2025-12, e ela chega trazendo melhorias importantes em estabilidade, desempenho e suporte ao Java moderno 🚀

Neste post, vamos entender o que muda, por que vale a pena atualizar e para quem essa versão é indicada.


📌 Qual é a versão mais recente do Eclipse IDE?

Atualmente, a versão mais atual disponível para download no site oficial é:

Eclipse IDE 2025-12

Essa versão faz parte do ciclo regular de lançamentos da Eclipse Foundation e é recomendada para quem desenvolve aplicações Java hoje.


🚀 Novidades do Eclipse IDE 2025-12

🧠 Suporte atualizado ao Java moderno

O Eclipse IDE 2025-12 acompanha a evolução do Java e oferece:

  • Suporte às versões mais recentes do Java

  • Melhor compatibilidade com recursos modernos da linguagem

  • Ambiente preparado para versões LTS e versões regulares

Ideal para quem trabalha com Java moderno, seja em projetos novos ou legados.


⚡ Melhor desempenho e mais estabilidade

Um dos grandes focos do Eclipse IDE 2025-12 é a qualidade da experiência diária:

  • IDE mais rápida e responsiva

  • Menor consumo de memória

  • Correções de bugs importantes

  • Mais estabilidade em projetos grandes

Essas melhorias são essenciais para ambientes corporativos e sistemas de médio e grande porte.


🧩 Ecossistema completo para Java

O Eclipse continua sendo uma IDE forte pelo seu ecossistema:

  • Integração com Maven e Gradle

  • Suporte a Java SE e Jakarta EE

  • Plugins para Git, bancos de dados e servidores

  • Ambiente altamente configurável

Você instala apenas o que precisa e mantém a IDE organizada 🔧


🖥️ IDE multiplataforma

O Eclipse IDE 2025-12 funciona muito bem em:

  • Windows

  • Linux

  • macOS

Isso facilita o uso em equipes com diferentes sistemas operacionais.


🤔 Vale a pena usar o Eclipse IDE 2025-12?

Sim ✅

O Eclipse IDE 2025-12 é recomendado se você:

  • Usa Java no dia a dia

  • Quer suporte às versões mais recentes da linguagem

  • Busca estabilidade e desempenho

  • Trabalha com projetos novos ou legados

Se você ainda utiliza uma versão antiga do Eclipse, a atualização é altamente recomendada.


📝 Conclusão

O Eclipse IDE 2025-12 mostra que o Eclipse continua:

  • Atualizado 🔄

  • Estável 🧱

  • Totalmente alinhado com o Java moderno ☕

Mesmo após tantos anos, o Eclipse segue sendo uma das IDEs mais completas para desenvolvimento Java.

O The Dev Side continua acompanhando a evolução do Java e de suas ferramentas 🚀

☕ Java 26: o que esperar da próxima versão do Java

O Java segue seu ritmo previsível de evolução e o próximo passo já tem nome: Java 26 🚀

Mas antes de falar em novidades, é importante alinhar as expectativas:

👉 O Java 26 ainda não foi lançado oficialmente.

No momento, ele está em desenvolvimento no projeto OpenJDK, passando pelas fases finais antes do lançamento geral.


📌 Java 26 já foi lançado?

❌ Ainda não.
O Java 26 está em fase de finalização e testes, com lançamento previsto dentro do ciclo normal de releases do Java.

Isso significa que:

  • 🧪 As funcionalidades principais já estão definidas

  • 🛠️ O foco agora é correção de bugs e estabilidade

  • 📅 O lançamento oficial acontecerá quando atingir o nível esperado de qualidade

Esse processo garante previsibilidade e confiança em cada nova versão.


🔄 O papel do Java 26 na evolução da linguagem

O Java 26 não surge como uma “revolução”, mas como parte de um modelo que vem funcionando muito bem:

  • Evoluções graduais

  • Menos mudanças bruscas

  • Melhorias constantes em produtividade e desempenho

Cada versão regular prepara o terreno para a próxima versão LTS, refinando recursos e fortalecendo a plataforma 🧱


🧵 Concorrência moderna continua evoluindo
O modelo de concorrência introduzido nos últimos anos segue sendo aprimorado.

O foco permanece em:

  • Código simples e legível

  • Alta escalabilidade

  • Menos complexidade para o desenvolvedor

O Java continua apostando na ideia de que simplicidade também é performance


🌊 APIs mais expressivas e coerentes
Streams, pattern matching e construções mais declarativas seguem em constante refinamento.

A cada versão, o Java:

  • Reduz código cerimonial

  • Aumenta a clareza

  • Aproxima o código da intenção do negócio 📖

O Java 26 segue exatamente essa linha.


⚙️ JVM cada vez mais eficiente
Mesmo antes do lançamento oficial, já é esperado que o Java 26 traga:

  • Otimizações internas da JVM

  • Melhor uso de memória

  • Ajustes finos em Garbage Collection

  • Evolução contínua para ambientes cloud e containers ☁️

São melhorias que raramente aparecem como manchete, mas fazem enorme diferença no dia a dia.


🤔 Vale a pena usar Java 26 quando for lançado?

Depende do cenário.

✅ Faz sentido se você:

  • Gosta de acompanhar novidades

  • Quer testar melhorias recentes

  • Trabalha em projetos de curto ou médio prazo

  • Quer se preparar para a próxima LTS

⚠️ Para produção de longo prazo, a recomendação continua sendo usar uma versão LTS, como Java 21 ou Java 25.


📝 Conclusão

O Java 26 ainda não chegou, mas já mostra algo importante:
o Java segue vivo, previsível e em constante evolução 🔄

A cada nova versão, a linguagem se torna mais madura, mais eficiente e mais agradável de usar — sem abandonar o passado.

O The Dev Side segue acompanhando ☕🔥
Porque Java continua evoluindo, mesmo antes do lançamento oficial.