<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ciro</title>
    <description>The latest articles on DEV Community by Ciro (@gekyzo).</description>
    <link>https://dev.to/gekyzo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F240507%2F870ff36f-851b-4b6a-9712-eaeccacf5e29.jpg</url>
      <title>DEV Community: Ciro</title>
      <link>https://dev.to/gekyzo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gekyzo"/>
    <language>en</language>
    <item>
      <title>El otro Java + Script, o cómo hacer scripting con Java</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Tue, 04 Nov 2025 23:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/el-otro-java-script-o-como-hacer-scripting-con-java-1m1k</link>
      <guid>https://dev.to/gekyzo/el-otro-java-script-o-como-hacer-scripting-con-java-1m1k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Real Java script, the only good JavaScript - Josh Long&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Java ha evolucionado mucho más allá de ser solo un lenguaje para grandes aplicaciones empresariales. Con las versiones modernas, ahora podemos crear scripts simples y ejecutables de forma rápida, similar a lenguajes como Python o Bash.&lt;/p&gt;

&lt;h2&gt;
  
  
  La nueva sintaxis de main
&lt;/h2&gt;

&lt;p&gt;Una de las mejoras más significativas es la sintaxis simplificada del método &lt;code&gt;main&lt;/code&gt;. Adiós a la verbosidad tradicional:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;script.java&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Así de simple. No más &lt;code&gt;public static void main(String[] args)&lt;/code&gt;, no más clases obligatorias. Solo el código que necesitas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Convirtiendo tu código en un script ejecutable
&lt;/h2&gt;

&lt;p&gt;Para hacer tu archivo Java directamente ejecutable desde la terminal, sigue estos pasos:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Elimina la extensión del archivo
&lt;/h3&gt;

&lt;p&gt;Renombra &lt;code&gt;script.java&lt;/code&gt; a simplemente &lt;code&gt;script&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Agrega el shebang
&lt;/h3&gt;

