Ejemplo aplicación Quarkus con Hibernate

Quarkus_Hibernate

Quarkus_Hibernate


Hibernate es un ORM muy conocido y sobre todo ha sido usado en frameworks como Spring , y es el framework de facto de JPA. En esta entrada de refactorizando «Ejemplo aplicación Quarkus con Hibernate«, vamos a ver como podemos implementar y utilizar Hibernate en Quarkus y terminar desplegandolo en Kubernetes. Si quieres ver una breve introducción con un ejemplo en Quarkus, echa un vistazo aquí.

Si tienes cualquier duda sobre los pasos quizás es mejor ver el código directamente, aquí.

Por lo tanto en este artículo vamos a ver:

  • Crear aplicación con Kuarkus con persistencia en Base de Datos
  • Arrancar la aplicación en local
  • Usar la extensión de Quarkus Dekorate para crear la configuración y los ficheros manifest.
  • Hacer Build y Push las imagenes a Dcoker para registrar con la extensión Jib.
  • Hacer Deploy en Kubernetes con los YAML que se han autogenerado.
  • Utilizar secret y config para guardar las propiedades.

¿Qué es Hibernate?

Hibernate es una herramienta de mapeo objeto relacional, de sus siglas en inglés ORM, funciona bajo Java y su objetivo es facilitar el trabajo entre la aplicación Java y la base de datos, haciendo un mapeo de los objetos, que implementa, además la especificación de JPA. Es decir, los campos y tablas de la base de datos, los va a convertir en objetos Java para poder trabajar con ellos. Hibernate nos va a permitir trabajar no solo con base de datos relacionales sino también con bases de datos de tipo NoSQL, haciendo uso de sus anotaciones.

Manos a la obra

A continuación vamos a describir paso a paso como crear y desplegar una aplicación con Quarkus e hibernate.

Si quieres una breve introducción sobre Quarkus, puedes verla en un blog anterior, pulsando aquí.

Tal y como hemos indicado en el título, en este artículo vamos a desplegar una aplicación Quarkus con Hibernate, para ello vamos a empezar desde 0, utilizando el arquetipo de Quarkus para crear nuestro proyecto.

Nuestro ejemplo va a consistir en un concesionario de coches, en el que cada marca de coche puede tener asociados varios coches. Por tanto, vamos a tener dos tablas, una que será marca y otra que será modelo, y se relacionaran entre si con una relación de 1 .. N, es decir, una marca puede tener de 1 a N modelos. El servicio que vamos a crear tendrá que devolver todos los modelos de una marca.

Para conseguir persistir en base de datos nuestras marcas y modelos, vamos a hacer uso de una imagen docker de postgreSql.

Arrancando Base de Datos PostgreSql

Tal y como hemos comentado, en nuestro ejemplo vamos a utilizar para persistir los datos una base de datos relacional, en este caso PostgreSql haciendo uso de Docker.

docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:10.5

Ejecutando el comando anterior por línea de comando se arrancará una base de datos PostgreSql, con usuario y contraseña postgres.

Creando arquetipo de Quarkus

Quarkus nos trae un arquetipo con el que podemos generar el esqueleto o la estructura de nuestra aplicación, para ello vamos a ejecutar el siguiente comando:

mvn io.quarkus:quarkus-maven-plugin:1.9.0.Final:create \
    -DprojectGroupId=com.refactorizando.quarkus.example \
    -DprojectArtifactId=quarkus-hibernate-example \
    -DprojectVersion=0.0.1-SNAPSHOT \
    -DclassName="com.refactorizando.quarkus.example.Controller.CarDealership" \
-Dpath="dealership" \
-Dextensions="kubernetes, jib"

Recuerda tener al menos una versión de maven igual o superior a 3.2

El comando anterior nos creará la estructura básica de Quarkus, con un controlador y un endpoint /dealership.

Podríamos arrancar la aplicación anterior haciendo uso de maven con el siguiente comando:

mvnw compile quarkus:dev

Y ahora si escribimos  http://localhost:8080/dealership, podremos ver lo que nos devuelve la aplicación.

Dependencias Maven para aplicación Quarkus con Hibernate

Para poder crear la capa de persistencia en una aplicación Quarkus con Hibernate, lo primero será añadir las dependencias de Hibernate en nuestro pom.xml:

<dependencies>
    <!-- Hibernate ORM specific dependencies -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-orm</artifactId>
    </dependency>

    <!-- JDBC driver dependencies -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
</dependencies>

Creación de aplicación en Hibernate con Quarkus

Una vez estas dependencias han sido incorporadas a nuestra aplicación vamos a modificar el fichero application.properties que encontrarás en la carpeta resources.

# datasource configuration
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = postgres
quarkus.datasource.password = postgres
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/hibernate_db

quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.sql-load-script=import.sql

A continuación vamos a crear las entidades, Brand y Model.

Brand:

@Entity
public class Brand {

  @Id
  private Long id;

  private String name;

  @OneToMany(mappedBy="brand")
  private List<Model> brands = new ArrayList<>();
}

Model:

@Entity
@NamedQuery(name = "Model.findByBrand", query = "SELECT m FROM Model m  where brand.name =: name")
public class Model {

  @Id
  private Long id;

  private String name;

  @ManyToOne
  @JoinColumn(name="brand")
  private Brand brand;

}

En las dos clases hemos creado las entidades que se mapearan en base de datos haciendo uso de la anotación @Entity. Para poder acceder a base de datos de nuestra aplicación Quarkus vamos a hacer uso de la clase EntityManager que pertenece a javax.persistence.

@ApplicationScoped
public class CarDealerShipService {

  @Inject
  EntityManager entityManager;

  public List<Model> findModelCarByBrandName(String brand) {

    return entityManager.createNamedQuery("Model.findByBrand", Model.class)
        .setParameter("name", brand)
        .getResultList();

  }

}

En la clase anterior hemos hecho uso de la clase EntityManager para poder conectarnos con la Base de Datos, en este caso PostgreSql. Si se observa la entidad Model, hemos creado una NamedQuery (que crea una query de SQL), para poder obtener todos los modelos por una marca. Esa NamedQuery se llama Model.findByBrand. Haciendo uso de la inyección de dependencias hemos inyectado el EntityManager, y hemos creado mediante, @ApplicationScoped un bean del servicio.

Una vez creado el servicio, solo haría falta un controlador que nos devolviese los modelos por una marca. El controlador con el path ha sido creado por el arquetipo de Quarkus, ahora vamos a añadir un nuevo endpoint:

@Path("/dealership")
@Produces("application/json")
@Consumes("application/json")
public class CarDealership {

  @Inject
  CarDealerShipService carDealerShipService;

  @GET
  @Path("/models")
  public Model[] getModelsByBrand(@QueryParam("brand") String brand) {
    return carDealerShipService.findModelCarByBrandName(brand).toArray((new Model[0]));

  }

La clase anterior será el punto de entrada de nuestra aplicación, en la que se ha creado un nuevo endpoint (/models/brand={brand}) al que se le pasará la marca por parámetro.

Arrancando aplicación Quarkus con Hibernate en Local

Para poder arrancar una aplicación en modo desarrollo en Quarkus vamos a ejecutar el siguiente comando:

./mvnw quarkus:dev

Y una vez arrancado podremos hacer peticiones a través del siguiente endpoint:

http://localhost:8080/dealership/models?brand=ford

No te olvides de tener datos en base de datos, tendrás que añadir un fichero import.sql en la carpeta resources

Desplegando nuestra aplicación en Kubernetes

A continuación vamos a añadir dos dependencias nuevas en nuestro pom para poder desplegar nuestra aplicación en Kubernetes.

