Todavía nos quedará tiempo para usar Java 9 Modules ya que acaban de llegar. ¿Pero qué son y para que sirven los Java 9 Modules?. Hasta hoy en día Java ha organizado sus clases a través del concepto de paquetes que es un concepto puramente lógico. Un conjunto de clases pertenecen a un paquete determinado. Hasta aquí todo correcto . A nivel fisico varios packages son ubicados en un JAR o Java Archive.
Esto ha terminado siendo un poco pobre ya que es necesario tener más de organización y modularidad a la hora de trabajar con grupos de clases y sus dependencias. Por ejemplo clases de un mismo paquete podrían estar ubicadas en dos JARs diferentes.
No solo eso sino que algunos de los ficheros JAR a nivel de Java incluyen cientos de packages. Por lo tanto estamos ante una situación que se acerca bastante al concepto de monolito (una única pieza). Este es el caso mítico del rt.jar que agrupa a todas las clases core de Java y sus packages.
Otro de los problemas que siempre han existido es como gestionar las dependencias entre un JAR y otro con los packages que están asociados. Maven siempre ha ayudado a ello , pero es cierto que es un herramienta aparte , no algo propio del lenguaje.
Java 9 Modules
Para solventar todos estos problemas Java 9 utiliza el concepto de módulo, algo que existe en otras plataformas como Node. Un módulo es un conjunto de clases que pueden contener uno o varios packages y que define las dependencias con el resto de módulos así como la visibilidad de las clases que contiene.
Ejemplo de Java 9 Modules
Vamos a construir un proyecto en Eclipse en el cual veamos un ejemplo sencillo de los módulos. Para ello nos vamos a construir un Utility Project .Recordemos que un proyecto de utilidades define una librería o JAR. En este proyecto vamos a incluir tres ficheros (Factura, Utilidades y module-info).
package com.arquitecturajava.core; import com.arquitecturajava.utils.UtilidadIVA; public class Factura { private int numero; private String concepto; private double importe; public int getNumero() { return numero; } public void setNumero(int numero) { this.numero = numero; } public String getConcepto() { return concepto; } public void setConcepto(String concepto) { this.concepto = concepto; } public double getImporte() { return importe; } public void setImporte(double importe) { this.importe = importe; } public double getImporteIVA() { return UtilidadIVA.calcularIVA(this.importe); } }
package com.arquitecturajava.utils; public class UtilidadIVA { public static double calcularIVA(double importe) { return importe *1.21; } }
En este caso tenemos dos clases Java relacionadas ubicadas en diferentes packages (core y utils) .
Vamos a ver que información contiene el fichero que se encarga de la gestión de módulos.
module ModuloA { exports com.arquitecturajava.core; }
Es aquí donde podemos ver cual es la estructura de nuestro módulo.
Es un módulo que no tiene dependencias pero que como peculiaridad no exporta todos los packages. Únicamente se exporta el package core que es el que contiene la clase Factura. Es momento de usar nuestra librería en otro proyecto Java que tenga un fichero main.
package com.arquitecturajava; import com.arquitecturajava.core.Factura; import com.arquitecturajava.utils.UtilidadIVA; public class Principal { public static void main(String[] args) { Factura f= new Factura(); f.setImporte(200); System.out.println(f.getImporteIVA()); UtilidadIVA } }
Java 9 y acceso
En principio el código parece correcto pero si lo miramos en Eclipse nos mostrará lo siguiente:
El código no funciona porque no podemos hacer uso de la clase UtilidadIVA ya que se encuentra en un package que el módulo no publica. Para poder utilizar el otro package hemos tenido que añadir a nuestro proyecto main la dependencia del módulo.
Aún así no podemos acceder a UtilidadIVA ya que lo hemos cerrado explicitamente. Acabamos de construir nuestro primer ejemplo de Java 9 Modules.
Java 9 Modules Export
Es ahora cuando podemos replantearnos si la encapsulación que hemos hecho de nuestros packages es la más correcta. En este caso es evidente que no. El calculo del IVA es una operación que puede ser usada por otras librerías o por el programa principal. Por lo tanto podemos modificar nuestro módulo y publicarla.
module ModuloA { exports com.arquitecturajava.core; exports com.arquitecturajava.utils; }
De esta forma ya podremos utilizar el código del calculo del IVA en un programa principal.
package com.arquitecturajava; import com.arquitecturajava.core.Factura; import com.arquitecturajava.utils.UtilidadIVA; public class Principal { public static void main(String[] args) { Factura f= new Factura(); f.setImporte(200); System.out.println(f.getImporteIVA()); System.out.println(UtilidadIVA.calcularIVA(100)); } }
El programa ya compila correctamente y si le ejecutamos nos devuelve los IVAs.
Esta tecnología es nueva pero afectará de forma importante a todas las aplicaciones en el futuro.
- Java 9 Collections y sus novedades
- Java Stream Sum y Business Objects
- Java 8 interface static methods y reutilizacion
- Java Modules
Hola Cecilio, primero gracias por todo tu aporte en cursos y artículos.
Este ejemplo en particular no me acaba de convencer, ni de funcionar y quería mostrarte una actualización donde creo que puede quedar más claro.
Saludos.
Hola Cecilio, gracias por tu esfuerzo, a la hora de poner un pie en el agua con temas nuevos siempre visito tu sitio. Reproduje lo que hiciste, pero me paso que pese a no haber exportado el paquete utils, el proyecto que usa el módulo fue capaz de accederlo sin problemas. Con lo cual no me quedo muy clara la funcion del descriptor del modulo.
Ya no me acuerdo de cuando escribí el artículo , pero date cuenta que los módulos estan orientados a mejorar la encapsulación , alguna cosa se te ha podido olvidar?? al usarlos más que al crearlos
Hola Cecilio, gracias por tus aportes. Si tengo un proyecto con dos módulos, A y B, ambos con un paquete de entidades y otro de controladores. Si hago la dependencia de A hacia B.
Mi pregunta es: Si desde el módulo A tengo acceso a las entidades del módulo B entonces desde el módulo B también tengo acceso a las entidades del módulo A?.
En principio no salvo que las hayas exportado pero no he revisado estos temas en java todavía a superdetalle
Hola, creo que la modularizacion en java particularmente va a fracazar en cuanto que va a ser dificil su adopcion por los desarrolladores. En primer lugar es un tanto engoroso y no brinda mas soluciones que lo que venimos haciendo con maven o gradle hace tiempo.
Seria muy puntuales las situaciones donde realmente le sacariamos provecho, serian cuando necesitemos una solucion autocontenida destinada mas que nada a microdispositivos.
Yo no lo veo así :), creo que era necesario adquirir esa funcionalidad por parte de Java . Es evidente que vamos a soluciones cada día más modulares y aunque maven será imprescindible en estos aspectos . El que el JDK pueda modular de una forma relativamente sencilla será un punto positivo
Hola cecilio, agradable introducción al respecto de java 9… solo me queda una duda, anteriormente en java 8 tu podías generar una aplicación en un jar el cual tenía sus lib y por medio del classpath al ejecutar el jar principal automáticamente este ya tomaba las dependencias necesarias para que el programa se ejecutará? en este caso como se aplica es decir hay forma de generar dicho jar y donde se deben colocar los modulos o como funciona esta parte? ojalá me puedas orientar ya que ando un poco perdido en esa parte.
Gracias y excelente día.
Abordaré en las próximas semanas más artículos sobre los modulos 🙂
Hola Cecilio, soy seguidor de tus publicaciones, agradezco el esfuerzo que haces por compartir tus conocimientos, pero en este tema en particular tengo la sensación que el post no fue de utilidad debido a que queda inconcluso su funcionamiento.
Hola Miguel , pues tienes razón ha quedado un poco corto. Le acabo de añadir un poco más de contenido para aclarar las cosas y más adelante escribiré artículos adicionales sobre el tema :). Gracias por el aporte 😉