domingo, 1 de abril de 2018

Eliminar la contraseña de un archivo pdf en línea

¿Conoces la contraseña de un archivo pdf y quieres eliminarla para compartirlo con otras personas?

Hace poco estuve probando diferentes herramientas para crear aplicaciones web usando Java, Javascript, Knockout.js asi como una biblioteca para la manipulación de archivos pdf que finalmente pude poner en línea en mi propio dominio.
Esto ha sido una gran experiencia para mí ya que finalmente tengo un dominio con una aplicación que hace algo de utilidad.
La aplicación se encuentra desplegada en esta dirección:
Visita el siguiente link dime qué opinas.
Planeo escribir sobre todo lo que aprendí haciendo esta utilidad, también pienso ir mejorando los estilos y practicando diversas cosas que iré aprendiendo por lo que estoy abierto a escuchar cualquier comentario, queja o sugerencia.
La aplicación en sí en bastante sencilla pero resultará útil para aquellas personas que necesiten compartir un archivo pdf con otras personas y que no quieran compartir la contraseña original de dicho archivo.
Por ejemplo, al momento de solicitar algunos créditos bancarios o de autofinanciamiento nos suelen pedir estados de cuenta como comprobantes de ingresos. Pues esta aplicación podría ser útil para quitar la contraseña de un archivo y poderlo mandar por correo al asesor.
Saludos. =)


martes, 28 de febrero de 2017

Template para proyecto web usando Java, Bootstrap, Spring MVC y Oracle JET.

Si alguna vez has querido tener un proyecto web hecho con Java, Bootstrap y Spring MVC seguramente te habrás encontrado con una gran cantidad de opciones referentes a versiones, IDEs de desarrollo, base de datos, herramientas para templates, Javascript y hojas de estilo.

Si este es tu caso y tú simplemente quieres bajar código para empezar a desarrollar una página web estás de suerte. Lo único que vas a necesitar es descargar Netbeans 8 y descargar el código de un template que subí a Github.

Netbeans lo puedes descargar de aquí:
https://netbeans.org/downloads/


El código lo puedes descargar desde Github:
https://github.com/sawbona/kfe

Mi objetivo es seguir haciendo cambios al código para hacerlo cada vez más funcional así como ir agregando documentación sobre la arquitectura y herramientas que elegí para este template.

Así que si pueden descargar el proyecto (kfe-template) y quieren dar comentarios o sugerencias, todas serán bienvenidas.

Saludos!


domingo, 28 de septiembre de 2014

Patrón de diseño: Wizard (Asistente)


Hace tiempo estuve realizando un pequeño compendio para una clase de Diseño de Interfaces Digitales sobre distintos patrones utilizados durante la generación de las vistas (interfaces digitales) que se ocupan comúnmente en los sistemas. Uno de estos patrones es el patrón Wizard (Asistente). 

Las siguientes líneas describen de forma resumida qué hacer con el patrón, cuándo se usa, cómo se utiliza y pone el ejemplo de algunas páginas donde consideré que podría aplicarse este patrón de diseño.



¿Qué hacer?

El objetivo de este patrón es guiar al usuario paso a paso por medio de la interfaz gráfica para realizar tareas en un orden prescrito.

Un ejemplo claro sería la instalación básica de aplicaciones de Windows donde al usuario se le pide configurar valores de instalación por medio de pantalla establecidas en las cuales el usuario tiene la opción de verificar o cambiar ciertos valores sencillos con el objetivo de instalar un producto o aplicación en su sistema operativo.


¿Cuándo usar este patrón?

Se puede usar si está diseñando una interfaz de usuario (IU) para realizar tareas que son largas o complicadas, y que generalmente serán nuevas para los usuarios. No es recomendado utilizarlo cuando la actividad es muy frecuente o cuando el usuario requiere mucho control del proceso (como la instalación avanzada de un paquete de software). Se debe estar razonablemente seguro que el diseñador de la IU sabe más que el usuario acerca de la mejor forma de realizar la tarea que será llevada a cabo.

Las tareas que son buenas candidatas para esta aproximación generalmente tienen muchas alternativas o son largas y tediosas. Consisten en una serie de decisiones por parte del usuario que afectan las decisiones siguientes.


El punto clave consiste en que el usuario debe desear ceder parte del control de lo que está pasando. En muchos contextos esto funciona bien ya que tomar decisiones puede no ser bienvenido por personas con cierto tipo de pensamientos: “No me hagas pensar, sólo dime qué hacer después”. Piensa que te estás moviendo en un aeropuerto que no conoces, generalmente es más fácil seguir una serie de señalamientos que te dan una idea de la estructura general del aeropuerto que aprender mucho sobre cómo está diseñado el aeropuerto en sí mismo.


Sin embargo, en otros contextos esto puede ser contraproducente. Los usuarios expertos generalmente encuentran a los asistentes frustrantemente rígidos y limitados. Esto es especialmente cierto en software para procesos creativos tales como la escritura, el arte o la programación. También es cierto para usuarios que desean aprender a usar las aplicaciones de manera más profunda; Los asistentes generalmente no muestran a los usuarios las acciones que realmente se están llevando a cabo o qué partes de la aplicación cambian de acuerdo a las decisiones que el usuario ha realizado. Esto puede llegar a ser exasperante para algunos usuarios. ¡La clave de este patrón es conocer a tu usuario!


