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

quarta-feira, 1 de novembro de 2023

Programação funcional no Java (Java 8+)

      Nesse artigo vou falar um pouco sobre programação funcional no Java. A programação funcional se refere ao uso de conceitos e técnicas como funções de ordem superior, expressões lambda, programação sem efeitos colaterais, imutabilidade e streams, para escrever código mais conciso, legível (nem sempre) e robusto. Esses recursos estão disponíveis a partir do Java 8.

 

Aqui estão alguns conceitos chave relacionados à programação funcional no Java:

 

1. Expressões Lambda: As expressões lambda permitem definir funções anônimas (funções sem nome) de forma concisa. Elas são usadas em várias partes do código, como argumentos para métodos, implementações de interfaces funcionais e para criar objetos ‘Comparator’. É sempre bom lembrar da importância da legibilidade do código, porque nem todos tem a mesma experiência, e o uso exagerado pode atrapalhar. Um exemplo de função lambda:

 

  (a, b) -> a + b  // Uma expressão lambda que adiciona dois números

 

2. Interfaces Funcionais: As interfaces funcionais são interfaces que têm um único método abstrato. Alguns exemplos incluem ‘Function’, ‘Predicate’, ‘Consumer’ e ‘Supplier’. Você pode usar expressões lambda para implementar essas interfaces de maneira concisa.

 

3. Streams: Os Stream’s são sequências de elementos que podem ser processadas de forma funcional. Eles permitem realizar operações de consulta, transformação e agregação em coleções de dados, como listas e conjuntos. Os Stream’s operam de forma lazy e podem ser processados sequencialmente ou em paralelo.

 

4. Imutabilidade: A programação funcional incentiva a imutabilidade, o que significa que objetos não devem ser alterados após a criação. Em vez disso, você cria novos objetos com base em objetos existentes. Isso evita efeitos colaterais e torna o código mais previsível.

 

5. Funções de Ordem Superior: Funções de ordem superior são funções que podem receber outras funções como argumentos e/ou retornar funções como resultado. No Java, usando programação funcional, você pode passar funções como argumentos para métodos e implementar métodos que aceitam funções como parâmetros.

 

6. Recursão Funcional: A programação funcional incentiva o uso de recursão funcional, onde os métodos se chamam de forma recursiva, evitando loops tradicionais. Isso promove um código mais declarativo. Porém tem que se tomar muito cuidado, pois o Java faz uso da pilha de chamadas, e caso essas chamadas recursivas sejam muito longas pode quebrar. Embora esteja disponível, é uma boa prática dar preferência  aos loops tradicionais caso o número de chamadas seja desconhecido ou sabidamente grande.

 

Aqui está um exemplo de programação funcional usando uma expressão lambda e um Stream:

 

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5);

 

//  calcular a soma dos quadrados dos números pares

int somaDosQuadradosDosPares = numeros.stream()

    .filter(n -> n % 2 == 0)  // Filtrar números pares

    .map(n -> n * n)  // Elevar ao quadrado

    .reduce(0, Integer::sum);  // Somar os resultados

 

System.out.println(somaDosQuadradosDosPares);  // Saída: 20

 

        A função ‘filter’ filtra os números pares, a função ‘map’ eleva ao quadrado (ambas usando expressão lambda) e ‘reduce’ soma os resultados. Isso ilustra a programação funcional em Java, tornando o código mais enxuto, embora nem sempre mais claro. 

Transformando String de Inteiros em Lista usando Programação Funcional

             Nesse artigo vou mostrar como transformar uma String de números inteiros separadas por “;” em um Array de Integer usando programação funcional em Java.

         

       A programação funcional ajuda muito a reduzir códigos, embora possa também, dependendo da forma que utilizada, perder um pouco legibilidade dele. Então as vezes usar uma forma não tão reduzida das funções e colocar comentários ajuda bastante. Lembre-se que nem todo mundo que programa tem o mesmo nível de experiência.

 

          O código abaixo monta um Stream (Um Stream é uma sequência de elementos que pode ser processada de forma sequencial ou paralela) a partir do split da String, usando o Map para transformar os dados (ele pode ser usado para converter tipos de dados, para chamar funções como UpperCase, etc.) e depois retornados como uma lista.

 

import java.util.Arrays;

import java.util.List;

import java.util.stream.Collectors;

 

public class Exemplo {

    public static void main(String[] args) {

 

        String str = "10;20;30;40;50";

  

        List<Integer> integerList = Arrays.stream(str.split(";"))

                .map(Integer::parseInt)

                .collect(Collectors.toList());

       

        integerList.forEach(System.out::println);

    }

}

quarta-feira, 31 de maio de 2023

Como criar uma requisição POST com Java

     Neste artigo vou mostrar como fazer um POST usando Java. Este código é valido para qualquer versão, mas no Java 11 introduziram uma nova forma de fazer que você pode estar vendo nesse link: Fazendo requisições com HTTP Client do Java 11

 

     Segue aqui o código: 

 