   <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-kubernetes</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-container-image-jib</artifactId>
    </dependency>

Estas dependencias van a crear los los json/yaml de los servicios y los deployment. También podríamos añadir las extensiones cuando estamos generando el arquetipo del proyecto añadiendo las extensiones -Dextensions=»kubernetes, jib»

Configurar fichero de propiedades para Kubernetes

Una vez que hemos añadido las extensiones para generar las imagenes y desplegar en K8s, necesitamos también configurar nuestro fichero properties o yml de nuestra carpeta resources. En este fichero vamos a definir las propiedades que va a utilizar nuestra aplicación, por ejemplo si el servicio va a ser Load Balancer o NodePort, si vamos a hacer uso de algún config map etc… . Para generar un fichero con todas las propiedades podemos ejecutar el siguiente comando maven:

mvn quarkus:generate-config

Desplegar aplicación de manera manual

Vamos a realizar un despliegue semi manual en kubernetes. Para ello vamos a generar la imagen nativa para subir la imagen del proyecto a nuestro docker local y a continuación, con el fichero kubernetes.yml que se genera con maven, lo subirimos a k8s.

El fichero kuberntes.yml se encuentra en target/kubernetes

Ejecutamos el siguiente comando para crear la imagen:

mvn package -Pnative -Dnative-image.docker-build=true

El comando anterior creará la imagen haciendo un pulling de quarkus/ubi-quarkus-native-image para crear un ejecutable nativo y poder crear un ejecutable que correrá en el contenedor.

Y finalmente a crear el build para docker:

docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-project .

Y ahora ya únicamente nos faltaría subir la imagen a kubernetes haciendo uso del siguiente comando:

kubectl apply -f target/kubernetes/kubernetes.yaml

Desplegar la imagen haciendo uso de maven

Para poder construir la imagen Docker desde la aplicación vamos a necesitar la opción quarkus.container-image.build y si queremos subir la aplicación a nuestro kubernetes local vamos a hacer uso de la opción quarkus.kubernetes.deploy. Tal y como ejecutamos a continuación

mvn clean package -Dquarkus.container-image.build=true -Dquarkus.kubernetes.deploy=true

Después de ejecutar el comando anterior nuestra aplicación debería estar desplegada en Kubernetes. Nuestro comando maven lo que ha hecho ha sido ir a la carpeta target, en la que se han generado los ficheros kubernetes.yml y kubernete.json, y construir una imagen con nuestro jar que se encuentra también en target.

En la siguiente imagen se observa el final del proceso de maven en el que se sube la imagen a kubernetes:

Desplegando imagen en kubernetes|Ejemplo aplicación Quarkus con Hibernate
Desplegando imagen en kubernetes

y con esto ya tendríamos desplegado nuestro servicio, si estas usando minikube por ejemplo, puedes acceder al servicio creado de la siguiente manera:

minikube IP: Para obtener la IP
kubectl get services: Para obtener el puerto

o también puedes hacer un port forward, con el pod el puerto interno y el puerto externo:

kubectl port-forward quarkus-hibernate-example-6c5fdf7cfb-c7j2t 32527 8080

http://ip:port/models/ford

¿La imagen se ha desplegado con error?

Si al desplegar la imagen en kubernetes has tenido algún error mira los siguientes puntos:

  • Verifica que la imagen se ha creado: docker images
  • Asegúrate que el nombre del grupo del contenedor es correcto (propiedad quarkus.container-image.group), por ejemplo, puedes mirar que la imagen que intenta buscar en kubernetes.yml existe.
  • Mira el error con kubectl logs <nombre del pod>
  • Mira la descripción: Kubectl describe pod <nombre del pod>
  • Si el error es que no puedes acceder a las imagenes docker y usas minikube ejecuta el siguiente comando: eval $(minikube docker-env)

Si sigues teniendo algún problema con el despliegue escribe un comentario.

Conclusión

Si estas acostumbrado a trabajar con JPA en un ORM como Hibernate, no te debería costar mucho trabajar con Quarkus e Hibernate ya que su utilización es prácticamente idéntica que por ejemplo con Spring. Las únicas diferencias son las que impone Quarkus, además este framework nos facilita mucho la vida para poder desplegar en Kubernetes.

Si quieres ver nuestro ejemplo lo podrás encontrar pulsando aquí.

Espero que este artículo de Ejemplo de Ejemplo aplicación Quarkus con Hibernate, haya sido de utilidad si tienes alguna duda o sugerencia no dudes en comentarlo o contactar a través de Facebook o Twitter. Y si te ha gustado compártelo en tus redes sociales.

Otros artículos que te pueden interesar

Entity Graph con JPA en Spring Boot

¿Qué es GraphQL?

Patrón Saga en Arquitectura de Microservicios


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *