<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://inazense.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://inazense.github.io/" rel="alternate" type="text/html" hreflang="es" /><updated>2026-05-07T18:09:54+02:00</updated><id>https://inazense.github.io/feed.xml</id><title type="html">Programando a Pasitos</title><subtitle>Blog de programación por Inazio Claver</subtitle><author><name>Inazio Claver</name></author><entry><title type="html">PostRest + Spring boot. API Rest sin escribir controladores</title><link href="https://inazense.github.io/posts/2026/05/07/postgrest-en-spring-boot/" rel="alternate" type="text/html" title="PostRest + Spring boot. API Rest sin escribir controladores" /><published>2026-05-07T16:17:00+02:00</published><updated>2026-05-07T16:17:00+02:00</updated><id>https://inazense.github.io/posts/2026/05/07/postgrest-en-spring-boot</id><content type="html" xml:base="https://inazense.github.io/posts/2026/05/07/postgrest-en-spring-boot/"><![CDATA[<h1 id="postrest--spring-boot-api-rest-sin-escribir-controladores">PostRest + Spring boot. API Rest sin escribir controladores</h1>

<p><img src="/img/posts/20260507_1.png" alt="PostRest + Spring boot" /></p>

<p>Hay muchas formas de montar una API en Spring Boot. La más habitual es crear controladores, servicios, repositorios, entidades y toda la capa intermedia que ya conocemos. Funciona bien, pero no siempre hace falta construir tanto cuando lo único que queremos es exponer datos de PostgreSQL de forma rápida, consistente y sin demasiada ceremonia.</p>

<p>Ahí es donde entra <strong>PostgREST</strong>. Si ya trabajas con PostgreSQL y no quieres escribir media aplicación solo para servir CRUD, PostgREST puede ahorrarte bastante tiempo. Y si lo combinas con Spring Boot de forma sensata, puedes separar muy bien responsabilidades: PostgreSQL expone los datos, PostgREST los convierte en una API REST y Spring Boot se encarga de la lógica que realmente aporta valor.</p>

<h2 id="qué-es-postgrest">Qué es PostgREST</h2>

<p>PostgREST es una herramienta que genera una API REST a partir de un esquema de PostgreSQL. No inventa un modelo intermedio ni obliga a definir controladores por cada recurso. Lee tablas, vistas, funciones y permisos, y con eso construye endpoints automáticamente.</p>

<p>En la práctica, eso significa que una tabla puede convertirse en un recurso, una vista puede actuar como una consulta ya preparada y una función puede usarse para operaciones más específicas. Todo ello respetando los permisos de base de datos, que es una de las partes más interesantes del enfoque.</p>

<p>La idea no es nueva, pero sí muy útil cuando tienes un dominio bastante claro y quieres evitar repetir lógica trivial en la capa Java.</p>

<h2 id="cuándo-tiene-sentido-usarlo">Cuándo tiene sentido usarlo</h2>

<p>No lo usaría para todo. Si tu aplicación necesita reglas de negocio complejas, agregados, workflows o integración pesada con otros sistemas, Spring Boot seguirá siendo el corazón de la solución.</p>

<p>Pero PostgREST encaja muy bien en estos casos:</p>

<ul>
  <li>CRUDs bastante directos.</li>
  <li>Backends internos.</li>
  <li>Prototipos serios que luego quieres mantener.</li>
  <li>APIs donde PostgreSQL ya concentra buena parte de la lógica.</li>
  <li>Sistemas donde prefieres empujar permisos y acceso a datos al propio motor.</li>
</ul>

<p>En otras palabras: cuando la API está muy pegada a datos y poco a comportamiento, PostgREST tiene mucho sentido.</p>

<h2 id="cómo-encaja-con-spring-boot">Cómo encaja con Spring Boot</h2>

<p>Aquí viene la parte importante. Spring Boot no sustituye a PostgREST ni PostgREST sustituye a Spring Boot. Lo útil es combinarlos con cabeza.</p>

<p>La arquitectura típica sería esta:</p>

<ul>
  <li>PostgreSQL como base de datos principal.</li>
  <li>PostgREST como capa REST automática sobre el esquema.</li>
  <li>Spring Boot como aplicación que consume esa API, añade lógica de negocio, autenticación, orquestación o integración con otros servicios.</li>
</ul>

<p>Eso te permite separar bastante bien responsabilidades. Spring Boot deja de actuar como simple intermediario de datos y pasa a hacer lo que mejor sabe hacer: coordinar procesos, validar reglas, integrar servicios y ofrecer endpoints propios cuando hace falta.</p>

<h2 id="preparar-postgresql">Preparar PostgreSQL</h2>

<p>Antes de montar nada, conviene tener claro qué tablas, vistas o funciones vas a exponer. No todo debería salir por la API por defecto.</p>

<p>Un ejemplo simple podría ser una tabla de pedidos:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">create</span> <span class="k">table</span> <span class="n">pedidos</span> <span class="p">(</span>
    <span class="n">id</span> <span class="n">bigserial</span> <span class="k">primary</span> <span class="k">key</span><span class="p">,</span>
    <span class="n">cliente</span> <span class="nb">varchar</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span> <span class="k">not</span> <span class="k">null</span><span class="p">,</span>
    <span class="n">total</span> <span class="nb">numeric</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="k">not</span> <span class="k">null</span><span class="p">,</span>
    <span class="n">creado_en</span> <span class="nb">timestamp</span> <span class="k">not</span> <span class="k">null</span> <span class="k">default</span> <span class="n">now</span><span class="p">()</span>
<span class="p">);</span>
</code></pre></div></div>

<p>Si PostgREST va a exponer esto, también debes pensar en permisos y roles. La gracia de PostgREST es que no se basa solo en “abrir” una tabla, sino en exponer lo que PostgreSQL permita realmente consultar o modificar.</p>

<h2 id="configurar-postgrest">Configurar PostgREST</h2>

<p>PostgREST suele configurarse con un fichero bastante simple. Ahí defines conexión, esquema expuesto, rol anónimo y algunas opciones más.</p>

<p>Un ejemplo mínimo:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">db-uri</span> <span class="p">=</span> <span class="s">"postgres://app_user:secret@localhost:5432/tienda"</span>
<span class="py">db-schema</span> <span class="p">=</span> <span class="s">"public"</span>
<span class="py">db-anon-role</span> <span class="p">=</span> <span class="s">"anon"</span>
<span class="py">server-port</span> <span class="p">=</span> <span class="s">3000</span>
</code></pre></div></div>

<p>Con eso ya puedes arrancarlo y empezar a probar endpoints sobre el esquema configurado. Si hay permisos bien definidos, la API responderá solo con lo que ese rol pueda ver o modificar.</p>

<h2 id="exponer-vistas-y-funciones">Exponer vistas y funciones</h2>

<p>Aquí es donde PostgREST gana bastante. Si una consulta es compleja o quieres devolver un resultado ya preparado, no hace falta meter esa lógica en Spring Boot.</p>

<p>Puedes crear una vista:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">create</span> <span class="k">view</span> <span class="n">pedidos_resumen</span> <span class="k">as</span>
<span class="k">select</span>
    <span class="n">id</span><span class="p">,</span>
    <span class="n">cliente</span><span class="p">,</span>
    <span class="n">total</span><span class="p">,</span>
    <span class="n">creado_en</span>
<span class="k">from</span> <span class="n">pedidos</span><span class="p">;</span>
</code></pre></div></div>

<p>O una función:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">create</span> <span class="k">function</span> <span class="n">crear_pedido</span><span class="p">(</span><span class="n">p_cliente</span> <span class="nb">varchar</span><span class="p">,</span> <span class="n">p_total</span> <span class="nb">numeric</span><span class="p">)</span>
<span class="k">returns</span> <span class="n">pedidos</span>
<span class="k">language</span> <span class="k">sql</span>
<span class="k">as</span> <span class="err">$$</span>
    <span class="k">insert</span> <span class="k">into</span> <span class="n">pedidos</span><span class="p">(</span><span class="n">cliente</span><span class="p">,</span> <span class="n">total</span><span class="p">)</span>
    <span class="k">values</span> <span class="p">(</span><span class="n">p_cliente</span><span class="p">,</span> <span class="n">p_total</span><span class="p">)</span>
    <span class="n">returning</span> <span class="o">*</span><span class="p">;</span>
<span class="err">$$</span><span class="p">;</span>
</code></pre></div></div>

<p>Eso te da bastante flexibilidad sin ensuciar la capa Java con consultas que en realidad pertenecen a la base de datos.</p>

<h2 id="consumir-postgrest-desde-spring-boot">Consumir PostgREST desde Spring Boot</h2>

<p>Spring Boot puede consumir PostgREST como cualquier otra API REST. La diferencia es que aquí la API no la has escrito tú a mano, sino que la ha generado PostgreSQL a través de PostgREST.</p>

