Mostrando entradas con la etiqueta java. Mostrar todas las entradas
Mostrando entradas con la etiqueta java. Mostrar todas las entradas

domingo, 19 de julio de 2026

JDBI con Spring Boot

JDBI es una librería de código abierto para Java que actúa como una capa de abstracción sobre JDBC (Java Database Connectivity).

Permite interactuar con bases de datos relacionales de forma más rápida y limpia, reduciendo el código repetitivo (boilerplate) sin ocultar el lenguaje SQL.

Creando un proyecto Spring Boot con JDBI

Iremos al sitio para crear nuestro proyecto: https://start.spring.io/

Agregaremos las dependencias de MariaDB y Spring Jdbc.

Una vez creado el proyecto agregaremos una más, la dependencia de JDBI:

pom.xml

        <dependency>
            <groupId>org.jdbi</groupId>
            <artifactId>jdbi3-core</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.jdbi</groupId>
            <artifactId>jdbi3-sqlobject</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.jdbi</groupId>
            <artifactId>jdbi3-spring5</artifactId> 
            <version>3.2.5</version>
        </dependency>

El diseño de nuestra aplicación será modular:

  • repository: para el acceso a los datos de la BD. 
  • model: para el mapeo objeto-relacional. 
  • service: contiene la lógica de negocio. 
  • controller: el punto de entrada de las peticiones HTTP.
  • config: para las configuraciones.

Base de datos de la aplicación

Usaremos MariaDB como BD. El nombre de la BD sera ``soporte_tecnico``. Nuestra tabla es la siguiente:

CREATE OR REPLACE TABLE usuarios(
id int PRIMARY KEY, password varchar(255),
nombre varchar(255), apellidos varchar(255),
correo varchar(255), cvesis varchar(255)
);

Esta entidad relacional describe los atributos de un usuario.

Capa de mapeo objeto-relacional

Crearemos nuestra clase tipo que mapee los atributos de la tabla usuarios.

Usuario.java

package com.codemonkey.demo_jdbi.model;

import org.jdbi.v3.core.mapper.reflect.ColumnName;
import org.jdbi.v3.core.mapper.reflect.JdbiConstructor;

public class Usuario {
    @ColumnName("id") private Long id;
    @ColumnName("nombre") private String nombre;
    @ColumnName("apellidos")private String apellidos;
    @ColumnName("correo") private String correo;
    @ColumnName("cvesis")private String cvesis;


   public Usuario(
    @ColumnName("id") Long id,
    @ColumnName("nombre") String nombre,
    @ColumnName("apellidos") String apellidos,
    @ColumnName("correo") String correo,
    @ColumnName("cvesis") String cvesis) {
    this.id = id;
    this.nombre = nombre;
    this.apellidos = apellidos;
    this.correo = correo;
    this.cvesis = cvesis;
	}


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getApellidos() {
        return apellidos;
    }

    public void setApellidos(String apellidos) {
        this.apellidos = apellidos;
    }

    public String getCorreo() {
        return correo;
    }

    public void setCorreo(String correo) {
        this.correo = correo;
    }

    public String getCvesis() {
        return cvesis;
    }

    public void setCvesis(String cvesis) {
        this.cvesis = cvesis;
    }
}

No incluiremos el campo del password.

Capa de datos

Crearemos una interface para el repositorio de datos.

UsuarioRepository.java

package com.codemonkey.demo_jdbi.repository;

import com.codemonkey.demo_jdbi.model.Usuario;
import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import java.util.List;

@RegisterConstructorMapper(Usuario.class) 
public interface UsuarioRepository {

    @SqlQuery("SELECT id, nombre, apellidos, correo, cvesis FROM usuarios")
    List<Usuario> listarUsuarios();

    @SqlUpdate("INSERT INTO usuarios(id, password, nombre, apellidos, correo, cvesis) VALUES (:id, :password, :nombre, :apellidos, :correo, :cvesis)")
    void insertar(Long id, String password,String nombre, String apellidos, String correo, String cvesis);
}

Esta interface tendrá dos métodos. Uno para consultar los datos con la instrucción SELECT y otro para insertar datos con INSERT.

Capa del servicio

Crearemos una clase tipo service para la lógica del negocio.

UsuarioService.java

package com.codemonkey.demo_jdbi.service;

