Faz dois anos que a Oracle anunciou uma mudança significativa no ciclo de atualizações do Java, passando a lançar uma nova versão da linguagem a cada seis meses em lugar de a cada três anos.

Sem dúvida esse foi um passo importante, permitindo ao Java evoluir mais rapidamente, enquanto satisfaz aos pedidos da comunidade de programadores para a adição de novas funcionalidades, muitas vezes presentes em outras tecnologias. Comentaremos sobre as principais novidades trazidas pelo Java 11, encerrando o assunto com algumas dicas para quem quiser testá-las.

Anotações de tipo em expressões lambda

A primeira novidade do Java 11 a ser comentada é uma alteração na sintaxe da linguagem, que agora permite a inferência de tipos para variáveis locais em expressões lambda, o que completa o recurso de inferência de tipos para variáveis locais lançado com o Java 10.

Por exemplo, supondo que desejamos realizar de forma funcional a conversão de uma moeda, digamos do dólar para o real, antes poderíamos escrever o seguinte trecho de código:

(valor, conversorMoeda) -> conversorMoeda.converter(valor);

Agora, uma vez que var pode ser utilizada em um parâmetro formal para um tipo implícito em uma expressão lambda, podemos utilizar esse recurso em conjunto com outras funcionalidades aplicáveis a tipos, como anotações. Vejamos o mesmo código acima, desta vez reescrito utilizando a inferência de tipos para variáveis locais em expressões lambda:

(@Nonnull var valor, @Nonnull var conversorMoeda) -> conversorMoeda.converter(valor);

Existem inúmeras vantagens em reescrever o código dessa forma, tantas quantas forem aquelas que justificam as notações de tipo incluídas no Java 8, que podem ser conferidas aqui. Dentre as principais entre elas podemos citar o fato de que anotações de tipo adicionam metadados que ajudam a reduzir o número de erros no código. Baseado nessas anotações, o compilador pode emitir alertas ao concluir que o código não atende a certos requerimentos.

Ao executar o código acima teríamos a oportunidade de capturar o seguinte erro em tempo de compilação:

Null type mismatch: required ''@NonNull Double'' but the provided value is null

O cliente HTTP do Java ganha uma padronização

Ainda que discretamente, o Java 9 deu um passo à frente quando incluiu um cliente HTTP ao conjunto de APIs da plataforma a partir da inclusão do pacote jdk.incubator.http. Agora, no Java 11, essa API está consolidada, tendo sido feita a troca do pacote jdk.incubator.http por java.net.http, implementando um modelo não blocante de comunicação na classe CompletableFuture, semelhante ao utilizado pelo Nodejs. Além disso, a API também oferece suporte ao HTTP 1.1/2, o que a torna uma opção muito mais robusta em comparação a API URLConnection.

No exemplo a seguir temos um código completo para uma requisição ao endpoint de uma API:

HttpRequest request = HttpRequest.newBuilder()
          .uri(URI.create("http://www.api.com/recursos"))
          .build();
   
HttpResponse.BodyHandler<String> bodyHandler = HttpResponse.BodyHandlers.ofString();
   
HttpClient client = HttpClient.newHttpClient();
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, bodyHandler);
future.thenApply(HttpResponse::body)
          .thenAccept(System.out::println)
          .join();

Com esse trecho de código podemos nos comunicar de forma assíncrona através do protocolo HTTP, o que torna possível a realização de testes para APIs com maior facilidade. Caso você já desenvolva com Spring já deve ter certa familiaridade com classes como HttpRequest, mas nota que para testar essa funcionalidade devemos utilizar o pacote java.net.http.