¿Por qué?

Divide y conquista. Separando la tarea en una secuencia de grupos pequeños de operaciones, cada una de los cuales puede ser manejado en un “espacio mental” discreto por el usuario se está simplificando la tarea efectivamente. Se tiene que colocar todo un camino planeado previamente que guíe al usuario a través de la tarea a realizar, para así ahorrarle al usuario el esfuerzo de entender toda la estructura de la tarea. Todo lo que necesita es dirigirse un paso a la vez confiando en que si sigue las instrucciones la tarea será realizada correctamente.

Sin embargo la propia necesidad de un asistente indica que la tarea puede ser muy complicada. Si puedes simplificar la tarea al punto donde una forma pequeña o unos cuantos clicks pueden hacer el trabajo, esa es una mejor solución. (También ten en mente que algunos asistentes se consideran un poco condescendientes en algunas culturas asiáticas, al parecer a los orientales no les gusta que se les lleve de la mano)


¿Cómo?

Tareas en trozos

Separa las operaciones que conforma a la tarea en una serie de trozos, o grupos de operaciones. Quizá sea necesario presentar estos grupos en una secuencia estricta, o no; alguna veces es valioso romper las tareas en los pasos 1, 2, 3 e incluso 4.


Una separación temática para una compra en línea puede incluir imágenes del producto seleccionado, información de la forma de pago, dirección de facturación y dirección de envío. El orden de la presentación no importa mucho porque las elecciones posteriores no dependen de las elecciones previas. Poner juntas las opciones relacionadas solo simplifica los pensamientos de las personas para el llenado de esas formas.


Puedes decidir separar las tareas en puntos de decisión de tal forma que las decisiones hachas por el usuario puedan cambiar los pasos siguientes dinámicamente. En un asistente de instalación de software, por ejemplo, el usuario puedo seleccionar instalar paquetes opcionales que requieren más decisiones, si el usuario decide no hacer una instalación personalizada, esos pasos son saltados.
Las IU dinámicas son buenas presentando tareas con flujos alternos como estos, porque el usuario nunca tiene que ver nada que no sea relevante para las decisiones que realiza.


En tales cosas la parte más difícil de diseñar este tipo de IU es obtener un balance entre el tamaño de los trozos y el número de ellos. No es muy útil tener un asistente de 2 pasos y un asistente de 15 pasos es tedioso. Por otra parte cada trozo no debe ser exageradamente largo o perderás alguno de los beneficios de este patrón.


Estructura física


Los asistente que presentan cada paso en una página separada, usualmente navegables con un botón de Siguiente y Atrás son las más obvias y bien conocidas implementaciones de este patrón. Estas no siempre son las mejores elecciones debido a que cada paso son espacios de la IU aislados que no muestran ningún contexto. Los usuarios no pueden ver que es lo que pasó antes o qué es lo que viene después. Esta no siempre es la elección correcta ya que cada paso es un espacio aislado dentro de la IU que no muestra ningún contexto, los usuarios no pueden ver que es lo que pasó antes o que es lo que viene después. Sin embargo una ventaja de tales asistentes es que se puede dedicar una página completa en cada paso que puede incluir ilustraciones y explicaciones amplias.

Si se elige hacer esto, debes permitir al usuario moverse hacia atrás y adelante a través de la secuencia completa de pasos. Ofrece un medio mediante el cual el usuario pueda regresar o reconsiderar una de sus elecciones anteriores. Adicionalmente muchas IU muestran un mapa seleccionable o una vista general de todos los pasos utilizando algunos de los beneficios de Two-Panel Selector. (En contraste con este patrón, un asistente implica un orden prescrito -aunque, en principio, sólo sea un orden sugerido- mientras que Two-Panel Selector implica acceso completamente aleatorio.)


Si por el contrario se elige mantener todos los pasos de una tarea en una sola página puedes utilizar alguno de los patrones del Capítulo 4:

  • Titled Section, con números grandes en los títulos. Este es el más útil para tareas que no tienen muchos flujos alternos y que todos los pasos pueden ser visibles al mismo tiempo.
  • Responsive Enabling, en el cual todos los pasos están presentes en la página, pero donde estos permanecen deshabilitados hasta que el usuario ha finalizado los pasos previos.
  • Responsive Disclosure, en el cual se espera para mostrar un paso en la IU hasta que el usuario ha finalizados el paso previo. Personalmente creo que esta es la forma más elegante para implementar un asistente pequeño. Es dinámico, compacto y fácil de usar.
Las buenas opciones por default son útiles sin importar la forma en que acomodes los pasos. Si el usuario está dispuesto a dejar el control del proceso en tus manos, hay muchas posibilidades que está dispuesto a que elijas opciones razonables por default de las que no está dispuesto a poner mucho cuidado tales como el directorio donde será instalado un software.


Ejemplos que hacen uso de este patrón


My Yahoo! ilustra muchas de las buenas características de un asistente actual. Usa la técnica de “lightbox” para centrar la atención en los diálogos; muestra de manera clara un Mapa de Secuencia (Capítulo 3) de los pasos que muestran al usuario que es lo que ha sucedido y los pasos que siguen, además cuenta con un botón de Cancelar en la parte superior derecha y con la tecla Escape se sale por completo del asistente. En resumen es fácil de usar, visualmente interesante.



Asistente utilizado en My Yahoo
El asistente para realizar pagos de Amazon

Podemos observar que en la parte superior existe un Mapa de Secuencia donde se indica al usuario en qué punto de la tarea se encuentra y cuáles son los pasos siguientes.



Asistente utilizado en Amazon


Ejemplo donde se podría utilizar este patrón


En las páginas de compra en línea como Gandhi o Mercado Libre existen asistentes para el proceso de compra pero no existen asistentes que muestren el funcionamiento del sistema a usuarios inexpertos que no hayan hecho uso de un servicio de compra en línea. Podría usarse un asistente para mostrar como navegar entre productos y cómo hacer todo un proceso de compra sin que el usuario tenga que comprar algo de verdad; es decir un asistente que indice claramente que el proceso es sólo para mostrar cómo funciona el sitio y que se indique que el usuario no comprará nada de verdad.


Página principal de Gandhi donde se podría implementar un asiste para realizar una compra

Página principal de Mercado Libre donde también se podría implementar un asistente

Para más información de este y más patrones pueden consultar el libro "Designing Interfaces" de Jenifer Tidwell.

Y bueno, como siempre la principal recomendación es practicar este patrón, hacer ensayo y error para ver cómo se comporta la interfaz que diseñamos. Finalmente cualquier duda o comentario son bienvenidos al blog.

Saludos y felices trazos.



jueves, 16 de diciembre de 2010

Avances en la compilación de OpenNI en Mac OS X.

Luego de la liberación de los drivers open source del Kinect de la empresa PrimeSense, estos se encontraban disponibles para Windows y Ubuntu, con esta idea en mente un programador, Diederick, inició un nuevo proyecto para portar estos drivers a Mac.

Como podemos ver en la discusión, Hiv Zendel de PrimeSense (el estudio israelí encargado del proyecto Natal) se interesó por el proyecto de Diederick e iniciaron una plática en irc. Luego de esta plática al parecer hubo avances y el día de ayer (14/dic/2010) Diederick publica en su blog algunas instrucciones para empezar a descargar el código de OpenNI y el sistema de compilación portado para probar dicho sistema de compilación en Mac.

Aquí el blog de Diederick con las instrucciones para bajar y probar el sistema de compilado hecho con cmake.

Básicamente hay que hacer lo siguiente:


  1. mkdir roxlu_openni
  2. cd roxlu_openni
  3. git clone https://github.com/roxlu/OpenNI.git .
  4. # on Mac
  5. cd Platform/Mac/Bin/Release
  6. ./build_release.sh
  7. make
  8. make install
  9. ./Sample-NiAudioSample


He estado probando a compilar el còdigo y sólo he tenido que instalar el cmake disponible aquí. Luego de instalar cmake también tuve que compilar e instalar la versión 8 de las bibliotecas de ljpeg cuyo código fuente se encuentra aquí.

Compilando la biblioteca ljpeg:

Compilar las bibliotecas ljpeg no ha sido muy complicado siguiendo las instrucciones de este blog. Básicamente consiste en bajar el código fuente, descomprimir, colocarnos a la altura de la carpeta descomprimida y ejecutar las siguientes líneas en una terminal:


cp /usr/share/libtool/config/config.sub .

cp /usr/share/libtool/config/config.guess .

./configure --enable-shared --enable-static

make
sudo make install
/usr/local/lib/libjpeg.a

sudo ranlib


Notarán que en la Mac que tengo, cambia un poco la ruta donde encontramos el config.sub y el config.guess de lo mostrado en el blog de DZones y Peter Cooper.

Una vez instalado el cmake y la biblioteca ljpeg el código de la página de Diederick compiló bien, el problema es que cuando ejecuto la línea ./Sample-NiAudioSample me lanza el siguiente mensaje de error:


   27273 [INFO] OpenNI version is 1.0.0 (Build 23)-Mac (Dec 15 2010 23:46:19)
   27354 [INFO] Log system initialized. Console: 1, File: 1, Severity: VERBOSE, Masks: ALL
   27389 [INFO] Log system initialized. Console: 1, File: 1, Severity: VERBOSE, Masks: ALL
Open failed: OpenNI library can't find any module!


Al parecer no tengo instalado un módulo con el que se pueda probar el OpenNI, la buena noticia es que el día de hoy en el mismo blog de Diederick publicó que ha terminado el port del código del SensorKinect, que espero poder probar a compilar el día de mañana.

Al parecer queda poco para poder utilizar los drivers OpenNI en Mac, mientras tanto seguiremos al pendiente.

miércoles, 15 de diciembre de 2010

Introducción a Maven 2.2.1 con Netbeans.

Introducción

Existen una amplia variedad de cosas que se pueden hacer con Maven; sin embargo su principal función es la de ser un administrador de dependencias y versiones para proyectos hechos en Java. Es decir, si en alguna ocasión te has visto en la necesidad de lidiar con proyectos relativamente grandes como lo pueden ser las aplicaciones web, te habrás dado cuenta que mientras más frameworks, jars, utilerías y demás paquetes java se utilizan para un desarrollo, el nivel de complejidad entre las dependencias crece exponencialmente hasta llegar al punto que administrar estas dependencias puede llegar a ser un verdadero problema. Más aún, si el desarrollo de una aplicación se lleva a cabo por un equipo de dos o más personas, el problema puede llegar a ser demasiado grande para ser manejado descentemente sin la ayuda de herramientas como Maven.

