Ejemplo en Spring Boot con records de Java 16
En este nuevo artículo sobre ejemplo en Spring Boot con records de Java 16, vamos a ver una de las características más importantes que entro a formar parte de Java en la versión 16. Para ello vamos a hacer un simple ejemplo en Spring Boot para poder apreciar mejor su funcionalidad.
¿Qué son los records de Java 16?
En Marzo de este año (2021), salió la nueva versión de Java 16, con nuevas características. Una de esas nuevas características ha sido los records de Java, algo bastante deseado y en parte necesario con lo que podemos simplificar nuestro desarrollo.
Aunque ya apareción en Java 14 como preview y podía ser utiizada si la opción de preview era activada.
¿Qué son los Records?, según la JEP 395, los Records de Java son un nuevo tipo de clase en Java. Este tipo de clases van a permitir modelar objetos de datos simples de una manera más simple y eliminando ese boilerplate para transformar a objetos inmutables.
Esta característica nos va a permitir reducir como he comentado anteriormente, el boilerplate de nuestras clases. Los records nos van a proporcionar un constructor público, métodos de lectura para cada campo, la implementación de hashCode, equals y el toString.
Básicamente podríamos decir que la definición de una clase Record es la declaración de un estado que tiene un contrato con una API que coincide con el estado definido. Lo que implica esto es una cierta perdida de libertad al no poder desacoplar la API de su representación interna.
La definición de un Record es tan simple como hacer lo siguiente:
record Point(int x, int y) { }
La definición de un record consiste en un nombre, parámetros, una cabecera y un body.
Si tuvieramos que hacerlo sin record sería algo así:
public class Point { private int x; private int y; //getters and setters public Point(int x, int y) { ... } public boolean equals(Object o) { ... } public int hashCode() { ... } public String toString() { ... } }
Como podemos ver en el código al hacer uso de record se ha visto muy simplificado, incluso haciendo uso de lombok (aunque no es utilizado con el mismo propósito), el uso de record simplifica todavía más la clase.
Usos de records en Java
Uno de los usos más frecuentes en los que trabajar con records en Java es para hacer uso de DTOs. Al ser clases inmutables y de fácil definición podemos utilizar estos objetos en aplicaciones rest, en la parte del controlador (en nuestro ejemplo podremos verlo).
Es también muy útil para devolver objetos inmutables como puede ser una clase de configuración dentro de Spring que carga las propiedades de un properties.
Decompilar una clase Record en Java
Vamos a ver y a analizar lo que realmente hace un record cuando es compilado por Java. Para poder realizar esta comprobación vamos a nuestro terminal y ejecutamos el comando javap.
public final class com.refactorizando.example.record.model.BrandDto extends java.lang.Record { public com.refactorizando.example.record.model.BrandDto(java.lang.Long, java.lang.String); public final java.lang.String toString(); public final int hashCode(); public final boolean equals(java.lang.Object); public java.lang.Long id(); public java.lang.String name(); }
Al hacer uso de javap, podemos ver el código decompilado de la clase.
Un record en java se va a transformar en una clase final que extiende de java.lang.Record; un constructor con todos los campos que se han definido y la definición de sus campos.
No hacer uso de records al persistir información
Ya que simplificamos nuestra codificación, ¿podríamos hacer uso de records para hacer persistencia de nuestros objetos?, una respuesta rápida es no y seguir haciendo uso de la manera tradicional en la definición de nuestras clases.
Esto es debido a que cuando trabajamos con Hibernate ( si es el caso), no solo se va a centrar en guardar o en leer datos de la base de datos, también gestiona el estado y realiza actualizaciones, algo que con objetos inmutables es complicado de conseguir.
Además los registros no admiten un constructor sin parámetros y la definición de una entidad (@Entity) en Hibernate, necesita constructores sin parámetros, y por último la clase es final, lo que no es permitido para generar entidades con Hibernate.
Ejemplo de uso de records en Java
A continuación vamos a ver como podemos hacer uso de los records de Java 16 en una aplicación simple en Spring Boot. Asegurate de tener java 16 instalado, una buena herramienta para cambiar entre diferentes versiones de Java es hacer uso de sdkman.
Nuestro ejemplo va a consistir en dos records coche (Car) y marca (Brand), en el que una marca estará incluida en un coche. No vamos a realizar persistencia o trabajar con Spring Data, para centrarnos en el uso de records. Ya que, además, el uso de records, como hemos visto antes no debe usarse como entidades.
Si quieres ver el ejemplo completo puedes verlo en nuestro github aquí.
Para ello lo primero es definir los objetos Car y Brand con records.
Definir clases con record en Java
A continuación vamos a definir tanto la clase Car como Brand de nuestro ejemplo haciendo uso de record:
@JsonInclude(JsonInclude.Include.NON_NULL) public record CarDto(@JsonProperty("id") Long id, @JsonProperty("brand") BrandDto brandDto, @JsonProperty("model") String mode, @JsonProperty("color") String color) { }
@JsonInclude(JsonInclude.Include.NON_NULL) public record BrandDto(@JsonProperty("id") Long id, @JsonProperty("name") String name) { }
En la definición de los records hemos añadido Jackson con las propiedades @JsonProperty para permirtir la serialización y deserialización en los campos, ya que utilizamos los records como Dtos.
Para la definición de los record, hay que hacer uso de la palabra reservada record, y pasar por parámetro los campos que queremos que ese objeto tenga.
Conclusión
En este artículo sobre Ejemplo en Spring Boot con records de Java 16, hemos podido ver de manera práctica como el uso de records nos va a facilitar el desarrollo en aplicaciones, por ejemplo, haciendo uso de records como dtos.
Podríamos decir, que Java Records es una característica semántica, que permite una manera para modelar únicamente datos, y proporcionar un patrón de programación común.
Si quieres puedes ver el ejemplo completo aquí.
Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!
Si tienes que ir a un repositorio a buscar una Entity para luego transformala a un DTO hecho con record. Esta classe ‘record’ ofrece alguna forma? Como lo harias?
Record no puede ser usado con entidades o JPA , los atributos ni la clase pueden ser final, no hay setters. Resumiendo JPA no puede ser utilizado con Records porque rompe con algunos requerimientos y principios de JPA.