Além da interface Future, a qual implementa CompletableFuture, o pacote java.net.http adicionou outras classes importantes também presentes no exemplo anterior. São elas:

  1. HttpClient:Usamos essa classe para enviar requisições e obter respostas. Seu principal método é HttpClient.sendAsync(), usado para enviar uma requisição de forma assíncrona e retornar um objeto do tipo CompletableFuture.
  2. HttpRequest:Essa classe encapsula uma requisição e a sua URI, seus cabeçalhos, bem como o seu corpo.
  3. HttpResponse:Em resposta ao envio de um HttpRequest recebemos um objeto do tipo HttpResponse, a partir do qual podemos ler a resposta enviada de volta para o cliente. Por exemplo, para ler o corpo da resposta podemos utilizar a interface estática HttpResponse.BodyHandler, que implementa diversas funcionalidades, incluindo o retorno dos dados em uma String.
  4. HttpRequest.Builder: Trata-se de uma fábrica para a montagem e preparação de objetos do tipo HttpRequest. Quando utilizamos essa fábrica, todas as chamadas aos seus setters retornam o mesmo objeto fábrica, o que permite chamadas encadeadas. Ao final de todas as configurações necessárias, podemos chamar o método HttpRequest.build() retorna uma nova instância de HttpRequest.

Módulos removidos do Java EE

Falando de onde mora o perigo, no Java 9 diversos módulos foram selecionados para remoção. Os motivos para isso são diversos e vão desde dificuldades em sua manutenção até a disponibilidade de versões stand alone, o que tornaria sua adição nos pacotes base da plataforma Java desnecessário. Para o programador o importante agora é conviver com a mudança e saber o que fazer quando o código quebrar por falta desses pacotes.

Para quem usa Spring, em especial o Spring Boot, uma nova versão do Framework, a 2.1, está sendo preparada e oferece uma melhor compatibilidade com o Java 11. Enquanto essa versão não sai, a página oficial do projeto deixou algumas dicas com pacotes que podem ser adicionados ao seu projeto para evitar problemas.

A primeira delas é utilizar a versão atualmente em desenvolvimento para realizar os seus testes e estudar. Para faça a seguinte alteração no seu pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.0.M4</version>
</parent>

Agora, já que já não estamos mais utilizando uma versão RELEASE do código do projeto, é preciso instruir o Maven a utilizar algum repositório para localizar os pacotes que precisamos. Adicione esse código ao final do seu pom.xml:

<repositories>
    <repository>
        <id>spring-snapshots</id>
        <url>https://repo.spring.io/snapshot</url>
        <snapshots><enabled>true</enabled></snapshots>
    </repository>
    <repository>
        <id>spring-milestones</id>
        <url>https://repo.spring.io/milestone</url>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>spring-snapshots</id>
        <url>https://repo.spring.io/snapshot</url>
    </pluginRepository>
    <pluginRepository>
        <id>spring-milestones</id>
        <url>https://repo.spring.io/milestone</url>
    </pluginRepository>
</pluginRepositories>

Também é provável encontrarmos outros erros ao estudar com essa versão da linguagem. Um deles, já conhecido de quem fez a atualização para o Java 9 é o java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException. A causa desse erro não está relacionada ao Spring Boot, mas sim ao fato do pacote javax.xml.** ser um pacote do Java EE que estava presente no Java SE, sendo removido por completo agora no Java 11. Sendo assim, apenas instalar o JRE/JDK não garante a presença desse pacote, sendo necessário adicioná-lo manualmente no pom.xml do projeto. Existem algumas formas de se obter o pacote javax.xml.bind, mas o pessoal da Pivotal recomendou na página oficial do Spring Boot adicionar a seguinte dependência para resolver o problema:

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
</dependency>

Caso você esteja estudando a JAX-RS e deseje utilizar os recursos mais recentes da linguagem Java, incluir esse pacote no seu pom.xml também pode resolver a ausência do javax.xml.bind, permitindo dar continuidade aos seus estudos.

Curtiu este artigo e quer ler mais sobre as novidades do mundo da tecnologia? Deixe um joinha! Quer compartilhar alguma solução nesse contexto? Fique à vontade para comentar ;)


Saiu na DevMedia!

  • Programador Java:
    Aprender Java não é uma tarefa simples, mas seguindo a ordem proposta nesse Guia, você evitará muitas confusões e perdas de tempo no seu aprendizado. Vem aprender java de verdade, vem!

Saiba mais sobre Java ;)

  • Guia Completo de Java:
    Neste Guia de Referência você encontrará todo o conteúdo que precisa para começar a programar com a linguagem Java, a sua caixa de ferramentas base para criar aplicações com Java.