Apache Maven (o Maven a secas) es una de esas poderosas herramientas que cuando las ves por primera vez parecen no tener mucho sentido y esto es porque la forma en la que se configura (esto es por medio de archivos xml) la tarea de modificar, leer o introducir nuevos componentes a la configuración de Maven puede llegar a ser tortuosa, e incluso aburrida; pero no te desanimes, detrás de todo ese código xml existe una gran herramienta que con un poco de práctica se puede convertir en una buena aliada.

A pesar que existen GUI para manejar propiamente el xml requerido por Maven (por ejemplo la integrada con Eclipse o con Netbeans) la mayoría de las veces los códigos de configuración referentes a Maven que se encuentra en Internet, en su mayoría vienen en xml plano, por lo que por el momento nos evitaremos el uso de una interfaz gráfica para el manejo del archivo de configuración de Maven.

Las tareas que se pueden realizar con Maven pueden ser muy variadas: desde hacer un deploy automático en un servidor Weblogic hasta aplicar métricas a tu código, realizar estadísticas y entregar un reporte en un documento html configurado con una plantilla específicamente diseñada para tu propia empresa; todo esto por medio de plugins y más y más configuraciones de xml.

Pero antes de poder configurar a Maven para que haga todas estas cosas necesitamos hacer un pequeño proyecto de prueba para probar esta herramienta, así que entremos en materia.

Ejemplo básico

Precondición:
  • Estamos suponiendo que en este punto ya se tiene instalado el Netbeans versión 6.5 o mayor configurado con Maven.
  • Si es la primera vez que ejecutas Maven en tu computadora necesitarás tener conexión a internet ya que la primera vez que se Maven se ejecuta descarga algunos MB's de información para poder ejecutarse.
El primer paso es abrir tu Netbeans y dar click en File > New Proyect y dentro de la pantalla que aparece seleccionamos la carpeta de Maven y del lado derecho seleccionamos Maven Proyect.


En la siguiente pantalla dejamos la opción Maven Quickstart Archetype (1.0). Damos click en Next.

El siguiente paso es importante ya que debemos introducir información que identificará al nuevo proyecto que estamos construyendo. En la pantalla que aparece introducimos la siguiente información:
  • Project Name: test.maven
Aquí le decimos a NB cómo se llamará la carpeta de nuestro proyecto dentro del sistema de archivos de nuestra computadora.

  • Project Location: C:\Documents and Settings\sawbona\Mis documentos\NetBeansProjects
La carpeta dentro del sistema de archivos donde se guardará la carpeta que creamos en el punto anterior.

  • Project Folder: "NB automáticamente llena esta parte y lo hace uniendo los dos campos anteriores. Será la ruta final completa donde estará localizado nuestro proyecto"

En este punto es donde debemos de detenernos un poco para explicar cómo funciona Maven.

La forma en que Maven identifica un proyecto de manera única es mediante la unión de tres etiquetas lógicas "especiales" o cómo algunas personas he escuchado que lo llaman: meta-información. Esta información es la siguiente:

  • Nombre de la compañía que desarrolla el proyecto; o como Maven le llama "groupId"
  • Nombre del proyecto que se está desarrollando; mejor conocido como "artifactId" y finalmente...
  • Versión del proyecto; o "version" (sin asento) para Maven.
Estos son los tres trozos de información que Maven utiliza para identificar todas y cada una de las dependencias, cualquier proyecto o plugin que utilize y es en este punto donde NB nos pide que bauticemos a nuestro nuevo proyecto así que procedemos a darle un nombre.

  • Artifact Id: test.maven

En la versión de NB 6.5 y mayores este campo es tomado automáticamente del nombre que introdujimos como "Project Name", posteriormente este nombre lo podemos cambiar en el archivo de configuración de Maven; sin embargo recomiendo mantener el mismo nombre del Artifact Id con el nombre de la carpeta donde estamos guardando el proyecto, sobre todo porque cuando navegemos en el sistema de archivos vamos a poder reconocer más fácilmente qué carpeta contiene qué proyecto.

  • Group Id: sawbona.code
Aquí podrías poner el nombre del dominio de tu empresa, tu nombre o la escuela donde estudias. Este es un punto importante ya que cuando quieres agregar dependencias de otros grupos o empresar es fácil buscar en internet por el GroupId de la empresa que quieras. Para nuestro caso si alguien quisiera buscar código que nuestra empresa, grupo o nosotros mismos desarrollásemos, sería más fácil que identificaran nuestros productos por un groupId consistente y fácilmente identificable. Normalmente corresponde al dominio en internet.

  • Version: 1.0-SNAPSHOT
En el contexto de Maven, se utiliza la palabra SNAPSHOT para hablar de versiones en desarrollo y pues eso, bautizamos a nuestra aplicación de prueba como la primera versión de desarrollo.

La pantalla resultante de NB debe verse como la siguiente imagen:


Una vez introducida la esta información, damos click en el botón "Finish" tras lo cual NB creará en un directorio en nuestra computadora que contendrá dos clases y mirando dentro del explorador del NB podremos ver que el proyecto tiene la siguiente estructura.


Si nos fijamos en nuestro disco duro, NB ha creado una carpeta con la siguiente estructura:
La filosofía de la organización de Maven radica en que los proyectos hechos en Java siguen una estructura estándar dependiendo de su naturaleza (aplicación de escritorio, EJB, WAR, etc...). Es decir en nuestro caso le hemos dicho a NB que íbamos a crear un proyecto simple en Java con una clase principal que contiene un método main como punto de entrada, por lo que Maven (por medio de NB como intermediario) ha creado la carpeta de nuestro proyecto que contiene un archivo pom.xml y una carpeta src y una estructura predefinida.

Dentro de la carpeta src tenemos dos carpetas, una llamada main, que es donde colocaremos el código "funcional" de nuestra aplicación y una carpeta test que es donde deberíamos, por default, colocar el código de nuestras pruebas unitarias.

Para continuar con la prueba de nuestra aplicación volvemos a nuestro NB, abrimos el explorador de proyectos y navegamos hasta la clase App.java y la abrimos. Damos click con el botón derecho del mouse y seleccionamos "Run File".


Si es la primera vez que ejecutas Maven verás que en la salida de consola de NB (Control + 4) empiezan a aparecer líneas de texto informando que Maven está descargando información (o más formalmente "dependencias") de Internet, este proceso, dependiendo de tu  velocidad de conexión tardará de dos a diez minutos, por lo que deberás ser paciente.

Una vez que Maven ha descargado todas las dependencias necesarias para ejecutarse veras que en la salida de NB aparece la línea Hello World de nuestro proyecto de prueba.

Ya para finalizar...

Hasta este punto hemos creado, compilado e instalado una aplicación con un groupId=sawbona.code, artifactid=maven.test y version=1.0-SNAPSHOT. Para ver dónde es que vivirá nuestra aplicación abrimos nuestro sistema de archivos y en el caso de Windows abrimos la siguiente ruta:

C:\Documents and Settings\sawbona\.m2\repository\sawbona\code\test.maven\1.0-SNAPSHOT

Dentro de esta carpeta debe existir un jar llamado test.maven-1.0-SNAPSHOT.jar que corresponderá a nuestra aplicación ya empaquetada y lista para ser usada. Si nos fijamos en el nombre de este jar vemos que está conformado por el artifactId y por la versión que introdujimos en un principio. De la misma forma si nos fijamos en la ruta que estamos navegando vemos que está conformada por el groupId, donde cada punto lo trasforma a una nueva carpeta dentro del sistema de archivos, seguida por una carpeta que corresponde al artifactId y finalmente la versión de nuestro proyecto.

La otra mitad de la ruta (C:\Documents and Settings\sawbona\.m2\repository) que estamos navegando corresponde a lo que Maven llama nuestro "repositorio local" de dependencias. Cuando Maven necesita un jar para compilar un proyecto el primer lugar que analiza es su repositorio local en busca de los jars (también llamados dependencias) necesarios para compilar el proyecto en turno, estos jars (dependencias) nosotros los declaramos dentro del archivo de configuración de nuestro proyeto al cual Maven lo llama pom.xml. Por default maven primero busca en nuestro repositorio local y después va buscando en orden en diferentes repositorios ubicados en internet.

Si abrimos NB y miramos dentro de la carpeta Project Files de nuestro proyecto de prueba veremos un archivo llamado pom.xml y si miramos el contenido veremos una sección que reza así:


<modelVersion>4.0.0</modelVersion>
  <groupId>sawbona.code</groupId>
  <artifactId>test.maven</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>test.maven</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>



Cuando le dijimos a NB que creara nuestro proyecto, Maven agregó por default una dependencia a junit versión 3.8.1. Si buscamos dentro de nuestro repositorio local veremos que existe la siguiente ruta:

C:\Documents and Settings\sawbona\.m2\repository\junit\junit\3.8.1

Que es la ruta donde Maven ha descargado el jar de junit que incluirá como dependencia de nuestro proyecto y el cual aparece dentro de la carpeta de "Test Libraries" dentro del navegador de proyectos de NB.

También viendo el archivo pom.xml podemos ver que la información que introdujimos en el momento de la creación del proyecto con NB está plasmada en este archivo.

Así llegamos al punto final de esta entrada: el archivo pom.xml.

Este es el archivo principal de configuración de los proyectos hecho en y para Maven. En este archivo podemos configurar todo sobre maven: plugins, dependencias, reporteadores y una larga lista de etc. Estas modificaciones puedes ser hechas mediante un editor de texto plano como el NotePad++ o con una GUI destinada para estos propósitos. Cuando le decimos a NB que nos cree un proyecto hecho en Maven básicamente NB funciona como in termediario que manda a ejecutar unas tareas específicas de Maven (llamados plugins) para que cree un esqueleto básico (también llamado archetype) y es este el que crea la estructura básica del proyecto junto con el archivo pom.xml que hemos analizado.

Y eso es todo. Esta es mi pequeña introducción a apache Maven con Netbeans que espero que a alguna persona le sea útil.