import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class Java8Post { public static void main(String[] args) throws Exception { String url = "https://exemplo.com/requisicao"; URL obj = new URL(url); HttpURLConnection connection = (HttpURLConnection) obj.openConnection(); // Configurar a requisição como POST connection.setRequestMethod("POST"); // Adicionar cabeçalhos necessários connection.setRequestProperty("Content-Type", "application/json"); // Habilitar o envio de dados na requisição connection.setDoOutput(true); String requestBody = "{\"chave\": \"valor\"}"; // Enviar o corpo da requisição DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); outputStream.writeBytes(requestBody); outputStream.flush(); outputStream.close(); // Obter a resposta da requisição int responseCode = connection.getResponseCode(); System.out.println("Código de resposta: " + responseCode); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = reader.readLine()) != null) { response.append(inputLine); } reader.close(); System.out.println("Resposta: " + response.toString()); } }


 

     Pra esse artigo é só. 

segunda-feira, 16 de maio de 2022

Erro "Invalid secret key format" ao iniciar o Jboss na migração do Java da Oracle para o OpenJDK

         Neste artigo vou mostrar a solução para o erro java.io.IOException: Invalid secret key format, que ocorre ao usar o Vault do Jboss para armazenar senhas criptografadas. Esse erro ocorre no módulo PicketBox, que é um framework de segurança Java para prover aos desenvolvedores as seguintes funcionalidades:


  • Suporte a autenticação;
  • Suporte a autorização;
  • Suporte a auditoria;
  • Etc.


        Ao usar o OpenJDK o módulo Picketbox não tem acesso ao módulo "sun.jdk", então ele não pode usar a classe "com.sun.crypto.provider.SealedObjectForKeyProtector", ocasionando em um dos erros abaixo: 


Caused by: java.io.IOException: Invalid secret key format
    at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
    at java.security.KeyStore.load(KeyStore.java:1445)
    at org.picketbox.util.KeyStoreUtil.getKeyStore(KeyStoreUtil.java:201)
    at org.picketbox.util.KeyStoreUtil.getKeyStore(KeyStoreUtil.java:151)
    at org.picketbox.plugins.vault.PicketBoxSecurityVault.getKeyStore(PicketBoxSecurityVault.java:688)
    ... 11 more

ou

  Caused by: java.io.IOException: Invalid secret key format
  at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
  at java.security.KeyStore.load(KeyStore.java:1445) [rt.jar:1.8.0_191-1-redhat]
  at org.wildfly.security.credential.store.impl.KeyStoreCredentialStore.load(KeyStoreCredentialStore.java:859) [wildfly-elytron-1.6.1.Final-redhat-00001.jar:1.6.1.Final-redhat-00001]
  ... 11 more

        

        Para corrigir o problema, é necessário adicionar ao PicketBox a dependência ao "sun.jdk", no arquivo %JBOSS_HOME%/modules/system/layers/base/org/picketbox/main/module.xml a seguinte linha:


<module name="sun.jdk"/>


            Pode-se também adicionar um parametro na JVM da seguinte forma:


-Djboss.modules.system.pkgs=org.jboss.byteman,com.sun.crypto.provider           


         Dessa forma, o módulo em questão é carregado e o uso do Vault e criptografia do JBoss funciona normalmente como no JDK da Oracle. A partir da versão 7.1 do JBoss EAP esse problema foi corrigido, a primeira solução que mostrei já vem por padrão. 



Fonte:

https://picketbox.jboss.org/

http://www.mastertheboss.com/jbossas/jboss-security/solving-java-io-ioexception-invalid-secret-key-format/

https://issues.redhat.com/browse/JBEAP-14660

 

segunda-feira, 11 de dezembro de 2017

Salvando LocalDate e LocalDateTime com JPA 2.1

Quando o JPA 2.1 foi lançado o Java 8 ainda não tinha saído, então algumas features ficaram prejudicadas. Porém para nossa felicidade, o JPA 2.1 tem conversores que nos permitem dizer ao JPA como mapear tipos de dados. A seguir vou mostrar como mapear então o LocalDate e o LocalDateTime:

@Entity
public class Pedido {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", updatable = false, nullable = false)
        private Long id;
       
        @Column
        private LocalDate dataPrevisaoEntrega;
       
        @Column
        private LocalDateTime dataPedido;
       
        ...
       
}

          Um conversor deve implementar a interface javax.persistence.AttributeConverter<X,Y>, passando a classe da entidade em X e classe do banco de dados em Y. O conversor também precisa ser anotado com javax.persistence.Converter. Seguem os conversores:

@Converter(autoApply = true)
public class LocalDateConverter implements AttributeConverter<LocalDate, Date> {
       
    @Override
    public Date convertToDatabaseColumn(LocalDate localDate) {
        return (localDate == null ? null : Date.valueOf(localDate));
    }

    @Override
    public LocalDate convertToEntityAttribute(Date sqlDate) {
        return (sqlDate == null ? null : sqlDate.toLocalDate());
    }
}

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
       
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) {
        return (localDateTime == null ? null : Timestamp.valueOf(localDateTime));
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
        return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
    }
}
         
          Perceba que na anotação @Converter foi passado o atributo autoApplay=true. Isso faz com que o conversor seja aplicado automaticamente em todos os casos. Quando esse atributo é falso, você fica responsável por informar ao JPA sempre que desejar usá-lo, anotando a propriedade com @Convert e passando a classe do conversor como segue:

@Column
@Convert(Converter = LocalDateConverter.class)
private LocalDate dataPrevisaoEntrega;

          Pronto, podemos trabalhar com as novas classes do Java 8 de forma simples e prática. Vou compartilhar um site muito bom para quem quer se aprofundar no JPA e no qual me baseei para este artigo: