javaDB embebido en archivo jar ejecutable

Hace tiempo atrás revisando en que diferían JavaSE 5 y JavaSE 6, observe que el jsdk de la versión 6 incluía javaDB y me asombro el saber que Java traia consigo su propio gestor de base de datos, así que desde entonces tenia el gusanillo de trastear con el mencionado gestor y Java.

Para quien no lo sepa aun javaDB es el mismo apache Derby, un gestor de base de datos relacional «ligero» 100% Java (tiene un tamaño de 2MB).

He aquí mi primer encuentro con javaDB.

El entorno es Mac OS X snow leopard con la ultima versión de java (1.6.0_22) distribuida para este entorno de parte de Apple y como IDE Eclipse. Mi primera decepción fue el darme cuenta que la versión del jsdk distribuido por parte de Apple no trae consigo javaDB asi que procedí a descargarlo desde este enlace, por otro lado es agradable mencionar que el archivo a descargar es en formato .dmg, una vez ya relatada mi primera decepción (esperaba que mi jsdk fuera igual de completo que cualquier otro distribuido de parte de Oracle para los entornos Linux o Windows), procederé a explicarles como obtener un Jar  que traiga consigo javaDB y fuese un ejecutable a mi modo de verlo fácilmente distribuible.

Como mi idea principal consistía en probar javaDB, procedi a buscar un ejemplo en la red, lo bueno es que encontré uno casi perfecto, que cumplía casi a la perfección todo lo que quería, consiste en el ejemplo del libro de direcciones (AddressBook). Antes de continuar será necesario que descarguemos el código fuente del ejemplo y aquellos que hagan uso de un IDE importemos el código fuente en un proyecto (ver figura)

Una vez importado el código, podemos detallar que nuestro proyecto tendra una carpeta «lib» allí estará un jar de nombre derby.jar, que no es mas que nuestro javaDB en una versión vieja (si prestan atención el ejemplo data del 2006), si quisiéramos trabajar con una versión mas nueva pues sencillamente copiaríamos al proyecto el  derby.jar ubicado en la carpeta de instalación de javaDB,  además también podemos notar que el proyecto también contará con un build.xml (para quien no conozca Ant, ir al menu Windows->show view y seleccionar la vista de Ant, una vez se muestra la vista arrastrar el archivo build.xml a la vista). En la vista de Ant ejecutar la tarea «dist», la cual es la tarea por defecto. Una vez ejecutada la tarea procedemos a refrescar el proyecto (F5) y veremos que se nos ha creado una carpeta de nombre «dist» que contendrá a su vez una carpeta «lib» con la dependencia (que no es mas que nuestro derby.jar) y un fichero de nombre AddressBook.jar  que será un jar ejecutable. Si hacemos doble click sobre este fichero o sencillamente ejecutamos la tarea «run» de Ant, y podremos ver como se ejecuta nuestra aplicación y como podemos guardar, editar y eliminar registros, sencillamente fabuloso.

Pero ustedes se preguntarán ¿Si es tan fabuloso por qué no lo definí como perfecto? y la razón es la siguiente, si copiamos ese archivo ejecutable AddressBook.jar, lo pegamos por ejemplo en nuestro escrito y procedemos a ejecutarlo, se darán cuenta que no es del todo distribuible, ya que para que se ejecute perfectamente sería necesario haber copiado y pegado la carpeta «lib» con su respectivo derby.jar. A mi modo de ver las cosas no es muy elegante distribuir un «supuesto» jar ejecutable y a su vez hacerlo con una carpeta aparte con sus respectivas dependencias, incluso el embebido lo pondría en entre dicho porque nuestra aplicación no es autocontenida, es decir la aplicación por si sola no tiene todo lo que requiere (excluyendo la JVM de esos requerimientos). Así que me puse a investigar el tener todo en 1, es decir que fuese un único jar ejecutable.

El problema esta en que un jar (asumamos AddressBook.jar) al ejecutarse, por defecto no puede cargar las clases contenidas en otro jar  (asumamos derby.jar) que este dentro del primero, es decir aunque agregásemos nuestra carpeta «lib» con el derby.jar dentro de AddressBook.jar no podríamos ejecutar la aplicación ubicada en nuestro escritorio (o en cualquier otro lugar donde lo hayamos pegado), aquí les dejo un enlace del tutorial donde se menciona. ¿Que alternativa tendríamos?  una de ellas seria usar Java Web Start para la instalación y otra hacer nosotros mismos nuestro propio ClassLoader a medida, esta opción me tentó, incluso quede con el gusanillo de investigar al respecto, pero buscando por la red encontré una buena herramienta, además de no ser la única en su clase y en el one-jar, el cual consiste en un proyecto para crear un único jar ejecutable y traiga consigo (dentro) todas sus dependencias (jars).

Existen varias opciones para crear el ejecutable, mediante tarea Maven, tarea Ant e incluso por linea de comandos, he optado por la última, la cual es muy sencilla y detallo a continuación los pasos:

  1. Descargar el archivo one-jar-boot-0.97.jar
  2. Crear un directorio «root» que contenga a su vez 2 directorios mas llamados «main» y «lib».
  3. Copiar el archivo AddressBook.jar (nuestro jar ejecutable obtenido mediante Ant) dentro de la carpeta «root/main» y copiar el derby.jar en el directorio «root/lib».
  4. Descomprimir el archivo one-jar-boot-0.97.jar en el directorio «root» y eliminar la carpeta «src» donde están ubicados los fuentes del archivo recien descomprimido.
  5. Editar el archivo boot-manifest.mf y añadir una nueva linea. One-Jar-Main-Class:   com.sun.demo.addressbook.AddressFrame
  6. En linea de comandos ubicarnos en el directorio «root». >cd root
  7. En  linea de comandos >jar cvfm ../ejecutable.jar boot-manifest.mf . (no omitir el ultimo punto «.»)

Finalmente hemos obtenido nuestro ejecutable.jar, es decir una aplicación de escritorio que tiene embebido un gestor de base de datos ligero, plena y elegantemente distribuible.

Espero les sea de utilidad y cualquier duda y/o sugerencia será bien recibida.