&lt;p&gt;Al inicio del archivo, añade esta línea especial:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;script&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;!/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El shebang (&lt;code&gt;#!&lt;/code&gt;) le indica al sistema operativo que use Java para ejecutar este archivo. El parámetro &lt;code&gt;--source 25&lt;/code&gt; especifica la versión de Java a utilizar.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Dale permisos de ejecución
&lt;/h3&gt;

&lt;p&gt;En tu terminal, ejecuta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este comando hace que el archivo sea ejecutable por todos los usuarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Ejecuta tu script
&lt;/h3&gt;

&lt;p&gt;Ahora puedes correr tu script directamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y verás tu salida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hola
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Por qué es útil?
&lt;/h2&gt;

&lt;p&gt;Esta funcionalidad es perfecta para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatización&lt;/strong&gt;: Tareas repetitivas sin necesidad de compilar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototipado rápido&lt;/strong&gt;: Probar ideas sin estructura de proyecto&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utilidades&lt;/strong&gt;: Pequeñas herramientas de línea de comandos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aprendizaje&lt;/strong&gt;: Enseñar Java sin la complejidad inicial&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Java ya no es solo para aplicaciones grandes. Ahora también puedes usarlo para scripts rápidos y prácticos, combinando la simplicidad de lenguajes de scripting con el poder y la robustez de Java.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Configurar un CDN gratuito con GitHub y jsDelivr</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Tue, 21 Oct 2025 22:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/configurar-un-cdn-gratuito-con-github-y-jsdelivr-28al</link>
      <guid>https://dev.to/gekyzo/configurar-un-cdn-gratuito-con-github-y-jsdelivr-28al</guid>
      <description>&lt;p&gt;¿Necesitas servir archivos CSS o JavaScript desde un CDN pero no quieres pagar por servicios de terceros? Existe una solución simple y gratuita que aprovecha GitHub y jsDelivr.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Cuando desarrollas aplicaciones web, es común necesitar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compartir hojas de estilo CSS entre múltiples proyectos&lt;/li&gt;
&lt;li&gt;Servir archivos estáticos con baja latencia global&lt;/li&gt;
&lt;li&gt;Cachear recursos de forma eficiente&lt;/li&gt;
&lt;li&gt;Versionar tus assets de manera confiable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Los CDN tradicionales pueden ser costosos o requerir configuración compleja. Pero hay una alternativa mejor.&lt;/p&gt;

&lt;h2&gt;
  
  
  La solución: GitHub + jsDelivr
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.jsdelivr.com/" rel="noopener noreferrer"&gt;jsDelivr&lt;/a&gt; es un CDN gratuito que puede servir archivos directamente desde repositorios de GitHub. No requiere registro, configuración ni costo alguno.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ventajas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gratis y sin límites&lt;/strong&gt; para proyectos open source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red global de servidores&lt;/strong&gt; con baja latencia&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caché automático&lt;/strong&gt; para mejorar el rendimiento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control de versiones&lt;/strong&gt; mediante tags de Git&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minificación automática&lt;/strong&gt; disponible&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementación paso a paso
&lt;/h2&gt;

&lt;p&gt;Vamos a crear un CDN para servir archivos CSS, similar a &lt;a href="https://github.com/Gekyzo/stylesheet-cdn" rel="noopener noreferrer"&gt;este ejemplo real&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Crea un repositorio en GitHub
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;stylesheet-cdn
&lt;span class="nb"&gt;cd &lt;/span&gt;stylesheet-cdn
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Agrega tus archivos CSS
&lt;/h3&gt;

&lt;p&gt;Crea una carpeta &lt;code&gt;styles/&lt;/code&gt; y añade tu archivo CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;styles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ejemplo, &lt;code&gt;styles/mis-estilos.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Tu CSS aquí */&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;-apple-system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Roboto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Oxygen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cantarell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2c3e50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f4f4f4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Sube el repositorio a GitHub
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add stylesheet"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Usa tu archivo desde el CDN
&lt;/h3&gt;

&lt;p&gt;Ahora puedes incluir tu CSS en cualquier página web:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
      &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
      &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/gh/TuUsuario/stylesheet-cdn@main/styles/mahonnaise.vs-code-markdown-theme.css"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;¡Hola mundo!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Este CSS se sirve desde un CDN global gratuito.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Patrón de URL
&lt;/h3&gt;

&lt;p&gt;El formato de URL de jsDelivr es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://cdn.jsdelivr.net/gh/{usuario}/{repositorio}@{branch}/ruta/al/archivo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mejores prácticas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Usa versiones en producción
&lt;/h3&gt;

&lt;p&gt;Para proyectos en producción, es recomendable usar tags de Git en lugar de &lt;code&gt;@main&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Crea un tag&lt;/span&gt;
git tag v1.0.0
git push origin v1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- URL con versión específica --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/gh/TuUsuario/stylesheet-cdn@v1.0.0/styles/mahonnaise.vs-code-markdown-theme.css"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto asegura que tu aplicación no se rompa si actualizas el archivo en el futuro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minificación automática
&lt;/h3&gt;

&lt;p&gt;jsDelivr puede minificar tus archivos automáticamente añadiendo &lt;code&gt;.min&lt;/code&gt; antes de la extensión:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/gh/TuUsuario/stylesheet-cdn@v1.0.0/styles/mahonnaise.vs-code-markdown-theme.min.css"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Considera el caché
&lt;/h3&gt;

&lt;p&gt;Los archivos se cachean en el CDN, por lo que los cambios pueden tardar 5-10 minutos en propagarse. Para desarrollo, usa &lt;code&gt;@main&lt;/code&gt;. Para producción, usa tags versionados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso
&lt;/h2&gt;

&lt;p&gt;Esta técnica es perfecta para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Librerías CSS compartidas&lt;/strong&gt; entre múltiples proyectos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Themes y plantillas&lt;/strong&gt; de código abierto&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archivos JavaScript&lt;/strong&gt; de utilidades comunes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursos estáticos&lt;/strong&gt; como fuentes o iconos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototipos rápidos&lt;/strong&gt; sin necesidad de configurar hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitaciones
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El repositorio debe ser &lt;strong&gt;público&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;No es ideal para archivos muy grandes (&amp;gt;50MB)&lt;/li&gt;
&lt;li&gt;El caché puede dificultar el desarrollo activo (usa &lt;code&gt;@main&lt;/code&gt; para desarrollo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Con GitHub y jsDelivr puedes tener un CDN global de nivel empresarial completamente gratis. Esta solución es ideal para proyectos open source, bibliotecas compartidas, y cualquier recurso estático que quieras distribuir eficientemente.&lt;/p&gt;

&lt;p&gt;El código completo de ejemplo está disponible en &lt;a href="https://github.com/Gekyzo/stylesheet-cdn" rel="noopener noreferrer"&gt;github.com/Gekyzo/stylesheet-cdn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cdn</category>
      <category>github</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Guía rápida SDKMAN!</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Wed, 08 Oct 2025 20:59:05 +0000</pubDate>
      <link>https://dev.to/gekyzo/sdkman-ioe</link>
      <guid>https://dev.to/gekyzo/sdkman-ioe</guid>
      <description>&lt;h1&gt;
  
  
  Guía de SDKMAN, gestionar versiones de Java fácilmente
&lt;/h1&gt;

&lt;p&gt;Si trabajas con Java, seguramente has tenido que lidiar con diferentes versiones según el proyecto. SDKMAN es una herramienta que hace esta tarea mucho más sencilla, permitiéndote instalar y cambiar entre versiones de Java con un simple comando.&lt;/p&gt;

&lt;p&gt;En este artículo te muestro cómo instalarlo y usar sus funciones principales.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalación
&lt;/h2&gt;

&lt;p&gt;Para instalar SDKMAN en tu sistema (Linux, macOS o WSL), ejecuta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://get.sdkman.io"&lt;/span&gt; | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez completada la instalación, verificamos que todo funcionó correctamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdk version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si vemos la versión de sdkman, la instalación se habrá completado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listar distribuciones de Java
&lt;/h2&gt;

&lt;p&gt;SDKMAN soporta múltiples distribuciones de Java (Oracle, Temurin, GraalVM, etc.). Para ver todas las versiones disponibles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdk list java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este comando nos mostrará una lista completa con todas las distribuciones y versiones. Si buscamos algo específico, por ejemplo solo versiones de Java 21, puedes filtrar los resultados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdk list java | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;" 21&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto nos mostrará únicamente las distribuciones de Java 21, haciendo más fácil encontrar la que necesitemos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalar una versión de Java
&lt;/h2&gt;

&lt;p&gt;Una vez que hemos identificado la versión que queremos, utilizaremos su identificador para instalarlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdk &lt;span class="nb"&gt;install &lt;/span&gt;java 21.0.2-open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SDKMAN descargará e instalará esa versión automáticamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Establecer la versión de Java
&lt;/h2&gt;

&lt;p&gt;Aquí es donde SDKMAN realmente brilla. Puedes configurar qué versión usar de dos formas:&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuración global
&lt;/h3&gt;

&lt;p&gt;Para cambiar la versión de Java que usaremos en todo tu sistema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdk use java 21.0.2-open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuración por directorio
&lt;/h3&gt;

&lt;p&gt;Si trabajamos en varios proyectos que requieren diferentes versiones de Java, podemos configurar una versión específica para cada directorio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdk &lt;span class="nb"&gt;env &lt;/span&gt;init
sdk use java 21.0.2-open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estos comandos generan un archivo &lt;code&gt;.sdkmanrc&lt;/code&gt; en el directorio actual. Este archivo refleja la versión de Java que utilizaremos en ese directorio en específico, sin alterar la configuración global.&lt;/p&gt;

&lt;p&gt;Cada vez que entremos a ese directorio, SDKMAN detectará el archivo y usará automáticamente la versión correcta.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Anotación @JsonUnwrapped</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Mon, 20 Mar 2023 08:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/anotacion-jsonunwrapped-19ac</link>
      <guid>https://dev.to/gekyzo/anotacion-jsonunwrapped-19ac</guid>
      <description>&lt;p&gt;La anotación &lt;code&gt;@JsonUnwrapped&lt;/code&gt; es una anotación de la biblioteca Jackson para Java que se &lt;strong&gt;utiliza para indicar una propiedad no debe estar anidada en la estructura JSON resultante,&lt;/strong&gt; sino que debe estar a nivel superior.&lt;/p&gt;

&lt;p&gt;Por ejemplo, supongamos que tenemos una clase &lt;code&gt;Person&lt;/code&gt; que tiene una propiedad &lt;code&gt;Address&lt;/code&gt; que también es una clase con sus propias propiedades. Si queremos serializar un objeto &lt;code&gt;Person&lt;/code&gt; en JSON, la estructura resultante sería algo así como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Juan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"street"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Calle 123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ciudad de México"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CDMX"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sin embargo, si queremos que las propiedades de &lt;code&gt;Address&lt;/code&gt; estén en el mismo nivel que las propiedades de &lt;code&gt;Person&lt;/code&gt;, podemos utilizar la anotación &lt;code&gt;@JsonUnwrapped&lt;/code&gt; en la propiedad &lt;code&gt;Address&lt;/code&gt;. La clase &lt;code&gt;Person&lt;/code&gt; se vería así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@JsonUnwrapped&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;street&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al serializar un objeto &lt;code&gt;Person&lt;/code&gt; utilizando esta clase, la estructura resultante sería:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Juan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"street"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Calle 123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ciudad de México"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CDMX"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, las propiedades de &lt;code&gt;Address&lt;/code&gt; se desempaquetaron y se incluyeron &lt;strong&gt;en el mismo nivel que las propiedades de &lt;code&gt;Person&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;En resumen, la anotación &lt;code&gt;@JsonUnwrapped&lt;/code&gt; es una herramienta que puede ser útil en situaciones en las que queremos una estructura JSON más simple o para facilitar la integración con otros sistemas que esperan una estructura JSON específica.&lt;/p&gt;

</description>
      <category>java</category>
      <category>spring</category>
      <category>jackson</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Anotación @Transient</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Tue, 24 Jan 2023 23:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/anotacion-transient-1548</link>
      <guid>https://dev.to/gekyzo/anotacion-transient-1548</guid>
      <description>&lt;p&gt;Mediante la anotación &lt;code&gt;@Transient&lt;/code&gt; (o transitorio en español) podemos crear atributos en clases de tipo entidad (anotadas con &lt;code&gt;@Entity&lt;/code&gt;) &lt;strong&gt;que no van a persistir en la base de datos&lt;/strong&gt;. Igualmente, los atributos anotados con &lt;code&gt;@Transient&lt;/code&gt; no se mapean con ninguna columna de la entidad.&lt;/p&gt;

&lt;p&gt;Gracias a esta funcionalidad, podemos crear comportamientos como el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"group"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserGroup&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserType&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Transient&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PermissionLevel&lt;/span&gt; &lt;span class="n"&gt;permissionLevel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Este atributo NO se almacenará en la base de datos&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;setPermissionLevel&lt;/span&gt;&lt;span class="o"&gt;(...)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos ver que el atributo &lt;code&gt;PermissionLevel&lt;/code&gt; no se almacenará en la base de datos, ya que puede que queramos actualizar su valor en tiempo de ejecución, utilizando en primer lugar unos valores o criterios, y según el usuario interactúa con la aplicación que estos valores cambien.&lt;/p&gt;

</description>
      <category>gratitude</category>
      <category>opensource</category>
      <category>learning</category>
    </item>
    <item>
      <title>JUnit Cómo repetir un test con parámetros</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Wed, 16 Nov 2022 23:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/junit-como-repetir-un-test-con-parametros-1l15</link>
      <guid>https://dev.to/gekyzo/junit-como-repetir-un-test-con-parametros-1l15</guid>
      <description>&lt;p&gt;En publicaciones anteriores hemos visto de qué maneras se podía &lt;a href="https://dev.to/gekyzo/como-repetir-un-test-n-iteraciones-36pd?preview=8d5432e73aff87d94e34f32a0e291f6b934a91366ba4c244147aa297e347bf61455da58a71aba758bc0292a658d687a412063be791dfa6a4a76a5df8"&gt;repetir la ejecución de un test&lt;/a&gt;, así como la manera de &lt;a href="https://dev.to/gekyzo/junit-como-ejecutar-un-test-con-parametros-4cp3?preview=a4e5383b084aa4788dc11b0a971147c820f6e17c8a8dff5aafffdad71e0854457949698c8f50fe1c35748a5967db228910b1b0ac698de492219a6418"&gt;parametrizar un test&lt;/a&gt;.&lt;br&gt;
En esta ocasión vamos a ver &lt;strong&gt;cómo unir ambas ideas para repetir un test parametrizado&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Utilizaremos para ello el mismo ejemplo de la publicación repetir la ejecución de un test, recuerdo que se trata de un &lt;strong&gt;método que genera un número aleatorio de N dígitos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inicialmente, puede que pensamos que es suficiente con combinar las anotaciones mencionadas en las otras publicaciones, &lt;code&gt;@RepeatedTest&lt;/code&gt; + &lt;code&gt;@ParameterizedTest&lt;/code&gt;, pero lamentablemente &lt;strong&gt;JUnit no soporta esta funcionalidad&lt;/strong&gt; actualmente. Por fortuna la &lt;strong&gt;solución alternativa&lt;/strong&gt; es muy simple.&lt;/p&gt;

&lt;p&gt;Supongamos que partimos de un test parametrizado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Parameters:
 * 1. int - The lower bound.
 * 2. int - The upper bound.
 * 3. int - The number of digits of the random generated value.
 */&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;randomNumberGeneratorParams&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99999&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
&lt;span class="nd"&gt;@MethodSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"randomNumberGeneratorParams"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Random numbers generator"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;random_numbers_generator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numOfDigits&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;    
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RandomUtil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numOfDigits&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, random is too high"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, actual is too low"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test passed: 5 of 5 ✅&lt;/span&gt;
&lt;span class="c1"&gt;// [1] low = 1, high = 9, numOfDigits = 1 -&amp;gt; numero generado 6&lt;/span&gt;
&lt;span class="c1"&gt;// [2] low = 10, high = 99, numOfDigits = 2 -&amp;gt; número generado 56&lt;/span&gt;
&lt;span class="c1"&gt;// [3] low = 100, high = 999, numOfDigits = 3 -&amp;gt; ...&lt;/span&gt;
&lt;span class="c1"&gt;// [4] low = 1000, high = 9999, numOfDigits = 4&lt;/span&gt;
&lt;span class="c1"&gt;// [5] low = 10000, high = 99999, numOfDigits = 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos imaginar que &lt;strong&gt;este test no es muy fiable&lt;/strong&gt;, ya que sólo hemos generado 1 número aleatorio para cada uno de nuestros casos de uso (generar un número de 1, 2, 3, 4 y 5 dígitos).&lt;/p&gt;

&lt;p&gt;Para confirmar con seguridad que la función aleatoria es correcta, sería mejor si pudiéramos &lt;strong&gt;generar N números en cada rango&lt;/strong&gt; o caso de uso, y comprobar que todos ellos cumplen con el test.&lt;/p&gt;

&lt;p&gt;Veamos cómo hacerlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;NUMBER_REPETITIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1_000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Parameters:
 * 1. int - The lower bound.
 * 2. int - The upper bound.
 * 3. int - The number of digits of the random generated value.
 */&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;randomNumberGeneratorParams&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99999&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
&lt;span class="nd"&gt;@MethodSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"randomNumberGeneratorParams"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Random numbers generator"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;random_numbers_generator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numOfDigits&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
 &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;iterationCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- Mediante el uso del loop do-while, podemos iterar la generación de los números aleatorios&lt;/span&gt;
     &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RandomUtil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numOfDigits&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, random is too high"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, actual is too low"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="n"&gt;iterationCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterationCount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;NUMBER_REPETITIONS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test passed: 5 of 5 ✅&lt;/span&gt;
&lt;span class="c1"&gt;// [1] low = 1, high = 9, numOfDigits = 1 -&amp;gt; números generados: 6, 3, 1, 3, 4, 2, 6, 8, 9...1_000_000 de números generados&lt;/span&gt;
&lt;span class="c1"&gt;// [2] low = 10, high = 99, numOfDigits = 2 -&amp;gt; ...&lt;/span&gt;
&lt;span class="c1"&gt;// [3] low = 100, high = 999, numOfDigits = 3&lt;/span&gt;
&lt;span class="c1"&gt;// [4] low = 1000, high = 9999, numOfDigits = 4&lt;/span&gt;
&lt;span class="c1"&gt;// [5] low = 10000, high = 99999, numOfDigits = 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De esta manera, el test &lt;strong&gt;generará tantos números como indiquemos&lt;/strong&gt; en &lt;code&gt;NUMBER_REPETITIONS&lt;/code&gt;, y &lt;strong&gt;confirmará que todos ellos cumplen&lt;/strong&gt; con las afirmaciones del test.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>spanish</category>
      <category>spring</category>
      <category>java</category>
    </item>
    <item>
      <title>JUnit Cómo parametrizar un test</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Mon, 14 Nov 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/junit-como-ejecutar-un-test-con-parametros-4cp3</link>
      <guid>https://dev.to/gekyzo/junit-como-ejecutar-un-test-con-parametros-4cp3</guid>
      <description>&lt;p&gt;JUnit cuenta con una serie de funcionalidades orientadas a ejecutar tests en nuestra aplicación. &lt;br&gt;
Una de estas funcionalidades son los &lt;strong&gt;tests parametrizados&lt;/strong&gt;, que nos permiten poder declarar los valores que necesitemos fuera del propio test.&lt;/p&gt;

&lt;p&gt;Para entender su funcionamiento supongamos que nuestra aplicación cuenta con un &lt;strong&gt;validador de códigos bancarios IBAN&lt;/strong&gt;, que comprueba si un valor determinado cumple el patrón esperado en dichos códigos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Los códigos IBAN utilizados en esta publicación han sido generados mediante la web &lt;a href="http://randomiban.com/?country=Spain"&gt;http://randomiban.com/?country=Spain&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IbanValidator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Regex pattern that an Iban must match&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;PATTERN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^ES[0-9]{2}[0-9]{20}$"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PATTERN&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;    
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora supongamos que tenemos un test sobre esta clase con la siguiente forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Check validity of IBAN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;check_validity_iban&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;IbanValidator&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ES7921000813610123456789"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test passed: 1 of 1 ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, en este ejemplo estamos comprobando únicamente un valor concreto para el código IBAN, por lo que &lt;strong&gt;el test estaría sesgado&lt;/strong&gt;.&lt;br&gt;
Podríamos enfrentarnos a un &lt;strong&gt;falso positivo&lt;/strong&gt;, ya que si desconocemos la implementación del método &lt;code&gt;isValid()&lt;/code&gt; podría ser que siempre devuelva &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para resolver este problema, sería mejor probar la validación con diferentes valores de IBAN. Nuestro primer instinto podría ser copiar el test N veces, tantas como códigos IBAN diferentes queramos probar, pero JUnit nos facilita este trabajo mediante &lt;strong&gt;el uso de la anotación&lt;/strong&gt; &lt;code&gt;@ParameterizedTest&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  @ParameterizedTest
&lt;/h2&gt;

&lt;p&gt;Para indicar el origen de los parámetros de un test parametrizado, debemos hacer uso de otras anotaciones como:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@ValueSource&lt;/code&gt;: permite indicar los valores directamente en la anotación.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;@MethodSource&lt;/code&gt;: permite hacer referencia a un método &lt;em&gt;proveedor&lt;/em&gt; que contiene los parámetros.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  @ValueSource
&lt;/h3&gt;

&lt;p&gt;Utilizando esta anotación, podemos declarar los valores del parámetro de nuestro test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.params.ParameterizedTest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.params.provider.ValueSource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;lt;- Utilizamos la anotación @ParameterizedTest en lugar de @Test&lt;/span&gt;
&lt;span class="nd"&gt;@ValueSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"ES7921000813610123456789"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ES1600755981885574867892"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos en la anotación @ValueSource el tipo de parámetro (en este caso String) seguido de los valores que queremos probar&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Check validity of IBAN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;check_validity_iban&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos en el test el tipo y nombre del nuestro parámetro&lt;/span&gt;
    &lt;span class="nc"&gt;IbanValidator&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test passed: 2 of 2 ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una de las limitaciones que tiene &lt;code&gt;@ValueSource&lt;/code&gt; es que únicamente podemos hacer uso de un parámetro para el test, y en ocasiones esto puede ser insuficiente.&lt;br&gt;
Para resolver este problema debemos hacer uso de la anotación alternativa  &lt;code&gt;@MethodSource&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  @MethodSource
&lt;/h3&gt;

&lt;p&gt;Aplicando esta anotación al mismo ejemplo, el test quedaría de la siguiente forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.params.ParameterizedTest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.params.provider.Arguments&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.params.provider.MethodSource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;testIbanValidityParams&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Creamos un método proveedor donde indicamos &lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ES7921000813610123456789"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ES1600755981885574867892"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
&lt;span class="nd"&gt;@MethodSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"testIbanValidityParams"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos en la anotación @MethodSource el nombre del método que contiene los parámetros&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Check validity of IBAN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;check_validity_iban&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;IbanValidator&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test passed: 2 of 2 ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, lo único que necesitamos es crear un método estático que devuelva un &lt;code&gt;Stream&amp;lt;Arguments&amp;gt;&lt;/code&gt;, y estos serán utilizados por el test parametrizado.&lt;br&gt;
Algunas de las ventajas de esta anotación frente a &lt;code&gt;@ValueSource&lt;/code&gt; son:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Al extraer los parámetros a un método, podemos documentar mejor el test, ya que podemos comentar en el método proveedor información sobre cada parámetro.&lt;/li&gt;
&lt;li&gt;El método &lt;code&gt;Arguments.of()&lt;/code&gt; espera que &lt;strong&gt;indiquemos 1 o N parámetros&lt;/strong&gt;, por lo que podemos aumentar los casos de uso de nuestro test realizando una simple modificación:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Parameters:
 * 1. String - An example of an IBAN code to be validated.
 * 2. boolean - The expected validation
 */&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;testIbanValidityParams&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ES7921000813610123456789"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Creamos un nuevo parámetro booleano con la respuesta esperada&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ES1600755981885574867892"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ESX921000813610123456789"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"E81600755981885574867892"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
&lt;span class="nd"&gt;@MethodSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"testIbanValidityParams"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Check validity of IBAN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;check_validity_iban&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- Indicamos el nuevo parámetro 'expected'&lt;/span&gt;
    &lt;span class="nc"&gt;IbanValidator&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Modificamos la afirmación de 'assertTrue' a 'assertEquals'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test passed: 4 of 4 ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En esta última versión del test se puede apreciar lo fácil que sería incluir un nuevo caso de uso para la validación, así como nuevos parámetros para comprobar en el test.&lt;/p&gt;

</description>
      <category>java</category>
      <category>testing</category>
      <category>spring</category>
      <category>spanish</category>
    </item>
    <item>
      <title>JUnit: Cómo ejecutar un test N iteraciones</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Thu, 10 Nov 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/como-repetir-un-test-n-iteraciones-36pd</link>
      <guid>https://dev.to/gekyzo/como-repetir-un-test-n-iteraciones-36pd</guid>
      <description>&lt;p&gt;En ciertas ocasiones puede que &lt;strong&gt;necesitemos ejecutar un test N veces&lt;/strong&gt; para poder asegurar su correcto funcionamiento.&lt;/p&gt;

&lt;p&gt;Para ello, contamos con varias fórmulas. En primer lugar, vamos a considerar el siguiente escenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queremos testear un método que nos genera un número aleatorio de N dígitos. El valora de N se pasa como parámetro a dicho método.&lt;/li&gt;
&lt;li&gt;Creamos una clase de test de jUnit en la que declaramos el número de repeticiones o iteraciones que queremos ejecutar un determinado test.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;NUMBER_REPETITIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Creamos los tests para validar la funcionalidad del método. En este ejemplo, he creado un test mediante la anotación de jUnit &lt;code&gt;@RepeatedTest&lt;/code&gt; y otro test simple en el que realizamos toda la lógica dentro de un bucle do-while.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Test A&lt;/strong&gt;: utilizando la anotación &lt;code&gt;@RepeatedTest&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.RepeatedTest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@RepeatedTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;NUMBER_REPETITIONS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;random_number_with_four_digits&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;numOfDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RandomUtil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numOfDigits&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, random is too high"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, actual is too low"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test B&lt;/strong&gt;: utilizando el bucle do-while.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;random_numbers_generator&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;iterationCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;numOfDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RandomUtil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numOfDigits&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, random is too high"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error, actual is too low"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;iterationCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterationCount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;NUMBER_REPETITIONS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver &lt;strong&gt;ambos tests afirman lo mismo&lt;/strong&gt;, que el método generador de números aleatorios va a devolver un valor que se encuentra entre low y high.&lt;br&gt;
En ambos casos el test se va a ejecutar tantas veces como indiquemos en la constante &lt;code&gt;NUMBER_REPETITIONS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Una vez contamos con este escenario, &lt;strong&gt;podemos realizar distintas pruebas&lt;/strong&gt; alterando el valor de &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt;, &lt;code&gt;numOfDigits&lt;/code&gt; y &lt;code&gt;NUMBER_REPETITIONS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;En esta ocasión quería calcular la &lt;strong&gt;diferencia de los tiempos de ejecución&lt;/strong&gt; de cada tipos de test, y estas son las pruebas que he realizado:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nº Iteraciones&lt;/th&gt;
&lt;th&gt;Test A (@RepeatedTest)&lt;/th&gt;
&lt;th&gt;Test B (do-while)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1_000&lt;/td&gt;
&lt;td&gt;130 ms&lt;/td&gt;
&lt;td&gt;13 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100_000&lt;/td&gt;
&lt;td&gt;2600 ms&lt;/td&gt;
&lt;td&gt;20 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1_000_000&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Indeterminado&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;55 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo, los tests ejecutados &lt;strong&gt;mediante el bucle do-while han sido aproximadamente un 90% más rápidos&lt;/strong&gt; que los ejecutados mediante la anotación &lt;code&gt;@RepeatedTest&lt;/code&gt;, además de que para el caso de 1_000_000 iteraciones, no he podido obtener un resultado final ya que la aplicación se quedaba colgada.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>spanish</category>
      <category>testing</category>
    </item>
    <item>
      <title>Conversores personalizados para @RequestParam</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Mon, 07 Nov 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/conversores-personalizados-para-requestparam-2d52</link>
      <guid>https://dev.to/gekyzo/conversores-personalizados-para-requestparam-2d52</guid>
      <description>&lt;p&gt;En la &lt;a href="https://dev.to/gekyzo/conversores-personalizados-para-requestbody-37hp"&gt;publicación anterior&lt;/a&gt; vimos cómo crear conversores personalizados para propiedades dentro de una clase anotada con &lt;code&gt;@RequestBody&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;En esta ocasión veremos cómo hacer la misma lógica para parámetros anotados como &lt;code&gt;@RequestParam&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Refactorizando el ejemplo de la publicación anterior, supongamos que tenemos el siguiente controlador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transactions"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateTransactionController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CreateTransactionOutputDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nd"&gt;@RequestParam&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y enviamos una petición a este endpoint con los siguientes parámetros:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST '{{apiUrl}}/transactions?amount=45.13'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por defecto &lt;strong&gt;Spring será capaz de enlazar cada elemento de la petición con su correspondiente parámetro&lt;/strong&gt; de nuestro controlador, siempre y cuando encuentre el conversor adecuado para ello.&lt;/p&gt;

&lt;p&gt;No tendremos problemas si declaramos parámetros de tipo primitivo o sus wrappers, pero en caso de querer enlazarlos a una clase, &lt;strong&gt;debemos crear un conversor&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo mapear Value Objects
&lt;/h2&gt;

&lt;p&gt;Supongamos ahora que actualizamos el tipo de clase del parámetro de la siguiente manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file: Money&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{...}&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Creamos un record para encapsular un elemento de tipo Money&lt;/span&gt;

&lt;span class="c1"&gt;// file: CreateTransactionController&lt;/span&gt;
&lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CreateTransactionOutputDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nd"&gt;@RequestParam&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- Actualizamos el tipo parámetro&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para que Spring sea capaz de convertir estos datos correctamente, &lt;strong&gt;creamos el conversor&lt;/strong&gt; extendiendo de &lt;code&gt;org.springframework.core.convert.converter.Converter&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.core.convert.converter.Converter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MoneyConverter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Converter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- Implementamos la interfaz Converter&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseDouble&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- Implementamos la conversión con la lógica que deseemos&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez más, se trata de un código muy simple. Únicamente es necesario implementar la infertaz &lt;code&gt;Converter&lt;/code&gt; indicando como tipo de parámetros la clase de entrada y la de salida, en este caso indicamos que se va a convertir una &lt;code&gt;String&lt;/code&gt; en la clase &lt;code&gt;Money&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por último, debemos &lt;strong&gt;indicar a Spring que se utilice este conversor&lt;/strong&gt; para mapear las instancias de la clase &lt;code&gt;Money&lt;/code&gt;, incluyendo el nuevo conversor dentro del registro de formateadores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.servlet.config.annotation.WebMvcConfigurer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WebConfig&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;WebMvcConfigurer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addFormatters&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FormatterRegistry&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addConverter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MoneyConverter&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;    &lt;span class="c1"&gt;// &amp;lt;- Instanciamos e incluimos nuestro conversor&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez hecho esto, Spring será capaz de utilizar nuestro conversor cuando intente mapear propiedades de tipos distintos a los primitivos/wrappers o las clases para las que ya cuenta con conversores.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Conversores personalizados para @RequestBody</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Thu, 03 Nov 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/conversores-personalizados-para-requestbody-37hp</link>
      <guid>https://dev.to/gekyzo/conversores-personalizados-para-requestbody-37hp</guid>
      <description>&lt;p&gt;Normalmente, &lt;strong&gt;cuando declaramos un parámetro de un controlador&lt;/strong&gt; con la anotación &lt;code&gt;@RequestBody&lt;/code&gt;, solemos indicar la clase que contiene todos los posibles atributos del cuerpo de la petición.&lt;/p&gt;

&lt;p&gt;En la mayoría de casos, Spring es capaz de &lt;em&gt;bindear&lt;/em&gt; o enlazar el valor de cada elemento de la petición con su correspondiente atributo en nuestra clase, pero en ciertas ocasiones &lt;strong&gt;no podrá hacerlo de forma automática&lt;/strong&gt; o puede que nosotros mismos &lt;strong&gt;queramos alterar este comportamiento&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Para hacer esto, existen los &lt;strong&gt;Converter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Supongamos el siguiente ejemplo, tenemos un controlador que cuenta con un método de tipo POST que espera una serie de elementos en el cuerpo de la petición.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transactions"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateTransactionController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CreateTransactionOutputDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;CreateTransactionRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y enviamos una petición a este endpoint con el siguiente cuerpo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AB-1234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"iban"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES 1234 5678 901234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;45.67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por defecto Spring será capaz de enlazar cada elemento con su correspondiente atributo de nuestra clase, siempre y cuando ésta tenga la siguiente forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;CreateTransactionRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  
    &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cómo mapear Value Objects
&lt;/h2&gt;

&lt;p&gt;El problema aparece cuando queremos aplicar ciertos principios de DDD como los &lt;strong&gt;Value Objects&lt;/strong&gt;, y representar así mejor cada tipo de dato encapsulándolo en clases como estas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Reference&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{...}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Iban&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{...}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{...}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{...}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;CreateTransactionRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Reference&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Iban&lt;/span&gt; &lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  
    &lt;span class="nc"&gt;Amount&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Description&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, Spring no encontrará la forma de mapear cada elemento con la clase correspondiente, por lo que tendremos que &lt;strong&gt;indicarle cómo hacerlo creando clases Converter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;En primer lugar, debemos &lt;strong&gt;crear el conversor&lt;/strong&gt; para cada tipo de value object extendiendo de la clase &lt;code&gt;com.fasterxml.jackson.databind.util.StdConverter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(&lt;em&gt;Debemos crear un conversor por cada tipo de value object&lt;/em&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fasterxml.jackson.databind.util.StdConverter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReferenceConverter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;StdConverter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Reference&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Extendemos StdConverter e implementamos sus métodos&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Reference&lt;/span&gt; &lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Reference&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- Implementamos la conversión con la lógica que deseemos&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JavaType&lt;/span&gt; &lt;span class="nf"&gt;getInputType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TypeFactory&lt;/span&gt; &lt;span class="n"&gt;typeFactory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;typeFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;constructType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos el tipo de clase de entrada&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JavaType&lt;/span&gt; &lt;span class="nf"&gt;getOutputType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TypeFactory&lt;/span&gt; &lt;span class="n"&gt;typeFactory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;typeFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;constructType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;lt;- Indicamos el tipo de clase de salida&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos ver que se trata de un código muy simple. Únicamente es necesario extender de la clase &lt;code&gt;StdConverter&lt;/code&gt; indicando como tipo de parámetros la clase de entrada y la de salida, en este caso indicamos que se va a convertir una &lt;code&gt;String&lt;/code&gt; en la clase &lt;code&gt;Reference&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por último, debemos &lt;strong&gt;indicar a Spring que se utilice este conversor&lt;/strong&gt; para mapear las instancias de la clase &lt;code&gt;Reference&lt;/code&gt;, incluyendo en la propia clase la correspondiente anotación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.fasterxml.jackson.databind.annotation.JsonDeserialize&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@JsonDeserialize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;converter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReferenceConverter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos a Spring que use el converter correspondiente&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Reference&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora Spring será capaz de utilizar nuestro conversor cuando intente mapear propiedades de tipos distintos a los primitivos/wrappers o las clases para las que ya cuenta con conversores.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Utilizar varios archivos de configuración en Spring</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Mon, 31 Oct 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/utilizar-varios-archivos-de-configuracion-en-spring-399n</link>
      <guid>https://dev.to/gekyzo/utilizar-varios-archivos-de-configuracion-en-spring-399n</guid>
      <description>&lt;p&gt;En anteriores publicaciones vimos &lt;a href="https://dev.to/gekyzo/archivos-de-configuracion-en-spring-4k"&gt;cómo agrupar parámetros de configuración&lt;/a&gt; mediante el uso de la anotación &lt;strong&gt;@ConfigurationProperties&lt;/strong&gt; con el elemento &lt;em&gt;prefix&lt;/em&gt;, así como &lt;a href="https://dev.to/gekyzo/como-definir-la-ruta-de-un-archivo-de-configuracion-en-spring-448d"&gt;definir la ruta hasta un archivo de configuración&lt;/a&gt;, pero en ocasiones un único archivo de propiedades puede extenderse demasiado por lo que es más conveniente separarlo en varios ficheros.&lt;/p&gt;

&lt;p&gt;Podemos por ejemplo organizar los archivos de configuración de la siguiente manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;// file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resources/admin_cfg.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John"&lt;/span&gt;

&lt;span class="na"&gt;// file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resources/user_cfg.yml&lt;/span&gt;
&lt;span class="na"&gt;user.firstname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ben"&lt;/span&gt;
&lt;span class="na"&gt;user.lastname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stuart"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora podemos crear sus clases de configuración, e indicar la ruta de los archivos utilizando la anotación &lt;strong&gt;@PropertySource&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;
&lt;span class="nd"&gt;@PropertySource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"classpath:admin_cfg.yml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos la ruta&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;AdminConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos el prefijo (si fuera necesario)&lt;/span&gt;
&lt;span class="nd"&gt;@PropertySource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"classpath:user_cfg.yml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Indicamos la ruta&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;UserConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El acceso a estas propiedades se realiza instanciando la clase de configuración que deseemos, y llamando a la propiedad que nos interese:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getFullName&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"${config.lastname}, ${config.firstname}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fuente: &lt;a href="https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties"&gt;24.8 Type-safe Configuration Properties @ Spring Boot Reference Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spring</category>
      <category>springconfig</category>
      <category>kotlin</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Cómo definir la ruta de un archivo de configuración en Spring</title>
      <dc:creator>Ciro</dc:creator>
      <pubDate>Thu, 27 Oct 2022 07:00:00 +0000</pubDate>
      <link>https://dev.to/gekyzo/como-definir-la-ruta-de-un-archivo-de-configuracion-en-spring-448d</link>
      <guid>https://dev.to/gekyzo/como-definir-la-ruta-de-un-archivo-de-configuracion-en-spring-448d</guid>
      <description>&lt;p&gt;Por defecto, Spring busca en la carpeta de resources los archivos de configuración &lt;code&gt;application.properties&lt;/code&gt; o &lt;code&gt;application.yml&lt;/code&gt;, pero en caso de que queramos indicar la ruta a otros archivos de configuración podemos utilizar la anotación &lt;strong&gt;@PropertySource&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/gekyzo/archivos-de-configuracion-en-spring-4k"&gt;publicación anterior&lt;/a&gt; creamos clases que contenían propiedades de configuración, pero estas propiedades estaban declaradas en el archivo por defecto &lt;code&gt;application.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Si queremos definir la ruta hasta un archivo de configuración &lt;code&gt;.yml&lt;/code&gt; como el de este ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;// file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example_cfg.yml&lt;/span&gt;
&lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;value"&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1234&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debemos incluir la anotación &lt;strong&gt;@PropertySource&lt;/strong&gt; de la siguiente manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"example"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@PropertySource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"classpath:example_cfg.yml) // &amp;lt;- Indicamos la ruta hasta el archivo
&lt;/span&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;ExampleConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De esta manera Spring nos permite acceder a propiedades declaradas en ficheros .yml&lt;/p&gt;

&lt;p&gt;Fuente: &lt;a href="https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-yaml-shortcomings"&gt;24.7.4 YAML Shortcomings @ Spring Boot Reference Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spring</category>
      <category>springconfi</category>
      <category>kotlin</category>
      <category>spanish</category>
    </item>
  </channel>
</rss>