import com.codemonkey.demo_jdbi.model.Usuario;
import com.codemonkey.demo_jdbi.repository.UsuarioRepository;
import org.jdbi.v3.core.Jdbi;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UsuarioService {

    private final UsuarioRepository usuarioRepository;

    public UsuarioService(Jdbi jdbi) {
        this.usuarioRepository = jdbi.onDemand(UsuarioRepository.class);
    }

    public List<Usuario> listarUsuarios() {
        return usuarioRepository.listarUsuarios();
    }

    public void insertarUsuario(Long id, String password, String nombre, String apellidos, String correo, String cvesis) {
        usuarioRepository.insertar(id, password, nombre, apellidos, correo, cvesis);
    }
}

Capa para el acceso a las peticiones HTTP

Crearemos una clase tipo controller.

UsuarioController.java

package com.codemonkey.demo_jdbi.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResquestBody;
import java.util.logging.Logger; import java.util.logging.Level; import com.codemonkey.demo_jdbi.service.UsuarioService; import com.codemonkey.demo_jdbi.model.Usuario; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @RestController @RequestMapping("/api/usuarios") public class UsuarioController { private static final Logger LOGGER = Logger.getLogger(UsuarioController.class.getName()); private UsuarioService usuarioService; @Autowired public UsuarioController(UsuarioService usuarioService) { this.usuarioService = usuarioService; } // http://localhost:8083/api/usuarios/hola @GetMapping("/hola") public String hola() { LOGGER.log(Level.INFO, "Entramos al primer servicio."); return "El servicio esta vivo."; } // http://localhost:8083/api/usuarios/all @GetMapping("/all") public ResponseEntity<List<Usuario>> getUsuarios() { LOGGER.info("\t ==== Obtenemos todos los usuarios. ===="); List<Usuario> usuarios = usuarioService.listarUsuarios(); if(usuarios.isEmpty()) { return ResponseEntity.noContent().build(); } return ResponseEntity.ok(usuarios); } // http://localhost:8083/api/usuarios/insertar @PostMapping("/insertar") public ResponseEntity<String> insertarUsuario(@RequestBody Usuario usuario) { try { LOGGER.info("Insertando nuevo usuario: " + usuario.getNombre()); usuarioService.insertarUsuario( usuario.getId(), "qwErt@3200$", usuario.getNombre(), usuario.getApellidos(), usuario.getCorreo(), usuario.getCvesis() ); return ResponseEntity.status(HttpStatus.CREATED) .body("Usuario insertado correctamente."); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error al insertar usuario", e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Error al insertar usuario: " + e.getMessage()); } } }

Esta clase expone tres apis:

  • GET http://localhost:8083/api/usuarios/hola 
  • GET http://localhost:8083/api/usuarios/all 
  • POST http://localhost:8083/api/usuarios/insertar

La primera es para probar que la aplicación está activa. La segunda para consultar todos los datos de la tabla usuarios. La tercera para agregar un nuevo usuario.

Construimos la aplicación:

$ mvn clean install -X

Ejecutamos la aplicación:

$ mvn spring-boot:run

Hemos visto cómo crear una aplicación Spring Boot con Jdbi.

Enlaces:

https://jdbi.org/
https://codemonkeyjunior.blogspot.com/2016/02/jdbi-como-alternativa-jdbc.html
https://codemonkeyjunior.blogspot.com/2016/01/conociendo-jdbi.html
https://codemonkeyjunior.blogspot.com/2017/04/jdbi-con-groovy-2.html


domingo, 28 de junio de 2026

Tráiler del documental "Write Once, Run Forever: The Java Story"

Vídeo del tráiler sobre el documental "Write Once, Run Forever: The Java Story".

Descripción:

La historia de Java narra el improbable recorrido de Java, desde su casi desaparición antes incluso de su lanzamiento, pasando por su reinvención para la web, su ascenso como pilar del software empresarial, la batalla por el código abierto y sus múltiples demandas, hasta su notable renacimiento a partir de Java 8.

Contada por quienes lo crearon y la comunidad que lo impulsó.

Saldrá hasta el 17 de julio de 2026. Actualización: se puede ver ahora en: https://www.youtube.com/watch?v=ZqGSg4b_cZA

Enlaces:

https://www.youtube.com/channel/UCsUalyRg43M8D60mtHe6YcA
https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ
https://www.cultrepo.com/

sábado, 17 de enero de 2026

LangChain4j

LangChain4j es una librería para Java que unifica y simplifica la integración de modelos de lenguaje (LLM) y stores vectoriales en tus aplicaciones. Ofrece APIs unificadas para múltiples proveedores (OpenAI, Vertex AI, etc.) y stores (Pinecone, Milvus, etc.), además de un toolbox con patrones comunes como plantillas de prompts, memoria conversacional, RAG, agentes y function calling

Se usa en escenarios empresariales para construir asistentes con RAG, moderación y reglas de entrada/salida, manteniendo control sobre datos e infraestructura.

En pocas palabras, es una opción similar a Spring AI del que hablaremos en otra ocasión.

Sus principales características son:

  • API unificada que permite interactuar con diversos proveedores. 
  • Integración con frameworks como Sprinc Boot, Quarkus y Helidon. 
  • Memoria de conversación. 
  • Soporte RAG. 
  • Function Calling.

¿Qué se puede hacer con esta herramienta?

  • Extracción y tratamiento de texto. 
  • Chatbots. 
  • Agentes de IA. 
  • Etc.

Empezando con LangChain4j

OpenAI es una empresa de investigación y despliegue de IA y es la opción más directa y estable para probar LangChain4j. Iniciemos con un proyecto Java.

Requisitos:

  • Tener el JDK instalado (última versión). 
  • Tener Maven instalado (última versión). 
  • Tener una cuenta OpenAI (https://openai.com)

1. Creamos el proyecto con Maven y nos ubicamos en el directorio generado:

$ mvn archetype:generate -DgroupId=com.inforhomex -DartifactId=demo-langchain4j -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
$ cd demo-langchain4j

2. Agregamos las dependencias necesarias en el archivo ``pom.xml``

<dependencies>
  <!-- Núcleo LangChain4j -->
  <dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>0.31.0</version>
  </dependency>

  <!-- Cliente OpenAI -->
  <dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai</artifactId>
    <version>0.31.0</version>
  </dependency>
</dependencies>

3. Ahora editaremos la clase App.java

package com.inforhomex;


import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class App {
    public static void main(String[] args) {
        ChatLanguageModel model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4o-mini")
            .build();

        String respuesta = model.generate("Explica qué es LangChain4j en 2 frases.");
        System.out.println(respuesta);
    }
}

4. Obtener la API KEY OPENAI. Vamos a este sitio: https://platform.openai.com/account/api-keys

Una vez logeados debemos ir a la sección de API keys y crear una nueva. Deberá crearte una cadena encriptada de aproximandamente 165 caracteres. Guardala en un bloc de notas o cualquier otro editor.

5. Crear la variable de entorno.

Linux:

$ export OPENAI_API_KEY="tu_api_key_aquí"

Windows (Powershell):

$ setx OPENAI_API_KEY "tu_api_key_aquí"

5. Construimos nuestro proyecto Java con Maven:

$ mvn clean install -X

O con este otro comando:

$ mvn clean package

6. Hacer ejecutable nuestro proyecto, para ello modificamos el archivo ``pom.xml``:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.inforhomex</groupId>
  <artifactId>demo-langchain4j</artifactId>
  <version>1.0</version>

  <name>demo-langchain4j</name>
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
  </properties>

  <dependencies>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>2.0.12</version>
</dependency>


    <!-- Cliente OpenAI -->
    <dependency>
      <groupId>dev.langchain4j</groupId>
      <artifactId>langchain4j-open-ai</artifactId>
      <version>0.31.0</version>
    </dependency>

    <!-- Núcleo LangChain4j -->
    <dependency>
      <groupId>dev.langchain4j</groupId>
      <artifactId>langchain4j</artifactId>
      <version>0.31.0</version>
    </dependency>
  </dependencies>

  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
    </repository>
  </repositories>

  <build>
    <plugins>
      <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <mainClass>com.inforhomex.App</mainClass>
            </configuration>
        </plugin>

        <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.3.0</version>
      <configuration>
        <archive>
          <manifest>
            <mainClass>com.inforhomex.App</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>

    </plugins>
  </build>
</project>

7. Ejecutamos el proyecto:

$ mvn exec:java -Dexec.mainClass=com.inforhomex.App

Si tines problemas con tu OPEN AI KEY puedes escribir:

$ mvn compile exec:java -Dexec.mainClass=com.inforhomex.App -DOPENAI_API_KEY=AQUI_TU_OPENAI_KEY

Si todo va bien, deberá mostrarte una respuesta.

Conclusión: Hemos visto como hacer una consulta usando LangChain4j desde una aplicación Java.

Continuarmos con este tema en próximas entregas.

Enlaces:

https://github.com/langchain4j/langchain4j
https://www.linkedin.com/pulse/langchain4j-el-poder-de-la-ia-conversacional-para-java-fabian-aguero-vmv2f/
https://medium.com/mitb-for-all/langchain4j-building-generative-ai-applications-in-java-670ec3d6167d
https://adictosaltrabajo.com/2024/03/05/langchain4j-potenciando-tus-aplicaciones-java-con-inteligencia-artificial-ia-y-modelos-de-lenguaje-de-gran-escala-llm-primeros-pasos/
https://www.reddit.com/r/java/comments/14ff6ie/seekeng_feedback_langchain4j_a_library_for_easy/?tl=es-419
https://www.baeldung.com/maven-java-main-method

jueves, 1 de enero de 2026

Un vistazo a JakartaEE

Los que vienen programando en Java algún tiempo sabrán que trabajar con este lenguaje tiene sus pros y contras. No todo ha sido fácil, pero tampoco algo imposible.

Crear aplicaciones web con Servlets y JSP con sus configuraciones tediosas le complicaban la vida a más de uno. Ni se diga con los odiosos EJB y el uso de servidores como JBoss, Glassfish, etc.

Después vino Spring Framework con su Spring Boot que facilitó la vida a los desarrolladores web. Pues está herramienta se encargaba de lo complicado y dejaba al programador enfocarse en una sola cosa: su código.

Jakarta EE es la evolución directa de Java EE, el Java empresarial que muchos sufrían en antaño. La documentación oficial nos dice:

  • Es conjunto de especificaciones que se utiliza para crear productos y frameworks Java para aplicaciones empresariales a gran escala. 
  • Impulsa sistemas como bancos, sitios de comercio electrónico y plataformas empresariales. 
  • Se basa en Java SE con API adicionales para desarrollo web, acceso a bases de datos, mensajería y seguridad.

Características principales:

  • Tecnologías web: Servlets, JSP, JSF.
  • Lógica de negocio: EJB (Enterprise JavaBeans).
  • Persistencia de datos: JPA Mensajería: JMS Seguridad y transacciones.

Jakarta EE se ejecuta en servidores de aplicaciones como WildFly, GlassFish y Payara, que gestionan la configuración, la escalabilidad y el ciclo de vida.

Jakarta EE Get Started

Para los que vienen de Spring Boot este sitio se les hará familiar:

https://start.jakarta.ee/

Pues es similar al sitio https://start.spring.io/, el cual nos ayuda a crear un proyecto listo para usar y que nos evita las odiosas y tediosas configuraciones.

La documentación oficial nos dice:

"Jakarta EE Get Started crea rápidamente una aplicación Jakarta EE lista para usar, eliminando las complicaciones habituales de configuración. En lugar de empezar con una carpeta vacía, obtienes un proyecto completo y funcional, listo para construir, como si empezaras con un set de LEGO preconstruido que puedes personalizar al instante. Incluye la configuración correcta de Maven, estructuras de directorios estándar y código de ejemplo que demuestra los conceptos clave de Jakarta EE".

En pocas palabras, Jakarta EE aprendió lo que no hizo Java EE.

Al entrar al sitio podemos ver un formulario similar al de Spring Boot Initializer:

Comencemos con un proyecto sencillo.

Descargamos el archivo ZIP y lo descomprimimos en algún directorio:

$ cd jakartaee-hello-world

Veamos el contenido del proyecto:

src\main\java\org\eclipse\jakarta\hello\Hello.java
src\main\java\org\eclipse\jakarta\hello\HelloApplication.java
src\main\java\org\eclipse\jakarta\hello\HelloWorldResource.java

Hello.java

package org.eclipse.jakarta.hello;

public class Hello {

    private String name;

    public Hello(String name) {
        this.name = name;
    }

    public String getHello(){
        return name;
    }
}

La cual es una clase o un bean.

HelloApplication.java

package org.eclipse.jakarta.hello;

import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.ApplicationPath;

@ApplicationPath("rest")
public class HelloApplication extends Application {
    
}

Similar a la aplicación tipo Spring Boot.

HelloWorldResource.java

package org.eclipse.jakarta.hello;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;

@Path("hello")
public class HelloWorldResource {

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    public Hello hello(@QueryParam("name") String name) {
        if ((name == null) || name.trim().isEmpty()) {
            name = "world";
        }

        return new Hello(name);
    }
}

La cual es una clase similar a un Controller en Spring Boot.

En teoría, es una aplicación funcional. Comprobemos esto.

Compilamos el proyecto:

$ mvn clean install

Si todo va bien, nuestra aplicación estará compilada y se habrá creado el WAR en la carpeta generada llamada target.

Ahora será necesario descargar e instalar Glassfish:

https://glassfish.org/download

Una vez descargado y descomprimido en algún directorio en específico, debemos crear la variable de entorno para poder ejecutarlo:

C:\glassfish7\bin

Ahora iniciaremos el servidor Glassfish:

$ asadmin start-domain

Abriremos el navegador en la ruta: http://localhost:4848

Entraremos al administrador de Glassfish. Vamos a Application/Deploy. Seleccionamos nuestro WAR y damos ok. Ya podemos ejecutar la aplicación.

Abrimos el navegador en la ruta: http://localhost:8080/jakartaee-hello-world/rest/hello?name=Thomas_Muller

Salida:

¡Hemos creado nuestra primera aplicación con Jakarta EE!

Detenemos el servidor Glassfish:

$ asadmin stop-domain

Actualización:

Si no quieres instalar Glassfish, puedes ejecutar este comando:

$ mvnw clean package wildfly:run

Deberás descargar la última versión de Wildfly:

https://www.wildfly.org/downloads/

Descomprimir el ZIP y colocarlo en algún directorio (C:\wildfly).

Además de editar el pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.eclipse</groupId>
    <artifactId>jakartaee-hello-world</artifactId>
    <version>0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>jakartaee-hello-world</name>
    <description>
        Simple Jakarta EE 11 application running on WildFly.
    </description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.report.sourceEncoding>UTF-8</project.report.sourceEncoding>
        <maven.compiler.release>21</maven.compiler.release>
        <jakartaee-api.version>11.0.0-RC1</jakartaee-api.version>
        <compiler-plugin.version>3.13.0</compiler-plugin.version>
        <war-plugin.version>3.4.0</war-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-core-api</artifactId>
            <version>${jakartaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>jakartaee-hello-world</finalName>
        <plugins>
            
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>4.2.0.Final</version>
                <configuration>
                    <jbossHome>C:\wildfly</jbossHome>
                    <startupTimeout>180</startupTimeout>
                </configuration>
            </plugin>

            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler-plugin.version}</version>
            </plugin>

           
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>${war-plugin.version}</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project> 

Ya podrás desplegarlo sin la necesidad de iniciar Glassfish.

Feliz año 2026

Este es el post número 400 del blog.😉

Enlaces:

https://jakarta.ee/
https://www.linkedin.com/pulse/java-explained-servlets-jsp-jakarta-ee-rohit-bhosale-r2gzf/?trackingId=XgJjdE8PQombg7SZoMmx9Q%3D%3D
https://jakarta.ee/learn/starter-guides/a-comprehensive-beginners-guide-to-the-get-started/

sábado, 11 de octubre de 2025

Programando en Java no. 10: Consumir una API con la librería OkHttp

En el post anterior vimos como consumir una API desde C#. Ahora lo haremos con Java y OkHttp, un cliente HTTP que es muy eficiente y que ofrece:

  • La compatibilidad con HTTP/2 permite que todas las solicitudes al mismo host compartan un socket. 
  • La agrupación de conexiones reduce la latencia de las solicitudes (si HTTP/2 no está disponible). GZIP transparente reduce el tamaño de las descargas. 
  • El almacenamiento en caché de respuestas evita por completo que la red reciba solicitudes repetidas.

Además de seguir especificaciones HTTP modernas como:

  • Semántica HTTP - RFC 9110.
  • Almacenamiento en caché HTTP - RFC 9111 
  • HTTP/1.1 - RFC 9112 
  • HTTP/2 - RFC 9113 
  • WebSockets - RFC 6455
  • SSE - Eventos enviados por el servidor.

1. Comencemos creando el proyecto con Maven:

$ mvn archetype:generate \
        -DgroupId=com.inforhomex.app \
        -DartifactId=proyecto \
        -DarchetypeArtifactId=maven-archetype-quickstart \
        -DarchetypeVersion=1.4 \
        -DinteractiveMode=false

Nos posicionamos en el directorio creado y modificamos la clase principal.

App.java

package com.inforhomex.app;

import okhttp3.*;
import java.io.IOException;
import static java.lang.System.out;
import static java.lang.System.err;

/**
 * @author Codemonkey Junior
 */
public class App {

    public static final String URL_STRING = "http://localhost:3000/api/saludo";
    public static void main(String[] args) {
        out.println("\t [ Consumiendo una API con okhttp ]");
        hacerPeticionEnApi(args);
    }

    private static void hacerPeticionEnApi(String... args){
        OkHttpClient client = new OkHttpClient();
        HttpUrl.Builder urlBuilder = HttpUrl.parse(URL_STRING).newBuilder();
        urlBuilder.addQueryParameter("id", "765421");
        final String finalUrl = urlBuilder.build().toString();
        Request.Builder requestBuilder = new Request.Builder()
        .url(finalUrl).method("GET", null)
        .addHeader("application-name", "application-java");
        Request request = requestBuilder.build();
        try(Response response = client.newCall(request).execute()){
            out.println(response.code());
            if(response.body() != null){
                out.println(response.body().string());
            }else{
                out.println("La respuesta es: null");
            }
        }catch(IOException ioex){
            err.printf("Excepcion: %s\n", ioex.getMessage());
        }

    }

}

En esta clase creamos un cliente gracias a la librería okhttp3 y en específico a la clase ``OkHttpClient``. Indicamos la URL del servicio (hecho en Node JS). Indicamos el valor a mandar (id) y el nombre de la aplicación en las cabeceras (header).

Compilamos la aplicación:

$ mvn clean compile

Reusaremos el servicio creado en el post anterior.

index.js

import express from 'express';


const app = express();
const port = 3000;

// Parsear JSON
app.use(express.json());

app.get('/', (req, res) => {
    res.send('Hola, mundo desde Node JS y Express.');
});



app.get('/api/saludo', (req, res) => {
  const id = req.query.id || 'desconocido';
  const appName = req.headers['application-name'] || 'sin nombre';

  res.json({
    mensaje: `¡Hola! Recibí tu ID: ${id}`,
    origen: `Aplicación: ${appName}`
  });
});



app.listen(port, () => {
    console.log(`Escuchando desde el puerto: http://localhost:${port}`);
});

Ejecutamos el proyecto node e iniciará el servicio en la url: http://localhost:3000

$ npm start

Ejecutamos la aplicación Java con Maven, pero antes debemos hacer unos ajustes al ``pom.xml``

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.inforhomex.app</groupId>
  <artifactId>proyecto-okhtpp</artifactId>
  <version>1.0</version>

  <name>proyecto-okhtpp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.release>17</maven.compiler.release>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.11.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp-bom</artifactId>
        <version>5.2.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- Optionally: parameterized tests support -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.squareup.okhttp/okhttp -->
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp-jvm</artifactId>
      <version>5.1.0</version>
    </dependency>

    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>mockwebserver3</artifactId>
    </dependency>

    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>logging-interceptor</artifactId>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement>
      <plugins>

        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>exec-maven-plugin</artifactId>
          <version>1.4.0</version>
          <configuration>
            <mainClass>com.inforhomex.app.App</mainClass>
          </configuration>
        </plugin>


        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.3.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.4.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.12.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.6.1</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

Esto nos permitirá agregar las librerías y ejecutar la aplicación con Maven:

$ mvn exec:java

Si todo es correcto, veremos en consola el resultado:

         [ Consumiendo una API con okhttp ]
200
{"mensaje":"¡Hola! Recibí tu ID: 765421","origen":"Aplicación: application-java"}

¡Hemos consumido un servicio Node JS con Java y la librería okhttp!

Más ejemplos en próximas entregas.

Enlaces:

https://square.github.io/okhttp/


Jai un lenguaje de programación inspirado en C++

Hoy hablaremos de un nuevo lenguaje de programación llamado Jai . Se trata de un lenguaje de programación que está desarrolland...

Etiquetas

Archivo del blog