<p>Con <code class="language-plaintext highlighter-rouge">WebClient</code>, por ejemplo, puedes hacerlo así:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Service</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">PedidosClient</span> <span class="o">{</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">WebClient</span> <span class="n">webClient</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">PedidosClient</span><span class="o">(</span><span class="nc">WebClient</span><span class="o">.</span><span class="na">Builder</span> <span class="n">builder</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">webClient</span> <span class="o">=</span> <span class="n">builder</span>
                <span class="o">.</span><span class="na">baseUrl</span><span class="o">(</span><span class="s">"http://localhost:3000"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">build</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Mono</span><span class="o">&lt;</span><span class="nc">PedidoDto</span><span class="o">[]&gt;</span> <span class="nf">obtenerPedidos</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">webClient</span><span class="o">.</span><span class="na">get</span><span class="o">()</span>
                <span class="o">.</span><span class="na">uri</span><span class="o">(</span><span class="s">"/pedidos"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">retrieve</span><span class="o">()</span>
                <span class="o">.</span><span class="na">bodyToMono</span><span class="o">(</span><span class="nc">PedidoDto</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Y si prefieres bloquearte en un flujo tradicional, también puedes usar <code class="language-plaintext highlighter-rouge">RestTemplate</code>, aunque hoy en día <code class="language-plaintext highlighter-rouge">WebClient</code> suele encajar mejor si quieres una integración más moderna.</p>

<p>La clave está en no pensar en PostgREST como un atajo raro, sino como una API externa más, igual que tratarías con Stripe, GitHub o cualquier otro servicio [web:76].</p>

<h2 id="autenticación-y-permisos">Autenticación y permisos</h2>

<p>Aquí es donde muchas implementaciones se hacen bien o mal. PostgREST no debería exponer datos solo porque “están en la base de datos”. Lo correcto es controlar permisos en PostgreSQL y, si hace falta, usar JWT para identificar el rol o el contexto del usuario.</p>

<p>Eso permite algo muy potente: que la base de datos decida qué puede hacer cada perfil. Spring Boot puede encargarse de emitir o validar el token, pero la autorización fina la puede seguir imponiendo PostgreSQL.</p>

<p>Esta separación suele quedar bastante limpia en sistemas medianos. Spring Boot autentica, PostgREST sirve la API y PostgreSQL aplica el filtro real.</p>

<h2 id="ventajas-reales">Ventajas reales</h2>

<p>Las ventajas más claras de este enfoque son bastante prácticas:</p>

<ul>
  <li>Menos código repetido.</li>
  <li>Menos capas innecesarias para CRUDs.</li>
  <li>Aprovechar la potencia de PostgreSQL.</li>
  <li>Mejor separación entre acceso a datos y lógica de negocio.</li>
  <li>Control de permisos muy cercano al dato.</li>
</ul>

<p>Además, si vienes de proyectos donde todo termina en un montón de repositorios casi idénticos, este enfoque se agradece bastante. Hay menos ruido y más intención.</p>

<h2 id="lo-que-debes-vigilar">Lo que debes vigilar</h2>

<p>No todo son ventajas. Si abusas de PostgREST, puedes acabar moviendo demasiada responsabilidad a la base de datos y perdiendo claridad. Tampoco conviene esconder lógica de negocio importante dentro de funciones SQL sin criterio.</p>

<p>Yo lo vería así: PostgreSQL debe resolver bien el acceso, las consultas, las validaciones cercanas al dato y las operaciones simples. Spring Boot debe quedarse con la coordinación, la integración, la seguridad de alto nivel y las reglas que de verdad pertenecen a la aplicación.</p>

<p>Cuando separas eso bien, la solución se vuelve más limpia. Cuando lo mezclas todo, aparece el clásico backend que nadie quiere tocar.</p>

<h2 id="ejemplo-de-uso-razonable">Ejemplo de uso razonable</h2>

<p>Un escenario bastante sensato sería este:</p>

<ul>
  <li>PostgreSQL guarda pedidos, clientes y productos.</li>
  <li>PostgREST expone tablas y vistas.</li>
  <li>Spring Boot usa esa API para construir casos de uso más grandes, mandar correos, aplicar reglas de negocio y conectar con otros sistemas.</li>
</ul>

<p>Así no obligas a Spring Boot a hacer de simple proxy de base de datos. Y tampoco conviertes PostgreSQL en una especie de aplicación oculta sin control.</p>

<h2 id="conclusión">Conclusión</h2>

<p>PostgREST no viene a reemplazar Spring Boot. Viene a quitar trabajo mecánico cuando la API está muy ligada a PostgreSQL y no merece la pena escribir toda la capa REST a mano.</p>

<p>Si lo usas con criterio, puede darte una arquitectura bastante elegante: datos bien modelados, permisos cerca del motor y Spring Boot reservado para la lógica que realmente aporta valor. Y eso, al final, es una de las cosas que más agradeces en proyectos que tienen que durar.</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="spring-boot" /><category term="postgrest" /><category term="postgresql" /><category term="api-rest" /><category term="webclient" /><category term="jwt" /><category term="backend" /><category term="sql" /><category term="java" /><summary type="html"><![CDATA[Aprende qué es PostgREST y cómo integrarlo con Spring Boot para exponer PostgreSQL como API REST, consumir endpoints con WebClient y mantener una arquitectura más simple.]]></summary></entry><entry><title type="html">Principios SOLID. Cinco ideas para no pelearte con tu propio código</title><link href="https://inazense.github.io/posts/2026/05/04/principios-solid-explicados-para-java/" rel="alternate" type="text/html" title="Principios SOLID. Cinco ideas para no pelearte con tu propio código" /><published>2026-05-04T17:49:00+02:00</published><updated>2026-05-04T17:49:00+02:00</updated><id>https://inazense.github.io/posts/2026/05/04/principios-solid-explicados-para-java</id><content type="html" xml:base="https://inazense.github.io/posts/2026/05/04/principios-solid-explicados-para-java/"><![CDATA[<h1 id="principios-solid-cinco-ideas-para-no-pelearte-con-tu-propio-código">Principios SOLID: Cinco ideas para no pelearte con tu propio código</h1>

<p><img src="/img/posts/20260504_1.png" alt="Cabecera sobre principios SOLID" /></p>

<p>Hay temas que cuando empiezas a programar te suenan a teoría pura. A algo que está bien saber, pero que tampoco parece urgente. Con SOLID me pasó un poco eso.</p>

<p>Al principio bastante tenemos con sacar el ejercicio, hacer que compile y conseguir que no explote nada por sitios raros. Pero en cuanto empiezas a tocar proyectos algo más grandes, o simplemente vuelves a tu código de hace unos meses, te das cuenta de que no todo consiste en que funcione. También importa que se entienda, que se pueda cambiar sin miedo y que no te obligue a romper tres cosas cada vez que quieres añadir una cuarta.</p>

<p>Ahí es donde entran los principios SOLID.</p>

<p>No son magia, ni una receta universal, ni mucho menos algo que haya que meter con calzador en cualquier clase de veinte líneas. Pero sí vienen muy bien como guía para diseñar mejor las clases y evitar algunos errores bastante típicos cuando trabajamos con orientación a objetos.</p>

<h2 id="entonces-qué-es-solid">Entonces, ¿qué es SOLID?</h2>

<p>SOLID es el nombre que se le da a cinco principios de diseño orientado a objetos pensados para que el código sea más fácil de mantener, más flexible y menos acoplado. El blog ha publicado durante años contenido práctico sobre clases, objetos, paquetes y patrones en Java y Python, así que este tema encaja muy bien con esa línea de explicaciones paso a paso.</p>

<p>Las siglas corresponden a esto:</p>

<ul>
  <li><strong>S</strong>: Single Responsibility Principle.</li>
  <li><strong>O</strong>: Open/Closed Principle.</li>
  <li><strong>L</strong>: Liskov Substitution Principle.</li>
  <li><strong>I</strong>: Interface Segregation Principle.</li>
  <li><strong>D</strong>: Dependency Inversion Principle.</li>
</ul>

<p>Visto así parece el típico listado que uno memoriza para un examen y luego olvida. Pero si lo bajas a ejemplos del día a día, tiene bastante más sentido del que parece.</p>

<h2 id="s-una-clase-una-responsabilidad">S: una clase, una responsabilidad</h2>

<p>Este es seguramente el más fácil de entender. La idea es que una clase debería tener un único motivo para cambiar. O dicho de forma menos solemne: mejor que cada clase se dedique a una cosa y no a siete a la vez.</p>

<p>Por ejemplo, imaginemos una clase <code class="language-plaintext highlighter-rouge">Usuario</code> que valida datos, guarda información en base de datos, genera informes y además manda correos. ¿Se puede hacer? Sí. ¿Es buena idea? Más bien no.</p>

<p>Cuando mezclamos responsabilidades, el código se vuelve más difícil de mantener. Un cambio en la validación puede afectar al guardado, una modificación en base de datos puede romper otra parte y al final todo queda demasiado atado.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Usuario</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="nc">String</span> <span class="n">nombre</span><span class="o">;</span>
    <span class="kd">private</span> <span class="nc">String</span> <span class="n">email</span><span class="o">;</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">ValidadorUsuario</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">validar</span><span class="o">(</span><span class="nc">Usuario</span> <span class="n">usuario</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">usuario</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">usuario</span><span class="o">.</span><span class="na">getEmail</span><span class="o">()</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">UsuarioRepository</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">guardar</span><span class="o">(</span><span class="nc">Usuario</span> <span class="n">usuario</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// guardar usuario</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">EmailService</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">enviarBienvenida</span><span class="o">(</span><span class="nc">Usuario</span> <span class="n">usuario</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// enviar correo</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Aquí no hay nada especialmente sofisticado, pero sí una idea clara: separar tareas suele hacer la vida bastante más fácil.</p>

<h2 id="o-abierto-a-crecer-cerrado-a-tocar-lo-que-ya-funciona">O: abierto a crecer, cerrado a tocar lo que ya funciona</h2>

<p>El principio abierto/cerrado dice que una clase debería estar abierta a extensión, pero cerrada a modificación. Es decir, deberíamos poder añadir comportamiento nuevo sin andar reescribiendo una clase estable cada dos por tres.</p>

<p>Esto se nota mucho cuando empiezan a aparecer condicionales por todos lados. El típico caso: una clase que procesa pagos, y según si el pago es con tarjeta, PayPal, transferencia o lo que toque, metemos otro <code class="language-plaintext highlighter-rouge">if</code> más. Hoy son dos casos, mañana cinco, pasado mañana nueve.</p>

<p>Una alternativa bastante mejor es apoyarse en abstracciones.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">interface</span> <span class="nc">MetodoPago</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">pagar</span><span class="o">(</span><span class="kt">double</span> <span class="n">importe</span><span class="o">);</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">PagoTarjeta</span> <span class="kd">implements</span> <span class="nc">MetodoPago</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">pagar</span><span class="o">(</span><span class="kt">double</span> <span class="n">importe</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// lógica de tarjeta</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">PagoPaypal</span> <span class="kd">implements</span> <span class="nc">MetodoPago</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">pagar</span><span class="o">(</span><span class="kt">double</span> <span class="n">importe</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// lógica de paypal</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>De esta forma, si mañana aparece otro método de pago, se añade una nueva implementación y listo. Menos riesgo de cargarse lo que ya estaba funcionando.</p>

<h2 id="l-si-hereda-que-se-comporte-como-se-espera">L: si hereda, que se comporte como se espera</h2>

<p>El principio de sustitución de Liskov es de esos que suenan más aparatosos de lo que realmente son. Viene a decir que si una clase hereda de otra, deberíamos poder usar la hija en lugar de la padre sin que el programa empiece a hacer cosas raras.</p>

<p>Parece de sentido común, pero no siempre se respeta. A veces se hereda solo por reutilizar código, aunque la relación no tenga demasiado sentido. Y ahí empiezan los problemas.</p>

<p>El ejemplo clásico suele ser el de una clase <code class="language-plaintext highlighter-rouge">Ave</code> con un método <code class="language-plaintext highlighter-rouge">volar()</code>, y luego aparece <code class="language-plaintext highlighter-rouge">Pinguino</code> heredando de <code class="language-plaintext highlighter-rouge">Ave</code>. Claro, el pingüino ave es, pero volar, lo que se dice volar, no vuela demasiado.</p>

<p>Cuando pasa algo así, normalmente no falla solo el diseño: también nos está avisando de que quizá la jerarquía no está bien planteada.</p>

<h2 id="i-interfaces-pequeñas-mejor-que-monstruos-de-veinte-métodos">I: interfaces pequeñas, mejor que monstruos de veinte métodos</h2>

<p>Este principio dice que una clase no debería verse obligada a implementar métodos que no necesita. O, dicho de otra forma, mejor varias interfaces pequeñas y concretas que una gigantesca para todo.</p>

<p>Es algo bastante habitual cuando uno intenta “dejarlo todo preparado” y acaba creando una interfaz enorme con métodos para imprimir, exportar, validar, serializar, conectar, enviar y cocinar croquetas. Luego llega una clase que solo necesita dos de esos métodos y toca implementar el resto porque sí.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">interface</span> <span class="nc">Imprimible</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">imprimir</span><span class="o">();</span>
<span class="o">}</span>

<span class="kd">interface</span> <span class="nc">Exportable</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">exportar</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>No tiene mucho misterio: si algo solo necesita imprimir, que implemente <code class="language-plaintext highlighter-rouge">Imprimible</code>. Si además exporta, que implemente también <code class="language-plaintext highlighter-rouge">Exportable</code>. Y si no, mejor no inventarse obligaciones.</p>

<h2 id="d-depender-de-abstracciones-da-bastante-aire">D: depender de abstracciones da bastante aire</h2>

<p>La D corresponde a inversión de dependencias. Aquí la idea es que el código importante de la aplicación no dependa directamente de implementaciones concretas, sino de abstracciones.</p>

<p>Dicho así parece una frase de libro, pero en realidad se ve rápido con un ejemplo. Si una clase depende directamente de <code class="language-plaintext highlighter-rouge">EmailService</code>, queda atada a esa forma de notificar. Si mañana queremos mandar avisos por SMS o por Telegram, ya toca modificar esa clase.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">interface</span> <span class="nc">Notificador</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">enviar</span><span class="o">(</span><span class="nc">String</span> <span class="n">mensaje</span><span class="o">);</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">EmailNotificador</span> <span class="kd">implements</span> <span class="nc">Notificador</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">enviar</span><span class="o">(</span><span class="nc">String</span> <span class="n">mensaje</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// enviar email</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">ServicioPedidos</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Notificador</span> <span class="n">notificador</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">ServicioPedidos</span><span class="o">(</span><span class="nc">Notificador</span> <span class="n">notificador</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">notificador</span> <span class="o">=</span> <span class="n">notificador</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">confirmar</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">notificador</span><span class="o">.</span><span class="na">enviar</span><span class="o">(</span><span class="s">"Pedido confirmado"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>La diferencia está en que <code class="language-plaintext highlighter-rouge">ServicioPedidos</code> no necesita saber cómo se envía el mensaje. Solo necesita que exista alguien capaz de enviarlo.</p>

<h2 id="lo-importante-de-verdad">Lo importante de verdad</h2>

<p>Con SOLID pasa como con muchas buenas prácticas: entendido con sentido común, ayuda. Aplicado de forma rígida a cualquier cosa, puede acabar complicando más de la cuenta.</p>

<p>No hace falta convertir una utilidad pequeña en una arquitectura espacial. Pero tampoco está de más acostumbrarse a detectar ciertas señales: clases que hacen demasiadas cosas, dependencias demasiado fuertes, interfaces infladas o herencias que chirrían.</p>

<p>Al final, lo bueno de estos principios no es que tengan nombre en inglés ni que queden elegantes en una entrevista. Lo útil es que te obligan a parar un momento y pensar si el código que estás escribiendo hoy te lo vas a agradecer mañana o te vas a acordar de toda tu ascendencia cuando tengas que tocarlo dentro de seis meses.</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="java" /><category term="solid" /><category term="programacion-orientada-a-objetos" /><category term="oop" /><category term="patrones" /><category term="buenas-practicas" /><category term="clean-code" /><summary type="html"><![CDATA[Aprende qué son los principios SOLID y cómo aplicarlos en Java con ejemplos sencillos sobre responsabilidad única, abierto/cerrado, sustitución de Liskov, segregación de interfaces e inversión de dependencias.]]></summary></entry><entry><title type="html">Java. Ordenar un HashMap por key o value</title><link href="https://inazense.github.io/posts/2020/12/03/java-ordenar-un-hashmap-por-key-o-value/" rel="alternate" type="text/html" title="Java. Ordenar un HashMap por key o value" /><published>2020-12-03T04:33:00+01:00</published><updated>2020-12-03T04:33:00+01:00</updated><id>https://inazense.github.io/posts/2020/12/03/java-ordenar-un-hashmap-por-key-o-value</id><content type="html" xml:base="https://inazense.github.io/posts/2020/12/03/java-ordenar-un-hashmap-por-key-o-value/"><![CDATA[<p>Hace DEMASIADO tiempo que no actualizo este blog, vamos a quitarle las telarañas con una entrada corta, didáctica y que puede ser útil en más de una ocasión.
En esta ocasión vamos a ver cómo llevar a cabo una de las cosas más tontas del mundo, ordenar algo. Pero que puede ser un poco enrevesado según lo que te toque hacer.</p>

<h2 id="qué-es-un-map-o-hashmap-en-java">¿Qué es un Map o HashMap en Java?</h2>

<p>Antes vamos con una breve introducción. Básicamente, un <strong>Map</strong> o <strong>mapa en Java</strong> es una interfaz que nos va a permitir representar una <strong>estructura de datos</strong> que <strong>almacene información</strong> usando un <strong>par de “clave - valor”</strong>.</p>

<p>Es decir, que es la forma en la que vamos a poder tener la información guardada tal que así:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"Nombre"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Inazio"</span><span class="p">,</span><span class="w"> </span><span class="nl">"Profesión"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Bordador de calcetines personalizados"</span><span class="p">,</span><span class="w"> </span><span class="err">...</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>¿Y <strong>HashMap</strong> entonces que es? <strong>HashMap</strong> es la <strong>implementación de la interfaz Map</strong>, ni más ni menos.</p>

<h2 id="cómo-ordenar-un-hashmap-en-java">Cómo ordenar un HashMap en Java</h2>

<p>Para ordenar un <strong>HashMap</strong> en Java vamos a utilizar el siguiente código, que iré explicando paso a paso.</p>

<p>Lo primero, va a ser crear un <strong>Map</strong> que ordenar, que si no es como plantar judías para recoger melones, un sinsentido</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">map</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;();</span>
		
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="mi">15</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">12</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="mi">30</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">3</span><span class="o">,</span> <span class="mi">5</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">4</span><span class="o">,</span> <span class="mi">22</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="mi">27</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">6</span><span class="o">,</span> <span class="mi">4</span><span class="o">);</span>
<span class="n">map</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">7</span><span class="o">,</span> <span class="mi">87</span><span class="o">);</span>
</code></pre></div></div>

<p>Una vez que tengamos eso hecho, vamos a generar un método que nos devolverá el <strong>mapa ordenado</strong>, tal que así</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="nf">sortMapByValue</span><span class="o">(</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">map</span><span class="o">)</span>
<span class="o">{</span>
    <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">sortedMap</span> <span class="o">=</span>  <span class="n">map</span><span class="o">.</span><span class="na">entrySet</span><span class="o">().</span><span class="na">stream</span><span class="o">()</span>
            <span class="o">.</span><span class="na">sorted</span><span class="o">(</span><span class="n">comparingInt</span><span class="o">(</span><span class="n">e</span> <span class="o">-&gt;</span> <span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">e</span><span class="o">.</span><span class="na">getValue</span><span class="o">()</span> <span class="o">))</span>
            <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="n">toMap</span><span class="o">(</span>
                    <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">::</span><span class="n">getKey</span><span class="o">,</span>
                    <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">::</span><span class="n">getValue</span><span class="o">,</span>
                    <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">AssertionError</span><span class="o">();},</span>
                    <span class="nl">LinkedHashMap:</span><span class="o">:</span><span class="k">new</span>
            <span class="o">));</span>
    <span class="k">return</span> <span class="n">sortedMap</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Veamos en más detalle este código. Nuestra primera parada es esta</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">map</span><span class="o">.</span><span class="na">entrySet</span><span class="o">().</span><span class="na">stream</span><span class="o">()</span>
</code></pre></div></div>

<p><strong>entrySet()</strong> nos va a devolver el mapa en formato de <strong>colección</strong>, que es lo que necesitamos para permitir su ordenación y <strong>stream()</strong> lo que nos va a permitir es obtener un <strong>punto de entrada</strong> a esa <strong>colección</strong>.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sorted</span><span class="o">(</span><span class="n">comparingInt</span><span class="o">(</span><span class="n">e</span> <span class="o">-&gt;</span> <span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">e</span><span class="o">.</span><span class="na">getValue</span><span class="o">()))</span>
</code></pre></div></div>

<p>Este <strong>método</strong> nos va a permitir realizar la ordenación, comparando los valores de nuestro <strong>Map</strong> de forma descendente gracias al valor -1. Si quisiéramos hacerlo de forma ascendente debemos reemplazar este valor con un 1. Si queremos ordenar por <strong>key</strong> simplemente reemplazaríamos <strong>e.getValue()</strong> por <strong>e.getKey()</strong>.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="n">toMap</span><span class="o">(</span>
        <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">::</span><span class="n">getKey</span><span class="o">,</span>
        <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">::</span><span class="n">getValue</span><span class="o">,</span>
        <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">AssertionError</span><span class="o">();},</span>
        <span class="nl">LinkedHashMap:</span><span class="o">:</span><span class="k">new</span>
<span class="o">));</span>
</code></pre></div></div>

<p>Por último, este método nos procesa la información y la almacena en un contenedor de resultados mutables, y en este caso le indicamos que realiza un parseo a objeto <strong>Map</strong>.</p>

<p>Después de eso ya solo queda devolver nuestro <strong>Map</strong> y podremos pintar el resultado ordenado.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">Input:</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">15</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">12</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">22</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">27</span><span class="p">,</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">7</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">87</span><span class="p">,}</span><span class="w">
</span><span class="err">Output:</span><span class="w"> </span><span class="p">{</span><span class="mi">7</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">87</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">27</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">22</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">15</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">12</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="mi">4</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Si quieres ver el script completo puedes verlo en <a href="https://github.com/inazense/scripts/blob/master/scripts/java/SortMapByValue.java">mi repositorio de GitHub</a>.</p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="java" /><category term="hashmap" /><category term="map" /><category term="ordenacion" /><category term="streams" /><category term="sorting" /><category term="collections" /><summary type="html"><![CDATA[Aprende a ordenar HashMap en Java por clave o valor con streams y lambdas. Tutorial completo con código paso a paso sobre sorting de Map, entrySet, comparingInt y LinkedHashMap con ejemplos prácticos.]]></summary></entry><entry><title type="html">Crear una barra de progreso en la terminal con Python</title><link href="https://inazense.github.io/posts/2019/11/04/crear-una-barra-de-progreso-en-la-terminal-con-python/" rel="alternate" type="text/html" title="Crear una barra de progreso en la terminal con Python" /><published>2019-11-04T04:33:00+01:00</published><updated>2019-11-04T04:33:00+01:00</updated><id>https://inazense.github.io/posts/2019/11/04/crear-una-barra-de-progreso-en-la-terminal-con-python</id><content type="html" xml:base="https://inazense.github.io/posts/2019/11/04/crear-una-barra-de-progreso-en-la-terminal-con-python/"><![CDATA[<p>Cuando trabajamos con <strong>Python</strong> pintando resultados en la <strong>terminal</strong>, puede quedar un poco feo dejar el cursor esperando mientras procesamos ciertas acciones que van a tardar un tiempo en completarse. Esto es así aquí y en la China. El cursor parpadeando pone nervioso a todo el mundo.</p>

<p>Pero… ¿cuál podría ser la solución? Cierta librería, llamada <strong>tqdm</strong>, disponible para <strong>Python 3.x.</strong></p>

<h2 id="qué-es-tqdm">¿Qué es tqdm?</h2>

<p>Es una <strong>librería de Python</strong> que nos va a permitir pintar <strong>barras de progreso</strong> directamente en la <strong>terminal</strong>, iterando en bucles for / while y de la que nos vamos a desentender prácticamente desde el primer minuto.</p>

<p>El resultado final sería tal que así</p>

<p><img src="/img/posts/20191104_1.png" alt="tqdm lib example on python 3" /></p>

<p>Una simple <strong>barra de progreso</strong>, en el color por defecto de la <strong>terminal</strong>, que se irá rellenando progresivamente según iteremos dentro de nuestro bucle.</p>

<h2 id="y-cómo-se-hace-eso">¿Y cómo se hace eso?</h2>

<p>Lo primero, será instalar <strong>tqdm</strong>. Para ello nos iremos a la terminal y escribiremos el siguiente comando:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>tqdm
</code></pre></div></div>

<p>Por supuesto, si en nuestro ordenador tenemos <strong>Python2</strong> y <strong>Python3</strong>, deberemos reemplazar el comando <strong>pip</strong> por <strong>pip3</strong>.</p>

<p>Hecho esto, veamos un par de ejemplos, harto sencillos ambos dos.
En el primer <strong>script</strong>, vamos a realizar una iteración hasta llegar a un número en concreto, por ejemplo el 100:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>
<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span>

<span class="n">tareas</span> <span class="o">=</span> <span class="mi">100</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">tareas</span><span class="p">)):</span>
    <span class="n">sleep</span><span class="p">(</span><span class="mf">0.2</span><span class="p">)</span>
</code></pre></div></div>

<p>Básicamente lo que estamos haciendo es importar nuestra <strong>librería</strong>, definir un valor hasta el que iterar y envolver el objeto sobre el que iteraremos con el método <strong>tqdm</strong>. Rápido y sencillo.
La función sleep simplemente “duerme” la aplicación 0.2 segundos cada vez que entra en el <strong>for</strong>, para poder ver el progreso de nuestra barra tranquilamente. Por supuesto, no es necesario mantenerla y está ahí como mero ejemplo del <strong>código</strong> que podemos insertar.</p>

<p>Y, en caso de que lo que deseemos sea un lista, lo haremos del siguiente modo:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>
<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span>

<span class="n">tareas</span> <span class="o">=</span> <span class="p">[</span><span class="s">"tarea1"</span><span class="p">,</span> <span class="s">"tarea2"</span><span class="p">,</span> <span class="s">"tarea3"</span><span class="p">,</span> <span class="s">"tarea4"</span><span class="p">,</span> <span class="s">"tarea5"</span><span class="p">]</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">(</span><span class="n">tareas</span><span class="p">):</span>
    <span class="n">sleep</span><span class="p">(</span><span class="mf">0.2</span><span class="p">)</span>
</code></pre></div></div>

<p>¿Cuál es la única diferencia? Que ya no usamos el <strong>range</strong>, sino que lo recorremos como si fuese una lista (¡que lo es!) normal <strong>pythonesca</strong> de toda la vida.</p>

<p>Y hecho esto, ya podemos trabajar felices de la vida sabiendo que nuestros resultados aparecerán por pantalla de una forma un poquito más visual que antes.</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Python" /><category term="python" /><category term="tqdm" /><category term="barra-progreso" /><category term="terminal" /><category term="cli" /><category term="progress-bar" /><summary type="html"><![CDATA[Aprende a crear barras de progreso en la terminal con Python usando tqdm. Tutorial completo paso a paso sobre instalación, uso en bucles for/while, iteración de listas y ejemplos prácticos de código.]]></summary></entry><entry><title type="html">ReactJS I. Instalar React en Windows</title><link href="https://inazense.github.io/posts/2019/04/04/instalar-react-en-windows/" rel="alternate" type="text/html" title="ReactJS I. Instalar React en Windows" /><published>2019-04-04T05:33:00+02:00</published><updated>2019-04-04T05:33:00+02:00</updated><id>https://inazense.github.io/posts/2019/04/04/instalar-react-en-windows</id><content type="html" xml:base="https://inazense.github.io/posts/2019/04/04/instalar-react-en-windows/"><![CDATA[<p><strong>ReactJS</strong> (o React a secas) es una <strong>librería JavaScript</strong> de código abierto creada por <strong>Facebook</strong> para diseñar interfaces de usuario. No os voy a aburrir con más teoría porque eso es muy fácil de encontrar, así que os enlazo directamente con <a href="https://es.wikipedia.org/wiki/React">el artículo de Wikipedia</a> y si os apetece podéis leerlo tranquilamente.</p>

<p>Aquí nos vamos a centrar en la parte más práctica y, aprovechando que estoy en pleno aprendizaje de esta tecnología, iré escribiendo en una nueva sección de tutoriales lo que vaya consiguiendo aprender.</p>

<p>Esta entrada será muy cortita, así que vamos al grano.</p>

<h2 id="cómo-instalar-reactjs-en-windows">¿Cómo instalar ReactJS en Windows?</h2>

<p>Para instalar <strong>React en Windows 10</strong> usaremos el gestor de paquetes <strong>npm</strong>, que se incluye en la instalación de <strong>NodeJS</strong> (si bien no estamos supeditados a crear el backend de nuestra app con NodeJS, podemos usar el que más rabia nos dé).</p>

<p>Nos vamos a la web de Node (<a href="https://nodejs.org/es/download/">https://nodejs.org/es/download/</a>) y descargamos la versión que nos apetezca. En mi caso la de <strong>64 bits</strong>. Una vez descargado simplemente lo instalamos (siguiente - siguiente - siguiente) y al finalizar solo nos quedará comprobar si la instalación se ha llevado a cabo correctamente.</p>

<p>Abrimos la <strong>consola de comandos</strong> y escribimos este comando para que nos devuelva la versión actual de <strong>Node</strong>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>node <span class="nt">--version</span>
</code></pre></div></div>

<p>Y lo mismo para comprobar si está instalado <strong>npm</strong>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nt">--version</span>
</code></pre></div></div>

<p>Si ha ido todo bien, veremos algo como lo siguiente:</p>

<p><img src="/img/posts/20190404_1.png" alt="Versiones de Node y npm" /></p>

<p>¿Tenemos todo ok? Perfecto. ¿No tenemos algo similar a la imagen? Eso se ha producido debido a que no se han agregado esos comandos a las <strong>variables de entorno</strong>. Podemos solucionarlo siguiendo los pasos que especifican en <a href="https://stackoverflow.com/questions/27864040/fixing-npm-path-in-windows-8-and-10">ésta pregunta de Stackoverflow</a>.</p>

<p>Una vez que esa parte nos funciona, lo siguiente será hacer la instalación de todos los paquetes necesarios para <strong>ReactJS</strong>.</p>

<p>Escribiremos el siguiente comando:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nb">install</span> <span class="nt">-g</span> create-react-app
</code></pre></div></div>

<p>Con este comando lo que hacemos es instalar <strong>ReactJS</strong> en nuestro ordenador de forma <strong>global</strong>. Si no agregásemos el parámetro <code class="language-plaintext highlighter-rouge">-g</code> sólo podríamos usar ReactJS en la carpeta donde hemos ejecutado el código.</p>

<p>También podemos comprobar si se ha ejecutado correctamente con el comando:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>create-react-app <span class="nt">--version</span>
</code></pre></div></div>

<p>De esta manera lo podremos emplear donde gustemos. Veremos algo tal que así:</p>

<p><img src="/img/posts/20190404_2.png" alt="Create React App instalado" /></p>

<p>¡Conseguido! Estamos listos para el último paso, <strong>crear un nuevo proyecto de ReactJS</strong>.</p>

<h2 id="cómo-crear-un-proyecto-reactjs-en-windows">¿Cómo crear un proyecto ReactJS en Windows?</h2>

<p>Es harto sencillo y escribimos el siguiente comando:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>create-react-app my-app
</code></pre></div></div>

<p>Este comando generará todo lo necesario para poder empezar a usar la nueva aplicación de <strong>ReactJS</strong>. Veremos lo siguiente por consola:</p>

<p><img src="/img/posts/20190404_3.png" alt="Creando proyecto React" /></p>

<p>Al final de la imagen podemos ver que nos dan las instrucciones necesarias para arrancar nuestra aplicación de <strong>ReactJS</strong>, así comprobamos que todo está funcionando como debiera.</p>

<p>Ejecutamos los siguientes comandos:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>my-app
npm start
</code></pre></div></div>

<p>Y en nuestro navegador por defecto se abrirá la siguiente web:</p>

<p><img src="/img/posts/20190404_4.png" alt="ReactJS localhost" /></p>

<p>Eso sería todo de momento, en futuras entregas iremos ampliando con más cositas.</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="JavaScript" /><category term="react" /><category term="reactjs" /><category term="javascript" /><category term="windows" /><category term="nodejs" /><category term="npm" /><category term="create-react-app" /><category term="instalacion" /><summary type="html"><![CDATA[Guía completa para instalar React en Windows 10 paso a paso: descarga Node.js, configuración de npm, instalación de create-react-app y creación de tu primer proyecto ReactJS con ejemplos prácticos.]]></summary></entry><entry><title type="html">Sincronizar carpetas externas en OneDrive</title><link href="https://inazense.github.io/posts/2019/02/15/sincronizar-carpetas-externas-en-onedrive/" rel="alternate" type="text/html" title="Sincronizar carpetas externas en OneDrive" /><published>2019-02-15T04:33:00+01:00</published><updated>2019-02-15T04:33:00+01:00</updated><id>https://inazense.github.io/posts/2019/02/15/sincronizar-carpetas-externas-en-onedrive</id><content type="html" xml:base="https://inazense.github.io/posts/2019/02/15/sincronizar-carpetas-externas-en-onedrive/"><![CDATA[<p>Esta será una entrada cortita pero creo que bastante útil.
Es posible que, al igual que yo, uséis <strong>OneDrive</strong> para <strong>sincronizar</strong> vuestros documentos en la nube pero os moleste considerablemente no poder sincronizar varias <strong>carpetas</strong> en concreto que tengáis en vuestro ordenador.</p>

<p>Es decir, mi carpeta de <strong>OneDrive</strong> está localizada en <em>C:\Users\Usuario\OneDrive</em> pero tengo otra carpeta en <em>C:\OtraCarpeta</em> que me gustaría que se <strong>sincronizase</strong> también para poder <strong>acceder a los datos desde otros lugares</strong>, tener <strong>backup</strong>… Razones varias.</p>

<p>Pues bien….</p>

<h2 id="cómo-lo-hacemos">¿Cómo lo hacemos?</h2>

<p>Usaremos <strong>enlaces simbólicos</strong> que no es más que un <strong>“acceso directo”</strong> a una carpeta (o archivo) que se encuentra en otro directorio. Como iba diciendo, crearemos un <strong>enlace simbólico</strong> ejecutando el <strong>símbolo de sistema</strong> (¡ojo!, que no <strong>PowerShell</strong>) como <strong>administrador</strong> y escribiendo el siguiente comando:</p>

<pre><code class="language-cmd">mklink /D "rutaOneDrive\nuevaCarpeta" "rutaCarpetaASincronizar"
</code></pre>

<p>Después de eso, si nos vamos a nuestra carpeta de <strong>OneDrive</strong>, veremos que se creó un acceso directo a la carpeta anterior y que la <strong>sincronización</strong> comenzará a funcionar.</p>

<p>Y eso sería todo. <strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Sistemas" /><category term="onedrive" /><category term="windows" /><category term="enlaces-simbolicos" /><category term="mklink" /><category term="sincronizacion" /><category term="backup" /><category term="cloud" /><summary type="html"><![CDATA[Aprende a sincronizar carpetas externas en OneDrive con enlaces simbólicos usando mklink. Tutorial paso a paso para crear backup automático de cualquier carpeta en Windows con el símbolo del sistema.]]></summary></entry><entry><title type="html">Tutorial Java - Log4j desde cero</title><link href="https://inazense.github.io/posts/2018/08/03/tutorial-java-log4j-desde-cero/" rel="alternate" type="text/html" title="Tutorial Java - Log4j desde cero" /><published>2018-08-03T06:10:00+02:00</published><updated>2018-08-03T06:10:00+02:00</updated><id>https://inazense.github.io/posts/2018/08/03/tutorial-java-log4j-desde-cero</id><content type="html" xml:base="https://inazense.github.io/posts/2018/08/03/tutorial-java-log4j-desde-cero/"><![CDATA[<p>En el trabajo me ha surgido la necesidad de trabajar con la librería <a href="https://logging.apache.org/log4j">Log4j</a> en un proyecto y como me he vuelto un poco loco para configurarla que menos que aprovechar para retomar este blog (again).</p>

<h2 id="qué-es-log4j">¿Qué es Log4j?</h2>

<p><strong>Log4j</strong> es una librería perteneciente a los <strong>Java Logging Frameworks</strong> desarrollada por <strong>Apache Software Foundation</strong> usada para generar mensajes de <strong>logging</strong> de una forma limpia, sencilla, permitiendo filtrarlos por importancia y pudiendo configurar su <strong>salida</strong> tanto por <strong>consola, fichero</strong> u otras diferentes.</p>

<h2 id="niveles-de-prioridad">Niveles de prioridad</h2>

<p>Existen diversos niveles de prioridad. Los cinco que más empleo, ordenados por nivel más bajo son:</p>

<ul>
  <li><strong>DEBUG</strong>: Usado para escribir mensajes de depuración</li>
  <li><strong>INFO</strong>: Mensajes de estilo verbose. Puramente informativos de determinada acción</li>
  <li><strong>WARN</strong>: Para alertar de eventos de los que se quiere dejar constancia pero que no afectan al funcionamiento de la aplicación</li>
  <li><strong>ERROR</strong>: Usado para los mensajes de eventos que afectan al programa pero lo dejan seguir funcionando. Algún parámetro no es correcto pero se carga el parámetro por defecto, por ejemplo</li>
  <li><strong>FATAL</strong>: Usado para errores críticos. Normalmente después de guardar el mensaje el programa terminará</li>
</ul>

<h2 id="appenders">Appenders</h2>

<p>Otra parte fundamental de Log4j son los <strong>appenders</strong>. Y tu te preguntarás, <strong>¿qué son los appenders?</strong> Pues básicamente es cada una de las salidas por las que puede ser enviado un mensaje de <strong>log</strong>.</p>

<p>Existen varios <strong>appenders</strong> y todos ellos son configurables, aunque también podemos crear los nuestros propios.</p>

<p>Los appenders más usuales son:</p>

<ul>
  <li><strong>FileAppender / RollingFileAppender</strong>: Salida redirigida a un fichero de texto .log</li>
  <li><strong>SocketAppender</strong>: Hacia un servidor remoto para almacenar los registros</li>
  <li><strong>SMTPAppender</strong>: A un correo electrónico</li>
  <li><strong>JDBCAppender</strong>: Hacia una base de datos</li>
  <li><strong>ConsoleAppender</strong>: Salida por consola. En un entorno de producción no se suele usar esta forma por perder gran parte de su utilidad pero mientras se desarrolla es una forma útil de ver logs in situ.</li>
</ul>

<h2 id="y-la-parte-práctica-qué">¿Y la parte práctica, qué?</h2>

<p>Sí, sé que lo estás pensando. <strong>¿Cuándo va a empezar a explicar cómo hacerlo, que es lo que me interesa a mi?</strong> Pues venga, estás de suerte. Tu hora ha llegado.</p>

<p>Voy a explicar como montar un <strong>sistema logging básico con Log4j</strong> que nos muestre la salida tanto <strong>por consola como en un fichero</strong>.</p>

<h2 id="preparándonos">Preparándonos</h2>

<p>La explicación la voy a realizar con un proyecto <strong>Maven</strong>, así que lo primero que haremos será agregar la dependencia de <strong>Log4j</strong> a nuestro <strong>pom</strong>. La podemos encontrar <a href="https://mvnrepository.com/artifact/log4j/log4j">aquí</a>.</p>

<p>Si no sabes de que te estoy hablando puedes ver <a href="http://www.programandoapasitos.com/2017/07/tutorial-maven-en-eclipse.html">mi anterior entrada sobre <strong>Maven</strong></a> o bajarte el <strong>.jar</strong> y configurarla manualmente desde el mismo enlace.</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>log4j<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>log4j<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>1.2.17<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
</code></pre></div></div>

<h2 id="creando-y-configurando-el-archivo-log4jproperties">Creando y configurando el archivo log4j.properties</h2>

<p>Podríamos configurarlo a través de código o con la configuración básica por defecto, pero lo que vamos a hacer es configurar las opciones de <strong>Log4j</strong> a través de un archivo <strong>properties</strong>.</p>

<p>Para ello nos iremos, dentro de nuestro proyecto, a la carpeta <code class="language-plaintext highlighter-rouge">src/main/resources</code> y creamos un fichero nuevo que se llame <code class="language-plaintext highlighter-rouge">log4j.properties</code>.</p>

<p><img src="/img/posts/20180803_1.png" alt="default log4j.properties" /></p>

<p>Lo abrimos y escribimos el siguiente contenido:</p>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">log4j.rootLogger</span><span class="p">=</span><span class="s">DEBUG, stdout, file</span>
<span class="py">log4j.logger.infoLogger</span><span class="p">=</span><span class="s">DEBUG</span>
<span class="py">log4j.additivity.infoLogger</span> <span class="p">=</span> <span class="s">false</span>

<span class="c"># Redirigir mensajes por consola
</span><span class="py">log4j.appender.stdout</span><span class="p">=</span><span class="s">org.apache.log4j.ConsoleAppender</span>
<span class="py">log4j.appender.stdout.Target</span><span class="p">=</span><span class="s">System.out</span>
<span class="py">log4j.appender.stdout.layout</span><span class="p">=</span><span class="s">org.apache.log4j.PatternLayout</span>
<span class="py">log4j.appender.stdout.layout.ConversionPattern</span><span class="p">=</span><span class="s">[%d{yyyy-MM-dd HH:mm:ss}] [ %-5p] [%c{1}:%L] %m%n</span>

<span class="c"># Redirigir los mensajes a un fichero de texto soportando file rolling
</span><span class="py">log4j.appender.file</span><span class="p">=</span><span class="s">org.apache.log4j.RollingFileAppender</span>
<span class="py">log4j.appender.file.File</span><span class="p">=</span><span class="s">avisos.log</span>
<span class="py">log4j.appender.file.MaxFileSize</span><span class="p">=</span><span class="s">5MB</span>
<span class="py">log4j.appender.file.MaxBackupIndex</span><span class="p">=</span><span class="s">10</span>
<span class="py">log4j.appender.file.layout</span><span class="p">=</span><span class="s">org.apache.log4j.PatternLayout</span>
<span class="py">log4j.appender.file.layout.ConversionPattern</span><span class="p">=</span><span class="s">[%d{yyyy-MM-dd HH:mm:ss}] [ %-5p] [%c{1}:%L] %m%n</span>
</code></pre></div></div>

<p>Vamos a ver más detalladamente que hace cada parte de este fichero:</p>

<h3 id="configuración-básica">Configuración básica</h3>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">log4j.rootLogger</span><span class="p">=</span><span class="s">DEBUG, stdout, file</span>
<span class="py">log4j.logger.infoLogger</span><span class="p">=</span><span class="s">DEBUG</span>
<span class="py">log4j.additivity.infoLogger</span> <span class="p">=</span> <span class="s">false</span>
</code></pre></div></div>

<ul>
  <li>En la <strong>primera línea</strong> estamos indicando el <strong>nivel mínimo de logging</strong> y los <strong>appenders que vamos a emplear</strong>. En este caso usaremos un nivel de logging establecido en DEBUG y creamos dos appenders, stdout y file.</li>
  <li>La <strong>segunda línea</strong> sirve para configurar en que nivel se empezarán a mostrar las advertencias tanto por consola como a almacenarse en el fichero.</li>
  <li>Y con la <strong>tercera línea</strong> evitamos que los appenders hereden la configuración de sus appenders padres, en caso de que los hubiera (en el nuestro, sería el appender principal así que no tenemos ese problema).</li>
</ul>

<h3 id="configuración-por-consola">Configuración por consola</h3>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Redirigir mensajes por consola
</span><span class="py">log4j.appender.stdout</span><span class="p">=</span><span class="s">org.apache.log4j.ConsoleAppender</span>
<span class="py">log4j.appender.stdout.Target</span><span class="p">=</span><span class="s">System.out</span>
<span class="py">log4j.appender.stdout.layout</span><span class="p">=</span><span class="s">org.apache.log4j.PatternLayout</span>
<span class="py">log4j.appender.stdout.layout.ConversionPattern</span><span class="p">=</span><span class="s">[%d{yyyy-MM-dd HH:mm:ss}] [ %-5p] [%c{1}:%L] %m%n</span>
</code></pre></div></div>

<p>En estas líneas vamos a crear la configuración para imprimir los mensajes por consola:</p>

<ul>
  <li>En la <strong>primera línea</strong> indicamos que tipo de logger será haciendo referencia a la clase que imprimirá los mensajes (¡recuerda la sección Appenders!).</li>
  <li>En la <strong>segunda</strong> le decimos que queremos imprimirlo directamente por la consola.</li>
  <li>Y las <strong>dos últimas</strong> son para configurar la plantilla que tendrá cada mensaje.</li>
</ul>

<p>Puedes ver todas las posibles opciones de configuración en la <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html">página de ayuda de Oracle</a>.</p>

<p>El mensaje de salida sería algo tal que así:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[2018-08-03 11:48:39] [ INFO ] [App:29] Esto es una prueba desde App class.
</code></pre></div></div>

<h3 id="configuración-para-fichero">Configuración para fichero</h3>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Redirigir los mensajes a un fichero de texto soportando file rolling
</span><span class="py">log4j.appender.file</span><span class="p">=</span><span class="s">org.apache.log4j.RollingFileAppender</span>
<span class="py">log4j.appender.file.File</span><span class="p">=</span><span class="s">avisos.log</span>
<span class="py">log4j.appender.file.MaxFileSize</span><span class="p">=</span><span class="s">5MB</span>
<span class="py">log4j.appender.file.MaxBackupIndex</span><span class="p">=</span><span class="s">10</span>
<span class="py">log4j.appender.file.layout</span><span class="p">=</span><span class="s">org.apache.log4j.PatternLayout</span>
<span class="py">log4j.appender.file.layout.ConversionPattern</span><span class="p">=</span><span class="s">[%d{yyyy-MM-dd HH:mm:ss}] [ %-5p] [%c{1}:%L] %m%n</span>
</code></pre></div></div>

<p>En estas líneas vamos a hacer exactamente lo mismo que antes pero configurando el appender para que salga a través de un fichero:</p>

<ul>
  <li>En la <strong>primera línea</strong> configuramos la clase como <strong>RollingFileAppender</strong>, lo que significa que se crearán distintos ficheros al cumplirse determinadas condiciones que tratamos en las siguientes líneas.</li>
  <li>En la <strong>siguiente</strong> indicamos el nombre (con ruta incluida) que queremos que tenga nuestro fichero de log.</li>
  <li>Con <strong>MaxFileSize</strong> establecemos el tamaño máximo que tendrá nuestro fichero, y con <strong>MaxBackupIndex</strong> indicamos cuantos archivos podemos tener usando el mismo log. A partir de llegar al máximo, comenzarán a sobrescribirse empezando por el más antiguo.</li>
  <li>Y por último, al igual que por consola, indicamos que plantilla tendrán nuestros mensajes.</li>
</ul>

<h2 id="código-java-para-log4j">Código Java para Log4j</h2>

<p>La forma que me resulta más fácil de trabajar es <strong>crearme una clase independiente que funcione como un handler para Log4j</strong>.</p>

<p>Lo primero es definirme un enum con los tipos de log que puedo tener. En un alarde de originalidad lo podemos llamar… no sé, <code class="language-plaintext highlighter-rouge">TipoLog.java</code>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">enum</span> <span class="nc">TipoLog</span> <span class="o">{</span>
    <span class="no">DEBUG</span><span class="o">,</span> <span class="no">ERROR</span><span class="o">,</span> <span class="no">FATAL</span><span class="o">,</span> <span class="no">INFO</span><span class="o">,</span> <span class="no">WARNING</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Son las opciones de log que os conté en la sección <strong>Niveles de prioridad</strong>.</p>

<p>La siguiente parte es crear la clase Java, tal que así:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">org.apache.log4j.Logger</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.log4j.LogManager</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">UtilesLog</span> <span class="o">{</span>
    
    <span class="kd">private</span> <span class="kd">static</span> <span class="nc">Logger</span> <span class="n">log</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">UtilesLog</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
    
    <span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"rawtypes"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">registrarInfo</span><span class="o">(</span><span class="nc">Class</span> <span class="n">clase</span><span class="o">,</span> <span class="nc">TipoLog</span> <span class="n">tipo</span><span class="o">,</span> <span class="nc">String</span> <span class="n">mensaje</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">log</span> <span class="o">=</span> <span class="nc">LogManager</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">clase</span><span class="o">);</span>
        
        <span class="k">switch</span> <span class="o">(</span><span class="n">tipo</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">case</span> <span class="nl">DEBUG:</span>
                <span class="n">log</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="n">mensaje</span><span class="o">);</span>
                <span class="k">break</span><span class="o">;</span>
            <span class="k">case</span> <span class="nl">ERROR:</span>
                <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="n">mensaje</span><span class="o">);</span>
                <span class="k">break</span><span class="o">;</span>
            <span class="k">case</span> <span class="nl">FATAL:</span>
                <span class="n">log</span><span class="o">.</span><span class="na">fatal</span><span class="o">(</span><span class="n">mensaje</span><span class="o">);</span>
                <span class="k">break</span><span class="o">;</span>
            <span class="k">case</span> <span class="nl">INFO:</span>
                <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="n">mensaje</span><span class="o">);</span>
                <span class="k">break</span><span class="o">;</span>
            <span class="k">case</span> <span class="nl">WARNING:</span>
                <span class="n">log</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="n">mensaje</span><span class="o">);</span>
                <span class="k">break</span><span class="o">;</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>En esta clase tenemos una <strong>propiedad privada estática</strong> configurada por defecto para ser el Logger de la clase que lo contiene, <strong>UtilesLog</strong>. Podéis poner el nombre que deseéis por supuesto.</p>

<p>Esto se hace porque la <strong>clase Logger tiene que estar apuntando siempre a una clase</strong> sobre la que se crearán los mensajes, así que en vez de tener que declarar este Logger en todas y cada una de las clases de nuestro proyecto, podemos manejarlo en un único fichero de este modo.</p>

<p><strong>¿Y como mandamos el logger entonces?</strong> Con el método que tenemos debajo, <strong>registrarInfo</strong>.</p>

<p>Si te das cuenta tiene <strong>tres parámetros</strong>:</p>
<ul>
  <li>La <strong>clase</strong> sobre la que queremos generar los mensajes</li>
  <li>El <strong>tipo</strong> de mensaje</li>
  <li>El <strong>contenido</strong> del mismo</li>
</ul>

<p>Lo que hacemos simplemente es <strong>establecer el Logger para la clase pasada como parámetro</strong> y, dependiendo del tipo de log, <strong>enviar un tipo de mensaje u otro</strong>.</p>

<h2 id="ejemplo-de-uso">Ejemplo de uso</h2>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">App</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">UtilesLog</span><span class="o">.</span><span class="na">registrarInfo</span><span class="o">(</span><span class="nc">App</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="nc">TipoLog</span><span class="o">.</span><span class="na">INFO</span><span class="o">,</span> <span class="s">"Esto es una prueba desde App class."</span><span class="o">);</span>
        <span class="nc">UtilesLog</span><span class="o">.</span><span class="na">registrarInfo</span><span class="o">(</span><span class="nc">App</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="nc">TipoLog</span><span class="o">.</span><span class="na">DEBUG</span><span class="o">,</span> <span class="s">"Mensaje de debug"</span><span class="o">);</span>
        <span class="nc">UtilesLog</span><span class="o">.</span><span class="na">registrarInfo</span><span class="o">(</span><span class="nc">App</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="nc">TipoLog</span><span class="o">.</span><span class="na">ERROR</span><span class="o">,</span> <span class="s">"Ha ocurrido un error"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Y <strong>¡listo!</strong>, ya tenemos nuestro <strong>sistema de logging con Log4j creado y completamente funcional</strong>.</p>

<p>Puedes visitar el código completo en <a href="https://github.com/inazense/scripts/tree/master/scripts/java/ManejadorLog4j">mi repositorio de Github</a>.</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="java" /><category term="log4j" /><category term="logging" /><category term="appenders" /><category term="configuracion" /><category term="maven" /><category term="properties" /><summary type="html"><![CDATA[Aprende a integrar Log4j en proyectos Java con Maven. Guía paso a paso sobre configuración con ficheros properties, tipos de appenders, niveles de log y ejemplos de uso reales.]]></summary></entry><entry><title type="html">Leer ficheros properties en Java</title><link href="https://inazense.github.io/posts/2017/12/12/leer-ficheros-properties-en-java/" rel="alternate" type="text/html" title="Leer ficheros properties en Java" /><published>2017-12-12T10:11:00+01:00</published><updated>2017-12-12T10:11:00+01:00</updated><id>https://inazense.github.io/posts/2017/12/12/leer-ficheros-properties-en-java</id><content type="html" xml:base="https://inazense.github.io/posts/2017/12/12/leer-ficheros-properties-en-java/"><![CDATA[<p>Una práctica habitual en Java es guardar <strong>parámetros de configuración</strong> en un <strong>archivo de propiedades</strong>, que es básicamente un fichero de texto plano con la extensión <strong>.properties</strong> con su contenido almacenado como una <strong>pareja clave=valor</strong> y con el símbolo # para indicar línea de comentario.</p>

<p>Por ejemplo:</p>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Archivo properties
</span><span class="py">usuario</span><span class="p">=</span><span class="s">Inazio</span>
<span class="py">password</span><span class="p">=</span><span class="s">programandoapasitos.com</span>
<span class="py">ruta</span><span class="p">=</span><span class="s">/home/inazio/resources</span>
</code></pre></div></div>

<p>Así, en este ejemplo la primera línea será solo de comentarios, y en las posteriores cada <strong>clave</strong> será un parámetro de nuestra configuración y, separado por un igual, su <strong>valor</strong> correspondiente.</p>

<p><strong>Java</strong> nos proporciona una herramienta muy útil y sencilla para leer los <strong>archivos de propiedades</strong>, la <strong>clase Properties</strong>.</p>

<p>Para usarla, lo primero que haremos será inicializar nuestro objeto y posteriormente indicarle que cargue el <strong>fichero de propiedades</strong>.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Properties</span> <span class="n">propiedades</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Properties</span><span class="o">();</span>
<span class="n">propiedades</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="k">new</span> <span class="nc">FileReader</span><span class="o">(</span><span class="s">"config.properties"</span><span class="o">));</span>
</code></pre></div></div>

<p>Hecho esto, sólo nos quedará indicar si queremos que lea una o todas las <strong>propiedades</strong>.</p>

<h2 id="leer-una-propiedad">Leer una propiedad</h2>

<p>La verdad es que es tremendamente sencillo. Para realizazr la <strong>lectura de un valor</strong> en nuestro <strong>archivo properties</strong> basta con la siguiente línea</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">propiedades</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">miClave</span><span class="o">)</span>
</code></pre></div></div>

<p>Como veis, lo único que hacemos es usar el método <code class="language-plaintext highlighter-rouge">getProperty</code> y como parámetro le pasamos la <strong>clave</strong> del <strong>valor</strong> a extraer, devolviéndonoslo como un <strong>String</strong>.</p>

<h2 id="leer-todas-las-propiedades">Leer todas las propiedades</h2>

<p>Para leer todas las <strong>propiedades</strong> recurriremos a un objeto <code class="language-plaintext highlighter-rouge">Enumeration</code> que nos permitirá iterar sobre todas ellas, leeremos la clave de los <strong>valores</strong> en un bucle y obteniendo la <strong>clave</strong>, usaremos el mismo modo que en el ejemplo anterior. En este caso lo imprimiremos también</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Enumeration</span><span class="o">&lt;</span><span class="nc">Object</span><span class="o">&gt;</span> <span class="n">claves</span> <span class="o">=</span> <span class="n">propiedades</span><span class="o">.</span><span class="na">keys</span><span class="o">();</span>
  
<span class="k">while</span> <span class="o">(</span><span class="n">claves</span><span class="o">.</span><span class="na">hasMoreElements</span><span class="o">())</span> <span class="o">{</span>
  <span class="nc">Object</span> <span class="n">clave</span> <span class="o">=</span> <span class="n">claves</span><span class="o">.</span><span class="na">nextElement</span><span class="o">();</span>
  <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">clave</span><span class="o">.</span><span class="na">toString</span><span class="o">()</span> <span class="o">+</span> <span class="s">" - "</span> <span class="o">+</span> <span class="n">propiedades</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">clave</span><span class="o">).</span><span class="na">toString</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div></div>

<p><strong>¿Qué hacemos exactamente?</strong></p>

<p>En nuestro objeto <code class="language-plaintext highlighter-rouge">Enumeration</code> almacenamos todas las <strong>claves</strong> que incluye nuestro objeto <strong>Properties</strong>, e iniciamos un bucle hasta que recorrer todos los elementos.
Después creamos un objeto genérico que será nuestra <strong>clave</strong>, y es la que usamos para extraer el valor de dicho par en la línea de abajo, aprovechando para imprimir la <strong>clave</strong> y la propiedad haciendo de ambas un casteo de <strong>String</strong>.</p>

<p>¿A que resulta tremendamente sencillo? Ahora solo es cuestión de practicar con ello.
Podéis ver el código completo de esta entrada en mi <a href="https://github.com/inazense/scripts/blob/master/scripts/java/ManejadorProperties.java"><strong>github público</strong></a>. Ahí tendréis una clase con un <strong>patrón Singleton</strong> que permite manejar este tipo de archivos..</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="java" /><category term="properties" /><category term="configuracion" /><category term="fileReader" /><category term="getProperty" /><category term="enumeration" /><summary type="html"><![CDATA[Aprende a leer archivos properties en Java con la clase Properties. Tutorial completo paso a paso sobre getProperty, Enumeration, carga de ficheros .properties y ejemplos prácticos de configuración con código.]]></summary></entry><entry><title type="html">Tutorial Maven en Eclipse (II). Generar un JAR</title><link href="https://inazense.github.io/posts/2017/11/27/tutorial-maven-en-eclipse-ii-generar-un-jar/" rel="alternate" type="text/html" title="Tutorial Maven en Eclipse (II). Generar un JAR" /><published>2017-11-27T06:00:00+01:00</published><updated>2017-11-27T06:00:00+01:00</updated><id>https://inazense.github.io/posts/2017/11/27/tutorial-maven-en-eclipse-ii-generar-un-jar</id><content type="html" xml:base="https://inazense.github.io/posts/2017/11/27/tutorial-maven-en-eclipse-ii-generar-un-jar/"><![CDATA[<p>En la anterior entrada del <a href="/posts/2017-07-28-tutorial-maven-en-eclipse.md"><strong>Tutorial Maven en Eclipse</strong></a> aprendimos qué es <strong>Maven</strong>, como <strong>crear un proyecto Maven en Eclipse</strong>, a configurarlo y a manejar las <strong>dependencias de librerías</strong>.</p>

<p>¿Cuál sería el siguiente paso lógico? Aprender como <strong>generar los archivos JAR con Maven</strong> y agregarle todas los recursos necesarias, para poder usar nuestro proyecto en cualquier máquina en que queramos ejecutarlo.</p>

<h2 id="generar-jar-con-maven">Generar JAR con Maven</h2>

<p>Realmente esta fase ya la vimos en el tutorial anterior, pero voy a entrar un poco más en profundidad en ella.
Para generar un JAR desde Eclipse basta con ponernos sobre la carpeta del proyecto y hacer <strong>botón derecho → Run As → Maven install</strong>.
O también puedes hacerlo desde la consola de comandos situándote en la carpeta principal del proyecto y ejecutar</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mvn <span class="nb">install</span>
</code></pre></div></div>

<p>Ambas acciones harán el mismo proceso, generar los archivos necesarios para la ejecución del proyecto dentro de la carpeta <strong>target</strong>.</p>

<p>Para comprobar que el proceso de <strong>maven install</strong> ha funcionado correctamente y la ruta donde se ha generado el <strong>jar</strong> bastará con ver los mensajes que nos aparecen después de la ejecución, tal que así</p>

<p><img src="/img/posts/20171127_1.png" alt="new maven project" /></p>

<p>Aquí podemos ver que el <strong>build</strong> se ha realizado correctamente y en el recuadro en rojo vemos la ruta donde se almacenó nuestro <strong>.jar</strong>.</p>

<h2 id="cómo-copiar-recursos-a-target-en-maven">¿Cómo copiar recursos a target en Maven?</h2>

<p>Ahora bien, tenemos nuestro proyecto ya compilado, lo ejecutamos y… nos damos cuenta de que en la carpeta <strong>target</strong> no se encuentran los <strong>recursos</strong> a los que hemos hecho referencia en nuestro proyecto. Podemos haber enlazado imagenes, iconos, archivos de configuración… con su ruta relativa referente a donde se encuentre el <strong>jar</strong>, pero claro, no están en <strong>target</strong>. ¿Cómo lo hacemos funcionar entonces? ¿Acaso debemos copiar a mano todos los recursos necesarios? ¿Y si éstos cambian y nos olvidamos un día de hacerlo?</p>

<p>Esta es una parte que me costó algo de tiempo descubrir cómo solucionarla, pero al final encontré con la manera propicia de arreglarlo.</p>

<p>Para ello debernos usar un nuevo <strong>plugin</strong> llamado <strong>maven-resources-plugin</strong>. Lo que hará este <strong>plugin</strong> es precisamente eso, ayudarnos a <strong>copiar las dependencias a la ruta que le indiquemos</strong> nosotros, y lo mejor es que lo hace a tiempo real, no espera a compilar el proyecto. Podemos agregar y remover los recursos que le indiquemos y el se encargará de replicarlos al mismo tiempo.</p>

<p><strong>¿Cómo configurar maven-resources-plugin?</strong></p>

<p>Para empezar a usarlo debemos abrir el <strong>pom.xml</strong>, y en la sección de <strong>plugins</strong> dentro de <strong>build</strong> (dónde en el anterior <strong>tutorial</strong> agregamos el plugin para compilar el proyecto), crearemos uno nuevo indicando su <strong>artifactid</strong> y su <strong>versión</strong>. Posteriormente crearemos un grupo de ejecuciones que serán las que contendrán todas las rutas a copiar en nuestro proyecto.
Vamos a ver un ejemplo entero para comprenderlo mejor</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Copia de recursos a target --&gt;</span>
<span class="nt">&lt;plugin&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>maven-resources-plugin<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>3.0.2<span class="nt">&lt;/version&gt;</span>
  <span class="nt">&lt;executions&gt;</span>
    <span class="c">&lt;!-- Primera ejecución --&gt;</span>
    <span class="nt">&lt;execution&gt;</span>
      <span class="nt">&lt;id&gt;</span>copy-configuracion<span class="nt">&lt;/id&gt;</span>
      <span class="nt">&lt;phase&gt;</span>validate<span class="nt">&lt;/phase&gt;</span>
      <span class="nt">&lt;goals&gt;</span>
        <span class="nt">&lt;goal&gt;</span>copy-resources<span class="nt">&lt;/goal&gt;</span>
      <span class="nt">&lt;/goals&gt;</span>
      <span class="nt">&lt;configuration&gt;</span>
        <span class="nt">&lt;outputDirectory&gt;</span>${basedir}/target/configuracion<span class="nt">&lt;/outputDirectory&gt;</span>
        <span class="nt">&lt;resources&gt;</span>
          <span class="nt">&lt;resource&gt;</span>
            <span class="nt">&lt;directory&gt;</span>configuracion<span class="nt">&lt;/directory&gt;</span>
            <span class="nt">&lt;filtering&gt;</span>true<span class="nt">&lt;/filtering&gt;</span>
          <span class="nt">&lt;/resource&gt;</span>
        <span class="nt">&lt;/resources&gt;</span>
      <span class="nt">&lt;/configuration&gt;</span>
    <span class="nt">&lt;/execution&gt;</span>

    <span class="c">&lt;!-- Segunda ejecución --&gt;</span>
    <span class="nt">&lt;execution&gt;</span>
      <span class="nt">&lt;id&gt;</span>copy-recursos<span class="nt">&lt;/id&gt;</span>
      <span class="nt">&lt;phase&gt;</span>validate<span class="nt">&lt;/phase&gt;</span>
      <span class="nt">&lt;goals&gt;</span>
        <span class="nt">&lt;goal&gt;</span>copy-resources<span class="nt">&lt;/goal&gt;</span>
      <span class="nt">&lt;/goals&gt;</span>
      <span class="nt">&lt;configuration&gt;</span>
        <span class="nt">&lt;outputDirectory&gt;</span>${basedir}/target/recursos<span class="nt">&lt;/outputDirectory&gt;</span>
        <span class="nt">&lt;resources&gt;</span>
          <span class="nt">&lt;resource&gt;</span>
            <span class="nt">&lt;directory&gt;</span>recursos<span class="nt">&lt;/directory&gt;</span>
            <span class="nt">&lt;filtering&gt;</span>true<span class="nt">&lt;/filtering&gt;</span>
          <span class="nt">&lt;/resource&gt;</span>
        <span class="nt">&lt;/resources&gt;</span>
      <span class="nt">&lt;/configuration&gt;</span>
    <span class="nt">&lt;/execution&gt;</span>
  <span class="nt">&lt;/executions&gt;</span>
<span class="nt">&lt;/plugin&gt;</span>
</code></pre></div></div>

<p>Empezando por arriba, el <strong>artifactid</strong> y la <strong>versión</strong> serán algo estático para todos nosotros (si modificamos la versión por otra debemos ser conscientes que las etiquetas y contenido usados pueden variar). Posteriormente abrimos un tag llamado <strong>executions</strong> que será el que englobe todas las acciones a realizar, sin límite aparente en cuanto a <strong>execution tags</strong> permitidos dentro de él.
Y dentro de una <strong>execution</strong> es donde comienza la chicha.</p>

<p>Desgranando todo el contenido de una ejecución, esto es lo que usaremos:</p>

<ul>
  <li><strong>id</strong> → Identifica de manera única esa ejecución</li>
  <li><strong>phase</strong> → Indica la fase del proyecto donde se ejecutará esa ejecución. Como lo hacemos en validación, nos aseguramos que practicamente trabajará en tiempo real.</li>
  <li><strong>goals</strong> → Serán las metas que establezcamos para esa ejecución
    <ul>
      <li><strong>goal</strong> → Cada una de las metas. Aquí escribiremos <strong>copy-configuration</strong> para indicar que queremos copiar determinados recursos en otro sitio</li>
    </ul>
  </li>
  <li><strong>configuration</strong> → Será la configuración que le daremos a las metas que hayamos indicado
    <ul>
      <li><strong>outputDirectory</strong> → La ruta donde <strong>Maven</strong> copiará los recursos que le indiquemos. Como ruta raíz usaremos la abreviación <code class="language-plaintext highlighter-rouge">${basedir}</code> para empezar dentro del proyecto</li>
      <li><strong>resources</strong> → Tag que incluye todas las dependencias que queramos copiar
        <ul>
          <li><strong>resource</strong> → Cada una de las dependencias que queramos copiar, ya sean ficheros o carpetas.
            <ul>
              <li><strong>directory</strong> → La ruta del recurso a copiar. Parte siempre desde el directorio raíz del proyecto</li>
              <li><strong>filtering</strong> → Lo agregaremos por defecto a true para que establezca las rutas del proyecto automáticamente</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<p>Así, en el anterior código lo que hago es copiar las carpetas de <code class="language-plaintext highlighter-rouge">configuracion</code> y <code class="language-plaintext highlighter-rouge">recursos</code> de mi proyecto al directorio de <strong>target</strong>, para poder usarlas directamente cuando genere el <strong>jar</strong> sin necesidad de agregarlas manualmente.</p>

<p><img src="/img/posts/20171127_2.png" alt="maven project tree" /></p>

<p>De esta manera puedo olvidarme de gestionar mis dependencias manualmente, que es para lo que sirve <strong>Maven</strong> y a lo que le podemos sacar mucho partido. Cuanto más grande el proyecto, más partido le sacaremos.</p>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="java" /><category term="maven" /><category term="eclipse" /><category term="jar" /><category term="maven-resources-plugin" /><category term="build" /><category term="pom" /><summary type="html"><![CDATA[Aprende a generar archivos JAR con Maven en Eclipse y copiar recursos automáticamente. Tutorial completo sobre maven-resources-plugin, configuración del POM, mvn install y gestión de dependencias paso a paso.]]></summary></entry><entry><title type="html">Tutorial Maven en Eclipse I</title><link href="https://inazense.github.io/posts/2017/07/28/tutorial-maven-en-eclipse/" rel="alternate" type="text/html" title="Tutorial Maven en Eclipse I" /><published>2017-07-28T06:10:00+02:00</published><updated>2017-07-28T06:10:00+02:00</updated><id>https://inazense.github.io/posts/2017/07/28/tutorial-maven-en-eclipse</id><content type="html" xml:base="https://inazense.github.io/posts/2017/07/28/tutorial-maven-en-eclipse/"><![CDATA[<p>De normal, cuando realizamos un <strong>proyecto Java</strong> si es pequeño nosotros mismos podemos hacer las actividades típicas de la construcción de software.</p>

<ul>
  <li>Instalar las librerías necesarias para nuestro proyecto en el classpath</li>
  <li>Correr los casos de test</li>
  <li>Crear la documentación del código fuente</li>
  <li>Compilar código fuente</li>
  <li>Empacar el código compilado en JAR</li>
</ul>

<p>Pero, ¿qué sucede conforme nuestro proyecto va creciendo y se va agregando más gente a él? Pues que podemos perder el control del mismo y es más plausible cometer errores humanos en la construcción del programa. Para eso está <strong>Maven</strong>.</p>

<h2 id="qué-es-maven">¿Qué es Maven?</h2>

<p><strong>Maven</strong> es una herramienta para la gestión de proyectos, que nos permitirá administrar completamente el ciclo de vida de la misma. Comúnmente se conoce a <strong>Maven</strong> como un gestor de dependencias Y YA. Y eso no es del todo cierto. Podemos considerarlo como una herramienta de construcción con muchas características, que nos ayuda a gestionar las dependencias, test, documentación, compilaciones, distribuciones e incluso los <em>mailing list</em>.</p>

<p>Si quieres una explicación más profesional de lo que es <strong>Maven</strong> puedes seguir el enlace hacía <a href="https://es.wikipedia.org/wiki/Maven">Maven en Wikipedia</a>.</p>

<p>Bien, centrémonos. ¿Qué es, entonces, lo que <strong>Maven</strong> puede hacer por nosotros? Así, en muy resumidas cuentas, lo siguiente:</p>

<ul>
  <li>Build. Construye nuestro código fuente del proyecto</li>
  <li>Test. Ejecuta los casos de prueba</li>
  <li>Gestiona las dependencias de nuestro proyecto. Es cierto que no es sólo un gestor, pero para mi es de lo mejor que tiene <strong>Maven</strong>. Importa las librerías automáticamente desde un repositorio remoto. Nos podemos olvidar de hacer esa tarea manualmente.</li>
  <li>Permite la creación y descarga de plantillas de proyectos para tener la estructura ya creada. Por ejemplo si nos vamos a dedicar a hacer páginas web, o conectores, nos interesará para ahorrarnos el trabajo de tener que empezar desde cero una y otra vez</li>
  <li>Crea una web con la documentación del proyecto</li>
  <li>Desplega el proyecto (AKA <strong>artefacto</strong>) en servidor</li>
  <li>Y por supuesto, perfecta integración con <strong>Git, SVN, Jira</strong>…</li>
</ul>

<p>Imagina hacer todo esto manualmente, y más de una persona que trabaje en nuestro proyecto. ¡Es para volverse loco!</p>

<p>Un par de cosas que conviene conocer antes de empezar:</p>

<ul>
  <li><strong>artefacto</strong>. Es un proyecto que lo gestiona <strong>Maven</strong> y que incluye un fichero llamado <strong>pom.xml</strong>.</li>
  <li><strong>POM</strong>. Son las siglas de <strong>Project Object Model</strong>. Es un fichero <strong>XML</strong> que contiene la configuración del artefacto. Más adelante trabajaremos con él. Si has programado en <strong>Android</strong> anteriormente, un símil adecuado sería el <strong>AndroidManifest</strong>.</li>
  <li><strong>groupId</strong>. El identificador único para crear nuestro artefacto. Se suele poner el mismo que en un paquete <em>java.com.programandoapasitos</em></li>
</ul>

<h2 id="maven-en-eclipse">Maven en Eclipse</h2>

<p>Tenéis que saber que <strong>Maven</strong> es perfectamente posible usarlo desde la consola de comandos. Si es el caso que estáis interesados en esa forma os recomiendo <a href="https://jarroba.com/maven/">éste artículo de Jarroba.com</a> que lo explica perfectamente.</p>

<p>Pero en nuestro caso vamos a usar la comodidad que nos da Eclipse con las herramientas que ya vienen integradas por defecto en su versión <a href="https://www.eclipse.org/downloads/">Java EE Developers</a> que es la que incluye el plugin de <strong>Maven</strong>, aunque ojo que puede no ser la última versión de <strong>Maven</strong> disponible.</p>

<p>Lo primero será crear un nuevo proyecto <strong>Maven</strong> yendo a <em>File → New → Other</em>.</p>

<p><img src="/img/posts/20170728_1.png" alt="maven new file" /></p>

<p>Elegimos <em><strong>Maven</strong> → <strong>Maven Project</strong></em> y pulsamos Next.</p>

<p><img src="/img/posts/20170728_2.png" alt="new maven project" /></p>

<p>Ahora deberemos elegir la configuración de nuestro proyecto <strong>Maven</strong>. En la siguiente ventana podemos marcar el check de <em>Create a simple Project</em> (skip archetype selection), lo que nos creará un proyecto completamente simple sin más configuración, o bien podemos desmarcarla, que será nuestro caso, y elegiremos un arquetipo de las opciones que nos muestre el asistente.</p>

<p><img src="/img/posts/20170728_3.png" alt="new maven project 2" /></p>

<p>En la nueva ventana puedes seleccionar un arquetipo del listado o cargar uno desde una ubicación. En nuestro caso seleccionaremos el de <strong>groupId</strong> <em>org.apache.maven.archetypes</em> y <strong>Artifact id</strong> <em>maven-archetype-quickstart</em> y pulsamos Next.</p>

<p><img src="/img/posts/20170728_4.png" alt="new maven project 3" /></p>

<p>Y ahora, por último paso del asistente, tendremos que indicar nuestro propio <strong>groupId</strong> y el <strong>artifactId</strong>. Esto se hace porque los que vimos en la anterior pantalla eran los que usaron los creadores del artefacto. Sobrescribiéndolos lo establecemos como queremos y aparte de la personalización, si algún día se convierte en arquetipo lo podrán buscar con nuestros datos, y reemplazarlos con los suyos.</p>

<p><img src="/img/posts/20170728_5.png" alt="new maven project 4" /></p>

<p>Pulsamos <em>Finish</em> y ya tendremos nuestro proyecto. La estructura quedará tal que así</p>

<p><img src="/img/posts/20170728_6.png" alt="maven project tree structure" /></p>

<h2 id="usando-maven">Usando Maven</h2>

<p>Ahora que ya tenemos nuestro <strong>proyecto Maven</strong> creado es hora de configurar el <strong>POM</strong> para hacerlo funcionar. Para ello hacemos doble click en el archivo <strong>pom.xml</strong> y en la pestaña inferior elegimos la sección <strong>pom.xml</strong> para poder ver el código <strong>XML</strong> “a pelo”.</p>

<p><img src="/img/posts/20170728_7.png" alt="using maven 1" /></p>

<p>Cuando entremos veremos un <strong>archivo XML</strong> similar a este</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;project</span> <span class="na">xmlns=</span><span class="s">"http://maven.apache.org/POM/4.0.0"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="na">xsi:schemaLocation=</span><span class="s">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;modelVersion&gt;</span>4.0.0<span class="nt">&lt;/modelVersion&gt;</span>

  <span class="nt">&lt;groupId&gt;</span>com.programandoapasitos<span class="nt">&lt;/groupId&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>nombrePrueba<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>0.0.1-SNAPSHOT<span class="nt">&lt;/version&gt;</span>
  <span class="nt">&lt;packaging&gt;</span>jar<span class="nt">&lt;/packaging&gt;</span>

  <span class="nt">&lt;name&gt;</span>nombrePrueba<span class="nt">&lt;/name&gt;</span>
  <span class="nt">&lt;url&gt;</span>http://maven.apache.org<span class="nt">&lt;/url&gt;</span>

  <span class="nt">&lt;properties&gt;</span>
    <span class="nt">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span class="nt">&lt;/project.build.sourceEncoding&gt;</span>
  <span class="nt">&lt;/properties&gt;</span>

  <span class="nt">&lt;dependencies&gt;</span>
    <span class="nt">&lt;dependency&gt;</span>
      <span class="nt">&lt;groupId&gt;</span>junit<span class="nt">&lt;/groupId&gt;</span>
      <span class="nt">&lt;artifactId&gt;</span>junit<span class="nt">&lt;/artifactId&gt;</span>
      <span class="nt">&lt;version&gt;</span>3.8.1<span class="nt">&lt;/version&gt;</span>
      <span class="nt">&lt;scope&gt;</span>test<span class="nt">&lt;/scope&gt;</span>
    <span class="nt">&lt;/dependency&gt;</span>
  <span class="nt">&lt;/dependencies&gt;</span>
<span class="nt">&lt;/project&gt;</span>
</code></pre></div></div>

<p>De este código hay trozos que podemos intuir bastante bien con lo mencionado anteriormente. Del resto, el tag de <strong>properties</strong> indicará las propiedades de nuestro proyecto. Por ejemplo la codificación de los ficheros en <strong>UTF-8</strong> como vemos en esa línea.
Y luego tenemos dependencies, que es la sección donde gestionaremos… ¿adivinas qué? Exacto, nuestras <strong>dependencias</strong>. Pero eso lo retomaremos más adelante.</p>

<p>De momento lo que tenemos que conseguir es que <strong>Maven</strong> se encargue por nosotros de gestionar el JRE. Esto se hace incluyendo un nuevo plugin en este archivo. Así que nos ponemos debajo de <strong>&lt; dependencies &gt;</strong> y escribimos lo siguiente:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;build&gt;</span>
   <span class="nt">&lt;pluginManagement&gt;</span>
    <span class="nt">&lt;plugins&gt;</span>
     <span class="nt">&lt;plugin&gt;</span>
      <span class="nt">&lt;groupId&gt;</span>org.apache.maven.plugins<span class="nt">&lt;/groupId&gt;</span>
      <span class="nt">&lt;artifactId&gt;</span>maven-compiler-plugin<span class="nt">&lt;/artifactId&gt;</span>
      <span class="nt">&lt;configuration&gt;</span>
       <span class="nt">&lt;source&gt;</span>1.8<span class="nt">&lt;/source&gt;</span>
       <span class="nt">&lt;target&gt;</span>1.8<span class="nt">&lt;/target&gt;</span>
      <span class="nt">&lt;/configuration&gt;</span>
     <span class="nt">&lt;/plugin&gt;</span>
    <span class="nt">&lt;/plugins&gt;</span>
   <span class="nt">&lt;/pluginManagement&gt;</span>
  <span class="nt">&lt;/build&gt;</span>
</code></pre></div></div>

<p>¿Qué hemos hecho?
Dentro de <strong>build</strong> hemos creado la etiqueta <strong>pluginManagement</strong> para gestionar los <strong>plugins</strong> de <strong>Maven</strong>. Y dentro de eso hemos creado una llamada <strong>plugins</strong> que será la que los contendrá.
Después hemos procedido a añadir un nuevo <strong>plugin</strong>, en este caso <strong>maven-compiler-plugin</strong>. Y luego le hemos indicado, en su configuración, que el <strong>source</strong> y el <strong>target</strong> apunten a la versión que tengamos del <strong>JRE</strong> en nuestro dispositivo. En mi caso, el 1.8.</p>

<p>Ahora guardamos el fichero y no te preocupes si ves un error en el explorador de proyectos, en el siguiente paso se solucionará.
Vamos al proyecto <strong>Maven</strong> y pulsamos <em><strong>botón derecho → Maven → Update Project</strong></em>…</p>

<p><img src="/img/posts/20170728_8.png" alt="update maven project" /></p>

<p>En la ventana que se abrirá marcamos con un check nuestro proyecto dejando la siguiente configuración</p>

<p><img src="/img/posts/20170728_9.png" alt="update maven project 2" /></p>

<p>Cuando acabe el proceso de actualización veremos como desaparece el error de nuestro proyecto.</p>

<p>Hecho esto, vamos a lanzar por primera vez nuestro proyecto <strong>Maven</strong> y aprovecharemos para ver los ciclos de vida posibles que tiene.
Hacemos clic con el botón derecho sobre nuestro proyecto y vamos a <strong>Run As</strong>. Ahí nos aparecerán diversas opciones</p>

<p><img src="/img/posts/20170728_10.png" alt="run maven project" /></p>

<p>¿Qué hace cada una de ellas?</p>

<ul>
  <li><strong>Maven build</strong> → Compila el código del proyecto</li>
  <li><strong>Maven clean</strong> → Elimina todos los ficheros hechos por los builds anteriores</li>
  <li><strong>Maven generate-sources</strong> → Genera código para incluirlo en la compilación</li>
  <li><strong>Maven install</strong> → Instala los paquetes de la biblioteca en un repositorio local, compila el proyecto y lo comprueba.</li>
</ul>

<p>Así que para nuestra prueba, vamos a elegir la opción de <strong>Maven install</strong>.
Se nos mostrará una ventana de consola con el proceso actual de dicha acción.</p>

<p><img src="/img/posts/20170728_11.png" alt="run maven project 2" /></p>

<p>Si vemos un mensaje de <strong>BUILD SUCCESS</strong> como en la imagen de arriba significa que el proceso se ha completado con éxito.</p>

<p>Es posible que, en vez de un mensaje de éxito, veamos lo siguiente:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>No compiler is provided <span class="k">in </span>this environment. Perhaps you are running on a JRE rather than a JDK
</code></pre></div></div>

<p>Y nos esté dando un error. Esto quiere decir que tenemos mal configurada la ruta al <strong>JDK</strong> en el <strong>workspace de Eclipse</strong>.</p>

<p>Para solucionarlo hay que ir a <strong>Window → Preferences → Java → Installed JRE</strong>. Lo que debe aparecer es la versión de <strong>JDK</strong>, como en esta imagen</p>

<p><img src="/img/posts/20170728_12.png" alt="installed jre" /></p>

<p>Si en vez de eso tenemos el <strong>JRE</strong> es el motivo de que veamos ese error. Para subsanarlo pulsamos sobre <strong>Add → Standard VM → Directory</strong> y elegimos la carpeta de instalación de nuestro <strong>JDK</strong></p>

<p><img src="/img/posts/20170728_13.png" alt="installed jre 2" /></p>

<p><img src="/img/posts/20170728_14.png" alt="installed jre 3" /></p>

<p>Aplicamos los cambios, aceptamos y ya podemos repetir el proceso del <strong>Maven</strong> install habiendo corregido ese error.</p>

<h2 id="dependencias">Dependencias</h2>

<p>Para gestionar las dependencias, dentro del <strong>POM</strong> deberemos fijarnos en el tag <strong>dependencies</strong>.
Por defecto tenemos cargada la librería de junit, que nos servirá para ver un ejemplo de cómo añadir más librerías.</p>

<p>Tenemos, al igual que con los plugin, los tag de groupId y artifactId. Aparte de eso, lo que nos interesa también es el tercer tag, version, que nos permitirá indicar la versión de la librería y, en caso de tener que modificarla, bastará con cambiar ese valor y volver a hacer un install.</p>

<p>Así pues… ¿de dónde podemos conseguir las dependencias?
Bien, hay varios sitios y Google lo sabe todo, pero así más concretamente hay una página web llamada <a href="https://mvnrepository.com/">MVN Repository</a> que cuenta con un amplio abanico de dependencias organizadas por temas que es de lo mejorcito que podemos encontrar.</p>

<p>Simplemente entraremos en la dependencia que nos interese, por ejemplo el conector JDBC de MySQL, elegiremos la versión que queramos cargar en nuestro proyecto y en la parte inferior de la página nos aparecerá el código XML de Maven que deberemos copiar en el <strong>POM</strong>.</p>

<p><img src="/img/posts/20170728_15.png" alt="maven repository" /></p>

<p>De ese modo nuestro POM quedaría tal que así</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;project</span> <span class="na">xmlns=</span><span class="s">"http://maven.apache.org/POM/4.0.0"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="na">xsi:schemaLocation=</span><span class="s">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;modelVersion&gt;</span>4.0.0<span class="nt">&lt;/modelVersion&gt;</span>

  <span class="nt">&lt;groupId&gt;</span>com.programandoapasitos<span class="nt">&lt;/groupId&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>nombrePrueba<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>0.0.1-SNAPSHOT<span class="nt">&lt;/version&gt;</span>
  <span class="nt">&lt;packaging&gt;</span>jar<span class="nt">&lt;/packaging&gt;</span>

  <span class="nt">&lt;name&gt;</span>nombrePrueba<span class="nt">&lt;/name&gt;</span>
  <span class="nt">&lt;url&gt;</span>http://maven.apache.org<span class="nt">&lt;/url&gt;</span>

  <span class="nt">&lt;properties&gt;</span>
    <span class="nt">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span class="nt">&lt;/project.build.sourceEncoding&gt;</span>
  <span class="nt">&lt;/properties&gt;</span>

  <span class="nt">&lt;dependencies&gt;</span>
    <span class="nt">&lt;dependency&gt;</span>
      <span class="nt">&lt;groupId&gt;</span>junit<span class="nt">&lt;/groupId&gt;</span>
      <span class="nt">&lt;artifactId&gt;</span>junit<span class="nt">&lt;/artifactId&gt;</span>
      <span class="nt">&lt;version&gt;</span>3.8.1<span class="nt">&lt;/version&gt;</span>
      <span class="nt">&lt;scope&gt;</span>test<span class="nt">&lt;/scope&gt;</span>
    <span class="nt">&lt;/dependency&gt;</span>
    
    <span class="c">&lt;!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --&gt;</span>
    <span class="nt">&lt;dependency&gt;</span>
   <span class="nt">&lt;groupId&gt;</span>mysql<span class="nt">&lt;/groupId&gt;</span>
   <span class="nt">&lt;artifactId&gt;</span>mysql-connector-java<span class="nt">&lt;/artifactId&gt;</span>
   <span class="nt">&lt;version&gt;</span>5.1.6<span class="nt">&lt;/version&gt;</span>
    <span class="nt">&lt;/dependency&gt;</span>
  <span class="nt">&lt;/dependencies&gt;</span>
  
  <span class="nt">&lt;build&gt;</span>
   <span class="nt">&lt;pluginManagement&gt;</span>
    <span class="nt">&lt;plugins&gt;</span>
     <span class="nt">&lt;plugin&gt;</span>
      <span class="nt">&lt;groupId&gt;</span>org.apache.maven.plugins<span class="nt">&lt;/groupId&gt;</span>
      <span class="nt">&lt;artifactId&gt;</span>maven-compiler-plugin<span class="nt">&lt;/artifactId&gt;</span>
      <span class="nt">&lt;configuration&gt;</span>
       <span class="nt">&lt;source&gt;</span>1.8<span class="nt">&lt;/source&gt;</span>
       <span class="nt">&lt;target&gt;</span>1.8<span class="nt">&lt;/target&gt;</span>
      <span class="nt">&lt;/configuration&gt;</span>
     <span class="nt">&lt;/plugin&gt;</span>
    <span class="nt">&lt;/plugins&gt;</span>
   <span class="nt">&lt;/pluginManagement&gt;</span>
  <span class="nt">&lt;/build&gt;</span>
<span class="nt">&lt;/project&gt;</span>
</code></pre></div></div>

<p>Y después de hacer un <strong>Maven install</strong> ya estaremos en disposición de usar nuestra nueva dependencia.</p>

<p>Hasta aquí mi pequeño tutorial para empezar a desenvolverte en Maven. Sin duda hay muchísima más chicha que aprender, por eso te recomiendo que para profundizar mucho más en el tema visites los siguientes enlaces</p>

<ul>
  <li><a href="http://www.java2s.com/Tutorials/Java/Maven_Tutorial/index.htm">Java2S Maven Tutorial</a></li>
  <li><a href="https://maven.apache.org/pom.html">Apache Maven POM</a></li>
</ul>

<p><strong>¡Salud y coding!</strong></p>]]></content><author><name>Inazio Claver</name></author><category term="Java" /><category term="java" /><category term="maven" /><category term="eclipse" /><category term="pom" /><category term="dependencias" /><category term="plugins" /><category term="arquetipos" /><category term="jdk" /><summary type="html"><![CDATA[Aprende a usar Maven en Eclipse desde cero paso a paso. Tutorial completo sobre creación de proyectos, configuración del POM.xml, gestión de dependencias, plugins, arquetipos y solución de errores JDK/JRE con ejemplos prácticos.]]></summary></entry></feed>