Saludos.

    martes, 14 de diciembre de 2010

    Incursionando en un nuevo mundo.

    Como programador de aplicaciones Java desde hace más de dos años, puedo decir que la transición al mundo de los API's de Apple, la adopción de un nuevo sistema operativo (Mac OS X Snow Leopard), la experimentación en ActionScript de Flash y el poco acercamiento al lenguaje de programación Objective-C  que he podido tener, ha sido un camino lleno de sorpresas, frustraciones y mucho, pero mucho aprendizaje.

    Cuando uno viene del "armonioso" camino de Java, se piensa que normalmente la vida es sencilla. Luego de algunos años de práctica llegué a pensar que la recolección automática de basura era el pan diario de cada día en todos y cada uno de los mundos. También llegué a pensar que sólo había una forma de modelar interfaces, clases, herencia y en general que aquella cosa que nos enseñaron en la escuela que se llama programación orientada a objetos (PPO) sólo existe y vive para ser hecho con y para Java... y lo único que puedo decir de esto es "vaya ingenuo que he sido".

    Cuando se ha vivido la mayor parte del tiempo atado a un ambiente Windows y programando en Netbeans, la vida se va haciendo cada vez más sosa, parsimoniosa hasta el punto algorítmico. Eso era mi escuela, mi trabajo y hasta cierto punto lo que llegué a anhelar como mi sustento económico. Es decir, aún pienso que ser un honorable programador en Java puede ser en un futuro no muy lejano aquello que termine de llenar mi vida, pero por el momento no puedo negar que mis intereses se inclinan a aquello que siempre he querido hacer: programar videojuegos.

    Por el momento no digo que estar viviendo esta etapa como programador JavaEE no sea edificante y educativo, más bien todo lo contrario: de esta vida (que en un principio se llega a pensar que es lo máximo y que nada lo puede superar), estoy aprendiendo grandes cosas y seguramente en el futuro seguiré aprendiendo aún más.

    Es con esta convición de querer ir un paso más allá que en julio de este mismo año 2010 pude comprarme finalmente una de esas tan afamadas (¿debería pedir perdón por usar tal palabra... ^_^?) computadoras Mac y es de esta compra que todo este post viene a colasión, ya que el tener entre mis manos una linda Macbook Pro ha hecho que por fin pueda enfrentarme a todo un mundo hasta el momento desconocido para mí. Finalmente pude ir un paso más allá de las fronteras de Java y enfrentarme por primera vez a uno de los sabores de C -sí, uno de esos enemigos que durante tanto tiempo he visto como inquebrantable e indescifrable-, es decir Objective-C y poco antes de él, debí enfrentarme a un poco de ActionScript, Flash e Illustrator.

    Trataré en lo medida de lo posible de escribir de los pocos avances que vaya haciendo y de las cosas que vaya aprendiendo en el camino para que este blog sea algo más útil para mí y para los que lo puedan leer en algún momento. Por supuesto no puede quedar fuera todo aquello que he aprendido de Java y en la medida de lo posible trataré de poner cosas de Spring, EJB's y todo lo que se me vaya ocurriendo en el camino. =)

    Por ahora sólo quiero publicar una entrada nueva y dejar este pequeño post como el inicio de una nueva etapa en este espacio de tiempo que me ha tocado vivir.

    "Las grandes victorias requieren de grandes decisiones." - Neson Rocha Jr. ;)

    viernes, 27 de noviembre de 2009

    while(true)

    Ricardo says:
     y q carrera es?
    Jaap says:
     ya llevo dos años trabajando.
     Ciencias de la Computación
    Ricardo says:
     ahh va
     ponme windows 7
     porfa


    ... Sin comentarios.

    jueves, 26 de noviembre de 2009

    Configurando el acceso de un EJB a través de un Firewall en WebSphere.

    Hola les dejo una "traducción" que espero que a alguien le sirva.

    Descripción: Cando un cliente EJB (Java) se conecta a través de un firewall a un EJB que corre en un Servidor de Aplicaciones WebSphere el cliente necesita comunicarse tanto con el proceso Java "admin server" como con el proceso "application server" que es el encargado de correr el EJB.

    Si el firewall filtra el tráfico saliente entre la "caja" del Servidor de Aplicaciones WebSphere y la "caja" del cliente EJB es necesario fijar el "listener port" en el cliente EJB a un valor fijo y abrir dicho puerto en el firewall. Por default este puerto es asignado de manera aleatoria lo cual hace necesario fijarlo a un valor estático. Para hacer esto es necesario agregar la siguiente propiedad a la línea de comando de java que invoca al EJB en el cliente: "-Dcom.ibm.CORBA.ListerPort=aaaa" donde aaaa es un puerto libre mayor a 1023  en la "caja" del cliente EJB.

    Por otro lado, si el firewall filtra el tráfico saliente entre la "caja" del cliente EJB a la "caja" del Servidor de Applicaciones WebSphere es necesario abrir varios puertos "a través" del firewall. Es necesario abrir el "listener port", "bootstrap port" y el "LSD port" para el "admin server". Es necesario abrir el puerto para el "application server". Por default los "listener port" son fijados de manera aleatoria y deben ser configurados con valores estáticos los cuales tienen que ser abiertos "a través" del firewall. Para fijar el "listener port" para el "admin server" agregue la siguiente linea en el archivo /bin/admin.config "com.ibm.CORBA.ListernerPort=bbbb". Para fijar el "listener port" en el "application server" encuentre el parámetro de la línea de comandos de Java para el "application server" en la consola de administración y agregue la siguiente propiedad: "-Dcom.ibm.CORBA.ListernerPort=cccc". Por default el "bootstrap port" en el "admin server" es 900 y el puerto "LSD port" es 9000.

    Si la seguridad en el Servidor de Aplicaciones WebShpere es activada, la "caja" del Servidor de Aplicaciones WebSphere escuchar en puertos adicionales los cuales deben ser abiertos "a través" en el firewall. El "admin server" escucha "SSL y LSD SSL ports" y el "application server" escucha su propio "SSL port". Por default todos estos puertos son fijados de manera aleatorio y deben ser configurados a valores estáticos que deben ser abiertos "a través" del firewall. Para fijar los "SSL y LSD SSL ports" para el "admin server" agregue las siguiente líneas al archivo /bin/admin.config:

    "com.ibm.CORBA.SSLPort=dddd"
    "com.ibm.CORBA.LSDSSLPort=eeee"

    Para configurar el puerto SSL para el "application server" encuentre el parámetro de la línea de comandos de Java para el "application server" en la consola de administración y agregue la siguiente propiedad:

    "-Dcom.ibm.CORBA.SSLPort=ffff"
    Asegúrse que los puertos bbbb, cccc, dddd y eeee sean únicos, libres y mayores a 1024 dentro de la "caja" del Servidor de Aplicaciones WebSphere.

    lunes, 2 de noviembre de 2009

    Humor javero.

    Bueno, jajaja. Ahora después de ver en qué aplicaba el siguiente código me he reído un poco menos, pero lo cierto es que revisarlo en el Netbeans casi hace que me arranque los ojos XD.


    return false;//error de sint&aacute;sis
    

    jueves, 22 de octubre de 2009

    Implementacion de un Heap de números enteros en Java.


    /**
    * Clase para implementar un heap de numeros enteros.
    */
    public class Heap {

    /**
    * Aqui guardamos el heap.
    */
    private int[] heap;
    /**
    * Lleva la cuenta del numero de elementos en el heap.
    */
    private int numeroElementos = 0;

    /**
    * Recibe como argumento un arreglo del que extraera sus valores y los
    * copiara uno a uno en el heap usando el metodo inserta.
    * @param array El arreglo que introduciremos al heap.
    */
    public Heap(final int[] array) {
    heap = new int[array.length];
    for (int i = 0; i < array.length; i++) {
    int j = array[i];
    inserta(j);
    }
    }

    /**
    * Hace una copia del heap y lo devuelve.
    * @return Una copia de los valores del heap.
    */
    public final int[] getValue() {
    return heap.clone();
    }

    /**
    * Inserta un entero en el heap en la ultima posicion disponible y reordena
    * el heap para conservar la propiedad de orden se siga cumpliendo.
    * @param elemento El elemento a ordenar.
    */
    public final void inserta(int elemento) {
    if (numeroElementos == heap.length) {
    throw new IllegalStateException("Error, el heap esta lleno. " +
    "Elemento a insertar: " + elemento + " Heap size: " +
    numeroElementos);
    }
    // Cuando no hay elementos insertamos el elemento en la
    // primera posicion del arreglo que es la raiz del heap
    if (numeroElementos == 0) {
    heap[0] = elemento;
    numeroElementos++;
    return;
    }
    boolean esPadreMayor = false;
    // indiceHijo es el ultimo lugar del heap. Aqui es donde empezamos
    // a buscar la posicion del elemento a insertar. Posteriormente calcula
    // mos la posicion del padre de este nodo.
    int indiceHijo = numeroElementos;
    // Aqui guardamos el indice del nodo padra del nodo hijo.
    int indicePadre = 0;
    // Calculamos el indice del nodo padre.
    if (indiceHijo % 2 == 0) {
    indicePadre = (int) (Math.ceil(indiceHijo / 2)) - 1;
    } else {
    indicePadre = (int) (Math.ceil(indiceHijo / 2));
    }
    int valorPadre = heap[indicePadre];
    while (true) {
    // Terminamos cuando el padre que estamos analizando es mayor
    // que el valor del hijo actual. O cuando ya llegamos a la raiz
    // del arbol, que es cuando el indiceHijo == 0
    if (esPadreMayor || indiceHijo == 0) {
    break;
    }
    // Si encontramos que el valor del padre del nodo actual
    // es mayor que el valor del elemenot que estamos insertando
    // guardamos el valor del elemento en el nodo actual (indiceHijo)
    // y marcamos la variable esPadreMayor = true para en el siguiente
    // ciclo finalizar.
    if (valorPadre > elemento) {
    heap[indiceHijo] = elemento;
    esPadreMayor = true;
    continue;
    }
    // Sino se cumple ninguna de las condiciones anteriores, intercam
    // biamos el valor del nodo padre con el hijo y actualizamos
    // los indices. 'indiceHijo = indicePadre' para en la siguiente
    // iteracion repetir el mismo proceso.
    heap[indicePadre] = elemento;
    heap[indiceHijo] = valorPadre;
    indiceHijo = indicePadre;
    // Una vez calculado el nuevo indiceHijo, calculamos el nuevo
    // indicePadre.
    if (indiceHijo % 2 == 0) {
    indicePadre = (int) (Math.ceil(indiceHijo / 2)) - 1;
    } else {
    indicePadre = (int) (Math.ceil(indiceHijo / 2));
    }
    if (indicePadre >= 0) {
    valorPadre = heap[indicePadre];
    }
    }
    numeroElementos++;
    }

    /**
    * Obtiene el valor de la raiz del heap y reordena los elementos para
    * mantener la propiedad del heap.
    * @return En cada llamada obtiene el valor maximo del heap, eliminando
    * dicho elemento y reordenando el heap para que en la siguiente
    * llamada obtenga el valor maximo del heap restante.
    */
    public final int quitaRaiz() {
    if (numeroElementos == 0) {
    throw new IllegalStateException("Error, el heap esta vacio");
    }
    int resultado = heap[0];
    heap[0] = heap[--numeroElementos];
    int indiceNodo = 0;
    int indiceHijoMayor = 0;
    while (true) {
    int indiceHijoIzquierdo = indiceNodo * 2 + 1;
    int indiceHijoDerecho = indiceNodo * 2 + 2;
    if (indiceHijoIzquierdo >= numeroElementos) {
    break;
    } else {
    // Determinar cual de los dos hijos es el mayor
    if (indiceHijoDerecho >= numeroElementos) {
    indiceHijoMayor = indiceHijoIzquierdo;
    } else {
    if (heap[indiceHijoIzquierdo] > heap[indiceHijoDerecho]) {
    indiceHijoMayor = indiceHijoIzquierdo;
    } else {
    indiceHijoMayor = indiceHijoDerecho;
    }
    }
    }
    /**
    * Intercambiar los valores del indiceNodo y el indiceHijoMayor
    * si es que el valor del hijo mayor es mayor que el valor del
    * nodo actual. En caso que no sea así terminamos.
    */
    int valorHijoMayor = heap[indiceHijoMayor];
    if (valorHijoMayor > heap[indiceNodo]) {
    heap[indiceHijoMayor] = heap[indiceNodo];
    heap[indiceNodo] = valorHijoMayor;
    // Actualizar el valor del indiceNodo por indiceHijoMayor
    indiceNodo = indiceHijoMayor;
    } else {
    break;
    }
    }
    return resultado;
    }
    }

    martes, 20 de octubre de 2009

    Implementacion de Merge Sort en Java



    private int[] mergeSortImpl(int[] array) {
    // Caso base. Un arreglo de cero o un elemento ya esta ordenado,
    // asi que lo regresamos.
    if (array.length <= 1) {
    return array;
    }
    int puntoMedio = array.length / 2;
    // Creamos subarreglo izquierdo
    int[] izquierdo = new int[puntoMedio];
    for (int i = 0; i < puntoMedio; i++) {
    izquierdo[i] = array[i];
    }
    // Creamos el subarreglo derecho
    int[] derecho = new int[array.length - puntoMedio];
    for (int i = 0; i < array.length - puntoMedio; i++) {
    derecho[i] = array[puntoMedio + i];
    }
    // Ordenamos las dos mitades recursivamente
    int[] izquierdoOrdenado = mergeSortImpl(izquierdo);
    int[] derechoOrdenado = mergeSortImpl(derecho);
    //Mezclamos la solucion---
    // El indice i es para recorrer el subarreglo izquierdo
    int i = 0;
    // El indice j es para recorrer el subarreglo derecho
    int j = 0;
    // En 'resultado' guardamos el resultado de la mezcla de los dos
    // subarreglos
    int[] resultado = new int[izquierdoOrdenado.length + derechoOrdenado.length];
    /**
    * Terminamos de mezclar cuando i + j ya recorrieron todos los elementos
    * de los dos subarreglos
    */
    while (i + j < izquierdoOrdenado.length + derechoOrdenado.length) {
    // a) Si i ya llego al ultimo elemento del subarreglo izquierdo
    // copiamos el valor del siguiente elemento del subarreglo
    // derecho e incrementamos el indice j para, en el siguiente,
    // ciclo copiar el elemento de subarreglo derecho que sigue
    if (i == izquierdoOrdenado.length) {
    resultado[i + j] = derechoOrdenado[j];
    j++;
    continue;
    }
    // Lo mismo que a) pero para el subarreglo derecho
    if (j == derechoOrdenado.length) {
    resultado[i + j] = izquierdoOrdenado[i];
    i++;
    continue;
    }
    int elementoIzquierdo = izquierdoOrdenado[i];
    int elementoDerecho = derechoOrdenado[j];
    // Comparamos cual de los elementos que siguen es menor y ese
    // lo copiamos en resultado
    if (elementoIzquierdo <= elementoDerecho) {
    resultado[i + j] = elementoIzquierdo;
    i++;
    } else {
    resultado[i + j] = elementoDerecho;
    j++;
    }
    }
    return resultado;
    }

    Eliminar la contraseña de un archivo pdf en línea

    ¿Conoces la contraseña de un archivo pdf y quieres eliminarla para compartirlo con otras personas? Hace poco estuve probando diferentes h...