Entradas

Pasando Spring Certified Professional 2024 [v2] - 2V0-72.22

Ahora que pasé el examen 2V0-72.22 dejaré los recuros que utilicé para estudiar: Pivotal Certified Professional Core Spring 5 Developer Exam Core Spring 5 Certification in Detail Spring Professional Certification — Study Guide Spring Professional Certification - 6 full Tests (2V0-72.22) 2V0-72.22: VMware Spring Professional Develop Estudiando con ellos no tendrán problemas para pasar el exámen.

kafbat: UI para Kafka

Imagen
Anteriormente configuramos Kafka, ahora necesitamos una UI para mirar que pasa en nuestro Kafka 👀 Vamos a utilizar kafka-ui , navegamos a releases y descargamos la última disponible (en este momento la 1.2.0 Ya con el jar en nuestro poder, lo dejamos en la carpeta que consideremos adecuada y creamos el archivo local.yml con el siguiente contenido: kafka: clusters: - name: local bootstrapServers: localhost:9092 logging: level: root: INFO io.kafbat.ui: DEBUG reactor.netty.http.server.AccessLog: INFO org.springframework.security: DEBUG server: port: 8888 spring: jmx: enabled: true dynamic.config.enabled: true Ahora usando Java 21 , ejecutamos lo siguiente: ~/code/jdk/jdk-21.0.7+6/bin/java -Dspring.config.additional-location=./local.yml --add-opens java.rmi/javax.rmi.ssl=ALL-UNNAMED -jar api-v1.2.0.jar Revisamos que funcione en http://localhost:8888 Ya quedó configurado 😉

Usando Kafka localmente

Imagen
En esta entrada dejaremos funcionando Kafka localmente Descarguemos kafka , como normalmente ocurre, hay varias opciones, yo prefiero bajar el binario . Luego extraerlo en donde lo ocuparemos y le podemos crear una carpeta llamada data para lo que viene: Agregar el bin de Kafka al path: export PATH=~/code/kafka/kafka_2.13-3.9.0/bin/:$PATH Configurar los brokers Acá configuraremos 3 brokers, para eso vamos a la carpeta kafka_2.13-3.9.1/config y creamos 3 archivos: kafka1.properties, kafka2.properties y kafka3.properties . NO OLVIDAR, hay que indicar la carpeta donde quedarán los datos (en mi caso es /home/sebastian/code/kafka/data/): kafka1.properties: broker.id=1 log.dirs=/home/sebastian/code/kafka/data/kafka1 listeners=PLAINTEXT://:9092,CONTROLLER://:9192 process.roles=broker,controller controller.quorum.voters=1@localhost:9192,2@localhost:9193,3@localhost:9194 controller.listener.names=CONTROLLER listener.security....

Usando Vault localmente

Imagen
Vault es una herramienta utilizada en varios lugares, así que veamos cómo lanzarlo localmente... Ir a https://developer.hashicorp.com/vault/install para realizar la instalación, hay una gran cantidad de alternativas, en mi caso fue usar la disponible usando el package manager de Linux: al final tiene que quedar disponible el comando vault en el path. Crear una carpeta para los datos, yo creé una llamada vault y dentro de vault una llamada data: Ya en vault, crear el archivo config.hcl con el siguiente contenido: storage "raft" { path = "./data" node_id = "node1" } listener "tcp" { address = "127.0.0.1:8200" tls_disable = "true" } disable_mlock = true api_addr = "http://127.0.0.1:8200" cluster_addr = "https://127.0.0.1:8201" ui = true En la carpeta vault que creamos antes, configurarlo de la siguiente manera: en una terminal ejecutar (podrían guardar el comando en u...

Comparando Strings con ==

Todos aprendimos que para comparar strings utilizamos equals, pero que sucede si ocupamos == ¿? caso 1: los literales son iguales (quedan en el pool de strings), pero al comparar con uno creado con new String() ya no es igual a menos que se use intern: String d = "d"; final String dd = "d"; String ddd = new String("d"); System.out.println("1 true: " + (d == dd)); System.out.println("2 true: " + ("d" == dd)); System.out.println("3 true: " + (""" d""" == d)); System.out.println("4 false: " + ("d" == ddd)); System.out.println("5 true: " + (d == ddd.intern())); caso 2: usando string concatenation, serán iguales si no se concatenan con variables: String ja = "ja"; String va = "va"; ...

Testcontainers + Localstack +AWS Java SDK 2.x

Al usar localstack en las pruebas y el sdk 2.x de AWS para Java no es tan simple como sacar el endpoint y el credential provider de localstack y pasarlo al cliente de aws, hay que constuir primeros los objetos del sdk 2 para pasarlos al cliente con datos que entrega localstack: private static LocalStackContainer ls = null; @BeforeAll public static void before() { ls = new LocalStackContainer(DockerImageName.parse("localstack/localstack")) .withServices(DYNAMODB); ls.start(); final var credentials = ls.getDefaultCredentialsProvider().getCredentials(); final var ddbc = DynamoDbClient.builder() .endpointOverride(ls.getEndpointOverride(DYNAMODB)) .credentialsProvider( StaticCredentialsProvider.create(AwsBasicCredentials.create( credentials.getAWSAccessKeyId(), credentials.getAWSSecretKey()))).build(); } ese el código para construir el cliente de dynamo usan...

Experimento concurrente

En esta entrada dejaré el resultado de un experimento que surgió por una difícil pregunta que me generó varias dudas... El experimento es revisar el comportamiento de un programa usando un Map en forma concurrente: Comenzamos creando la clase con el map, luego agregarle algunos datos y el main: public class Concurrido { private final Map<Integer, String> estado = new HashMap<y>(); { IntStream.rangeClosed(1, 1_000_000) .forEach(i -> estado.put(i, String.valueOf(1))); } public static void main(String[] args) throws InterruptedException { final var c = new Concurrido(); final var t1 = new Thread(() -> { c.m1(); System.out.println("m1 terminado"); }); final var t2 = new Thread(() -> { c.m2(); System.out.println("m2 terminado"); }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("fin"); } el main lanzará 2 hilos...

Stub con Jetty embebido en Test con JUnit 5

En esta entrada mostraré un pequeño ejemplo para utilizar al servidor Jetty embebido durante las pruebas (con JUnit 5 ) para cuando necesitemos un Stub de algún servicio fuera de nuestro alcance. 1. Las dependencias: <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>9.4.28.v20200408</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> 2. La cl...

Codersrank - TOP DEVELOPERS IN JAVA [UPDATE]

Imagen
Ahora estoy en el puesto número 1 en  codersrank , así que dejaré las capturas para el recuerdo 👻: Chile + Java = 1 Chile + Santiago + Java = 1 ¿y cual será el motivo si mi puntaje no ha cambiado? 😀

GraalVM + Java 11 + AWS Lambda + PostgreSQL + DynamoDB + Docker

Imagen
En esta ocasión mostraré la travesía que fue conseguir compilar un jar con GraalVM y que luego corra en AWS Lambda . ¿Por qué hacerlo? En la actualidad, el cold start de lanzar un jar en un lambda es alto, varios segundos (en node puede ser medio segundo o menos), pero luego de eso cada invocación tiene un tiempo de respuesta bueno, son solo algunos milisegundos. Entonces mi motivación es hacer cada vez el cold start menor y si mejora el tiempo de respuesta de las siguientes invocaciones es aún mejor 😉. ¿Que se necesita? Java 11 Docker Maven Acceso a Lambdas en AWS ¿Cómo hacerlo? Esta es la parte entretenida, en un principio fue compleja pero luego de entenderla fue divertido. Para poder lanzar el jar compilado hay que utilizar AWS Lambdas con un custom runtime. El custom runtime tiene un comportamiento que debe ser seguido y se describe en este link y acá . En resumen: existe una URL para obtener un evento, otra para indicar si hay un error al iniciar, también una...

Codersrank - TOP DEVELOPERS IN JAVA

Imagen
Hoy solo quiero dejar las capturas de pantalla de Codersrank en las cuales tengo el agrado de aparecer 😊, no se por cuanto tiempo estaré en el ranking, así que las guardo de recuerdo 😊. Filtro: Chile + Santiago + Java = 1 Filtro: Chile + Java = 6 llegar al 1 en Chile será un poco dificil...

Buenas Practicas creando AWS Lambdas con Java

En esta entrada recopilaré buenas practicas que he aprendido al momento de crear Lambdas en AWS con Java y Maven. Algunas son mis recomendaciones y otras son desde AWS (sobre todo como evitar el cold start). Comenzamos: Todo lo que pueda ser estático tiene que ser estático, de esta manera serán reutilizados en los siguientes request que se realicen en la misma instancia del Lambda. inicializar todo  lo que puedan en el handler del lambda en un bloque estático:  public class LambdaHandler implements RequestStreamHandler { static { // acá } @Override public void handleRequest(InputStream is, OutputStream os, Context ctx) throws IOException { } } Hay que hacer esto porque cuando se instancia la clase hay más poder de computo que el configurado como límite para la lambda, si hay conexiones a DynamoDB hay que instanciar la conexión y hacer una Query (cualquiera) lo importante es que se instancien todas las dependencias. Lo mismo ocurre para conexiones con R...

Java + Cognito: Pre Token Generation Lambda Trigger

En esta ocasión dejaré el código necesario para poder generar la respuesta en un Lambda de AWS que se ejecute como un  Pre Token Generation Lambda Trigger , no es ninguna explicación de que es Lambda o Cognito, lo hago porque no encontré en el universo un ejemplo que explicara el formato de la respuesta usando Java, usando NodeJS habían cientos incluso desde la misma documentación de AWS... Si alguien pasa por el mismo problema y llega acá, este es el código: public class PreTokenGenerationLambdaTrigger implements RequestStreamHandler { private static final ObjectMapper OM; static { OM = new ObjectMapper(); OM.enable(SerializationFeature.INDENT_OUTPUT); ServiceLoader.load(LambdaServicio.class).forEach(LambdaServicio::cargar); } @Override public void handleRequest(InputStream is, OutputStream os, Context ctx) throws IOException { final var request = OM.readTree(is); final var response = (ObjectNode) request; OM.writeValue(os, response); } ...

Records preview en JDK 14 ea

Hoy escribiré un ejemplo del uso del nuevo type declaration Record  en una versión del JDK 14  Early-Access Builds . ¿Que es un Record? Es una nueva declaración de tipo, similar a una clase con las siguientes características (descritas en el JEP 359 ): tiene un nombre y un  state description que define sus componentes. cada componente del estado tiene un método de acceso público con el mismo nombre del componente. tiene un constructor público con la misma firma que el  state description en el cual se inicializa cada campo desde el argumento . implementa equals y hashCode, en donde 2 records serán iguales si son del mismo tipo y contienen el mismo estado. implementa toString con la representación de todos sus componentes. cada componente del  state description es private final . no pueden extender otras clases. no pueden tener otros campos de instancia, solo los del  state description . si se definen otros campos tienen que ser static . un...

JPA-Hibernate + POJO + Projection + ConstructorResult + NativeQuery + Testcontainers + PostgreSQL

Imagen
En esta ocasión mostraré un ejemplo usando Java SE 11 de como mapear una clase no entidad (un POJO) a partir de los datos que existen en la base de datos y que representan a una entidad utilizando ConstructorResult, Projection y una construcción "manual" con JPA. Las pruebas serán realizadas usando Testcontainers junto a Postgresql como base de datos. El procedimiento es el siguiente (se omiten los metodos/imports/anotaciones que no son relevantes y usaré lombok solo para getter/setter): 1- La Entidad Representa la entidad que mantendrá datos en la base de datos y de la cual extraeremos algunos de sus campos para nuestro pojo. @Entity @Table(schema = "jpa", name = "persona") public class Persona { @Id private int id; private String nombre; private String apellido; } 2- El POJO Requiere tener un constructor con los argumentos que la query utilizará: public class PersonaPOJO { private String nn; private String a...

Redis Streams: xadd + xread

Esta ocasión mostraré un ejemplo de Redis Streams , con los metodos xadd y xread utilizando la librería Lettuce .  Generar Mensajes El Stream tendrá el nombre mensajes y cada mensaje enviado tendrá un UUID y un número indicando la cantidad de mensajes enviados: final var cliente = RedisClient.create("redis://localhost:6379"); try (final var con = cliente.connect()) { final var cmd = con.sync(); int i = 0; while (i < 500_000) { final var res = cmd.xadd("mensajes", Map.of(UUID.randomUUID().toString(), String.valueOf(i))); i++; LOGGER.info("enviados: {} - id: {}", i, res); Thread.sleep(1_000); } } cliente.shutdown();  Recibir Mensajes El cliente lee un mensaje a la vez y recuerda el último ID leido para preguntar por los nuevos mensajes y se bloquea 5 segundos esperando mensajes: final var cliente = RedisClient.crea...

Spring Boot + Spring Security + React + Keycloak

Imagen
Ahora mostraré como utilizar Spring Boot , Spring Security y Keycloak para tener recursos protegidos accediendo a ellos utilizando React 😉. Configurar Keycloak Configurar Spring Boot Configurar React   Keycloak Keycloak se puede obtener utilizando docker o desde su página como Standalone server distribution (previamente en este enlace había indicado como obtenerlo y lanzarlo).  Luego de lanzarlo estará disponible localmente y procedemos a realizar su configuración (en mi caso visitando http://localhost:8282/): Si es la primera vez configuramos el usuario administrador. Una vez ingresado entramos a la aplicación: Seleccionamos Add realm y definimos su nombre, en este ejemplo es: sso Luego vamos a Clients y presionamos Create para agregar dos clientes: cliente-uno para Spring Boot y cliente-dos para React, en ambos definimos su Root URL y Web Origins (NO olvidar presionar el boton save cuando realizamos modificaciones, web ...