sábado, 8 de mayo de 2010

DEFINICIONES IMPORTANTES DE CALIDAD DE SOFTWARE

Es muy importante que se conozca sobre algunas definiciones de CALIDAD DE SOFTWARE que es muy probable que escuchemos de forma muy seguida. Aquí las enumero:

I.- APLICACIONES DISTRIBUIDAS:
Las aplicaciones distribuidas son aplicaciones que están diseñadas como aplicaciones de n niveles. La arquitectura de estas aplicaciones distribuidas favorece el diseño de aplicaciones escalables compartiendo recursos, como bases de datos y componentes empresariales

2.- ESCALABILIDAD:
La escalabilidad de una aplicación requiere una pertenencia equilibrada entre dos dominios distintos, software y hardware.
Para que un sistema sea escalable tiene que cumplir tres condiciones para ajustarse a los cambios:

- Tiene que poder adaptarse a un incremento en el número de usuarios.
- Tiene que poder adaptarse a un incremento en el tamaño de los datos que maneja.
- Tiene que ser mantenible.

Cuanto más fácil sea cumplir estas tres condiciones, más escalable será el sistema. La escalabilidad no es lo mismo que el rendimiento del sistema (performance). Lescalabilidad depende más del diseño de la aplicación que de las tecnologías usadas para implementarla.

La escalabilidad puede avanzar grandes pasos que aumenten la escalabilidad de un dominio sólo para sabotearlos cometiendo errores en el otro. Por ejemplo, la creación de un grupo de servidores Web con equilibrio de carga no beneficiará una aplicación Web que se ha diseñado para ejecutarse un solo equipo. De igual modo, el diseño de una aplicación altamente escalable y su implementación en equipos conectados a una red con poco ancho de bada no controlará bien las cargas pesadas cuando se sature el tráfico en la red.

2.1.- ESCALAR EN VERTICAL:
El escalado en vertical es el término que más se utiliza para lograr escalabilidad utilizando software mejor, más rápido y más caro. El escalado incluye agregar más memoria, más procesadores o procesadores más rápidos o, simplemente, migrar la aplicación a un único equipo más potente. Normalmente, este método permite un aumento en la capacidad sin requerir cambios en el código fuente. Desde el punto de vista administrativo, las cosas permanecen igual puesto que sigue habiendo un único equipo que administrar.

Actualizar un componente de hardware en un equipo sólo mueve el limite de capacidad de procesamiento de un lado a otro. Por ejemplo, una máquina que está al 100 % de uso de la CPU podría mejorar su capacidad agregando otra CPU. Sin embargo, la limitación puede pasar de la CPU a la memoria del sistema. Agregar CPU no aporta rendimiento en un modelo lineal. En su lugar, el rendimiento va disminuyendo cada vez que se agrega un procesador adicional. Para equipos con configuraciones de varios procesadores simétricos (SMP), cada procesador adicional produce una sobrecarga del sistema. Por tanto, un equipo con cuatro procesadores no obtendrá una mejora del 400% en capacidad sobre una versión con un único procesador. Una vez que haya actualizado todos los componentes de hardware al máximo de su capacidad, llegará el momento en que alcance el límite real de la capacidad de procesamiento del equipo. Llegado ese punto, el siguiente paso es escalar en vertical para moverse a otro equipo.


Escalar en vertical conlleva también otros posibles problemas. El uso de un único equipo en el que basar una aplicación crea un único punto de error, lo que disminuye enormemente la tolerancia de errores del sistema. Si bien algunos métodos, como varias fuentes de alimentación, pueden implementar redundancia en un sistema de un único equipo, pueden resultar costosas.

2.2.- ESCALAR EN HORIZONTAL:
Una alternativa a escalar en vertical es escalar en horizontal. Escalar en horizontal aprovecha el ahorro que supone utilizar el hardware de PC activo para distribuir la carga de procesamiento en más de un servidor. Aunque el escalado en horizontal se logra utilizando muchos equipos, la colección funciona esencialmente como un único equipo. Al dedicar varios equipos a una tarea común, mejora la tolerancia de errores de la aplicación. Por supuesto, desde el punto de vista del administrador, escalar en horizontal presenta un desafío mayor de administración debido al mayor número de equipos.

Los desarrolladores y administradores utilizan una gran variedad de técnicas de equilibrio de carga para escalar en horizontal con la plataforma Windows. El equilibrio de carga permite escalar un sitio en horizontal a través de un clúster de servidores, facilitando la adición de capacidad agregando más servidores duplicados. También proporciona redundancia, concediendo al sitio capacidad de recuperación de conmutación por error, de manera que permanece disponible para los usuarios incluso si uno o más servidores fallan (o si es preciso retirarlos del servicio para realizar labores de mantenimiento). El escalado en horizontal proporciona un método de escalabilidad que no se ve mermado por limitaciones de hardware. Cada servidor adicional proporciona una mejora casi lineal de la escalabilidad.
La clave para escalar horizontalmente una aplicación con éxito es la transparencia de ubicación. Si alguna parte del código de la aplicación depende de saber qué servidor está ejecutando el código, no se ha logrado la transparencia de ubicación y será difícil el escalado en horizontal. Esta situación se denomina afinidad de ubicación. La afinidad de ubicación requiere cambios de código para escalar una aplicación en horizontal de un servidor a varios, lo que, en pocas ocasiones, constituye una opción económica. Si diseña la aplicación con transparencia de ubicación en mente, resulta más fácil escalarla en horizontal.


3.- ROBUSTEZ:
Es la capacidad de los productos software de reaccionar apropiadamente ante condiciones excepcionales.
En implementación se cuenta con el mecanismo de excepciones el cual garantiza el correcto flujo de ejecución del código. (Programación por contrato)
Cuando se culmina un software de alta calidad, se presentarán casos o aspectos que no contemplarás y la robustez asegura que no se causarán eventos de índole grave o catastrófica. En detalles técnicos si se presenta errores en tu software, la robustez hará un despliegue de mensajes de error apropiados, en donde se pueda terminar la aplicación de manera limpia y segura para los datos.

4.- PORTABILIDAD:
Es la facilidad con que un sistema software puede ser migrado entre diferentes plataformas hardware o software.

5.- INTEGRIDAD:
Es la característica de un sistema de ser capaz de proteger sus diferentes componentes contra los procesos o elementos que no tengan derecho de acceso a los mismos. La integridad es un factor muy importante en sistemas contables , administrativos y gerenciales ya que de ellos depende el capital de la empresa

6.- COMPATIBILIDAD:
Es la facilidad de combinar diferentes elementos software con el fin de ejecutar una labor en conjunto.

7.- ALTA DISPONIBILIDAD:
Se refiere a la habilidad de la comunidad de para acceder al sistema, consiste en una serie de medidas tendientes a garantizar la disponibilidad del servicio, es decir, asegurar que el servicio funcione durante las veinticuatro horas.

8.- FRONT-END:
Es la parte del que interactúa con el o los usuarios.

9.- BACH-END:
Es la parte que procesa la entrada desde el front-end hasta back-end hace referencia al estado final de un proceso. Contrasta con front-end, que se refiere al estado inicial de un proceso

10.- FAT CLIENT o (Thin Server):
Es el aprovechamiento de datos, donde el cliente ha sido dotado de "inteligencia" y realiza muchos procesamientos locales.
En este esquema de arquitectura el grueso de la aplicación es ejecutada en el cliente, es decir, el nivel de presentación y el nivel de aplicación corren en un único proceso cliente, y el servidor es relegado a realizar las funciones que provee un administrador de base de datos.

11.- THIN CLIENT (Fat Server):
Este es el caso opuesto al anterior, el proceso cliente es restringido a la presentación de la interfaz de usuario, mientras que el grueso de la aplicación corre por el lado del servidor de aplicación. Aquí se posee poco procesamiento local, son más débiles y por supuesto, fáciles de manejar o administrar. La cantidad de datos requeridos por un cliente fat es constante mientras que un cliente más delgado típicamente requerirá de un servidor mayor con mayor capacidad de procesamiento y administración.

miércoles, 5 de mayo de 2010

MANEJO 'IBM WebSphere MQ' EN JAVA

Que tal compañeros el dia de hoy hablaré sobre un tema relacionado a la integración de aplicaciones empresariales. WebSphere MQ (anteriormente MQSeries) que es un modo de transmisión de data via colas MQ, para la integración de aplicaciones empresariales. El envio de datos a traves de MQ muy popular ya que es más rápido que si se trabajara vía el protocolo SOAP o via ficheros.

I.- Características de WebSphere MQ:

* Admite cualquier tipo de conectividad heterogénea, desde equipos de escritorio hasta macrocomputadoras (admite una gran variedad de plataformas distintas).
* Dispone de una extensa familia de interfaces de programación de aplicaciones (API) diseñados con el objeto de facilitar la creación de código para tareas de mensajería.
* Garantiza la entrega sin duplicaciones de los mensajes importantes.
* Permite un mapeo de objetos via ficheros .cpy, xsd y direntes transformaciones de mensajes (Formatos).
* Proporciona conectividad de aplicaciones. Puede utilizarse de forma autónoma o con otros miembros de la familia para ofrecer una solución de integraciones de negocio global.

II.- Sistemas Operativos y Plataformas de Hardware Apropiadas.

* AIX
* HP OpenVMS (Alpha)
* HP-UX
* iSeries i5/OS V5R3
* iSeries OS/400 V5R2
* Linux
* Linux for iSeries
* Linux for pSeries POWER
* Sun Solaris
* Windows 2000
* Windows NT
* Windows XP

III.- Ejemplo Aplicativo:

Ahora si mostraré una forma de trabajar con de WebSphere MQ en JAVA. Para ello se tiene que tener en cuenta y configurar previamente Las colas MQ que serviran para la transmisión. Estos son los datos que se tendra que configura antes que nada:

- QManager
- colaIN
- colaOUT
- canal
- servidor
- puerto
- id
- password
- messageId

Luego ya configurado y definido se registrará en un archivo .properties que será nuestro archivo de configuración del ejemplo a mostrar.

#####################################################################
################ PROPIEDADES DE PARA ACCESO DE DATOS ################
#####################################################################

#### EL DELIMITADOR DE ACCESO PUEDE SER CON LA SIMBOLOGIA => ':', '=', 'BLANCO' ####

##--------- CONFIGURACION: 'LOCAL MESSAGE BROKER' ---------##
propiedad.MQ.QManager = WBRK61_DEFAULT_QUEUE_MANAGER
propiedad.MQ.colaIN = MQ.A
propiedad.MQ.colaOUT = MQ.B
propiedad.MQ.canal = SYSTEM.BKR.CONFIG
propiedad.MQ.servidor = localhost
propiedad.MQ.puerto = 2414
propiedad.MQ.id = MQSIUSER
propiedad.MQ.password = MQSIPASS
propiedad.MQ.messageId = JAVAMAN00000000000000000


Se debe analizar como se van a manejar las colas MQ, ya que si son utilizados un solo 2 aplicaciones (La aplicación que hace PUT y la que hace GET a la trama) y si van a haber muchas aplicaciones que dejen en una misma cola diferentes Tramas MQ. Para el primer caso bastaría con el manejo de la ultima trama que se deja en cola ya que un aplicatibo lo dejara y otro lo leera en ese mismo instante, pero si se está en un escenario como el 2do se necesita el manejo de messageId y correlationId para poder manejar la identificación y deferenciación de cada Trama qye se deposita en una misma cola MQ.

Los ejemplos preparados soportan todo esto anteriormente mencionado.

Clase 'PruebaEnviarMQ':

package org.java.mq;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;

/**
* @author: cguerraa.
* @clase: PruebaEnviaMQ.java
* @descripción: descripción de la clase.
* @author_web: http://frameworksjava2008.blogspot.com - http://viviendoconjavaynomoririntentandolo.blogspot.com
* @author_email: cesarricardo_guerra19@hotmail.com.
* @author_company: nombre de la compañía del autor.
* @fecha_de_creación: dd-mm-yyyy.
* @fecha_de_ultima_actualización: dd-mm-yyyy.
* @versión: 1.0
*/
public class PruebaEnviarMQ{

private static final String ARCHIVO_CONFIGURACION = "ConfiguracionMQ.properties";
private static final String SOURCE_FORDER = "src/";

private static String TRAMA_INPUT = "MENSAJE GUARDADO DE FORMA DIRECTA VIA APLICATIVO JAVA - MQ ...!!!...ENVIO: OPCION CLASE JAVA.";

private Properties objProperties = null;
private MQQueueManager objQueueManager = null;
private ManejoErroresMQ manejoErroresMQ = null;
private ObjetoMQ objetoMQ = null;

{
this.objProperties = this.getObjetoProperties();
this.manejoErroresMQ = new ManejoErroresMQ();
this.objetoMQ = new ObjetoMQ();
}

//Constructores ...
public PruebaEnviarMQ(){
}

public PruebaEnviarMQ( String tramaParam ){
super();
TRAMA_INPUT = tramaParam;
}

public PruebaEnviarMQ( String nombreQManager, String colaInParam, String colaOutParam,
String canalParam, String servidorParam, String puertoParam,
String idParam, String passwordParam ){
super();
this.objetoMQ.setNombreQManager( nombreQManager );
this.objetoMQ.setColaInParam( colaInParam );
this.objetoMQ.setColaOutParam( colaOutParam );
this.objetoMQ.setCanalParam( canalParam );
this.objetoMQ.setServidorParam( servidorParam );
this.objetoMQ.setPuertoParam( puertoParam );
this.objetoMQ.setIdParam( idParam );
this.objetoMQ.setPasswordParam( passwordParam );
}

/**
* main
* @param argumentos
*/
public static void main( String[] argumentos ){
PruebaEnviarMQ conexionMQ = new PruebaEnviarMQ();
conexionMQ.enviarMensajeMQ();
}

/**
* cargarConfiguracionMQ
*/
public void cargarConfiguracionMQ(){

//Inicializando Paramentos ...
this.objetoMQ.setMensajeTramaMQ( TRAMA_INPUT );
this.objetoMQ.setTiempoInicioMQ( Long.toString( ( new java.util.Date() ).getTime() ) );
this.objetoMQ.setCorrelationIdMQ( this.objetoMQ.getTiempoInicioMQ() + new java.util.Date().getTime() );
this.objetoMQ.setNombreQManager( this.objProperties.getProperty( "propiedad.MQ.QManager" ).trim() );
this.objetoMQ.setColaInParam( this.objProperties.getProperty( "propiedad.MQ.colaIN" ).trim() );
this.objetoMQ.setColaOutParam( this.objProperties.getProperty( "propiedad.MQ.colaOUT" ).trim() );
this.objetoMQ.setCanalParam( this.objProperties.getProperty( "propiedad.MQ.canal" ).trim() );
this.objetoMQ.setServidorParam( this.objProperties.getProperty( "propiedad.MQ.servidor" ).trim() );
this.objetoMQ.setPuertoParam( this.objProperties.getProperty( "propiedad.MQ.puerto" ).trim() );
this.objetoMQ.setIdParam( this.objProperties.getProperty( "propiedad.MQ.id" ).trim() );
this.objetoMQ.setPasswordParam( this.objProperties.getProperty( "propiedad.MQ.password" ).trim() );
this.objetoMQ.setMessageIdParam( this.objProperties.getProperty( "propiedad.MQ.messageId" ).trim().getBytes() );

//Imprimiendo Datos MQ.
this.imprimeDatosMQ();

MQEnvironment.channel = this.objetoMQ.getCanalParam();
MQEnvironment.hostname = this.objetoMQ.getServidorParam();
MQEnvironment.port = Integer.parseInt( this.objetoMQ.getPuertoParam() );
MQEnvironment.userID = this.objetoMQ.getIdParam(); //Normalmente el mismo 'ID' del dominio.
MQEnvironment.password = this.objetoMQ.getPasswordParam(); //Normalmente el mismo 'PASSWORD' del dominio.

MQEnvironment.disableTracing();
}

/**
* enviarMensajeMQ
*/
public void enviarMensajeMQ(){

try{
this.cargarConfiguracionMQ();

System.out.println( "TRAMA ENVIADA [PUT]: " + this.objetoMQ.getMensajeTramaMQ() );

this.objQueueManager = new MQQueueManager( this.objetoMQ.getNombreQManager() );

//Configurar las opciones en la cola que se va a abrir...
//Todas las opciones de WebSphere MQ tienen el prefijo MQC en Java.
int opcionesInputMQ = MQC.MQOO_OUTPUT; //MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT;

//--------- Especificar las opciones de mensaje para ESCRIBIR (PUT). ---------------------------------------//
MQQueue objColaOUT = this.objQueueManager.accessQueue( this.objetoMQ.getColaInParam(), opcionesInputMQ, null, null, null );
MQPutMessageOptions opcionesPUT = new MQPutMessageOptions();
MQMessage mensajeOUT = new MQMessage(); //Definir un mensaje WebSphere MQ simple y escribir texto en formato UTF...

mensajeOUT.writeUTF( this.objetoMQ.getMensajeTramaMQ() );

mensajeOUT.messageId = mensajeOUT.messageId; //this.messageIdParam;
//mensajeOUT.correlationId = mensajeOUT.correlationId; //this.correlationIdMQ.getBytes();
mensajeOUT.format = MQC.MQFMT_STRING; //Formato que consiste en Solo Caracteres enviados.

//Escribe el mensaje en la cola MQ.
objColaOUT.put( mensajeOUT, opcionesPUT );

//Cerrando Colas MQ.
objColaOUT.close();

//Desconectar del gestor de colas
this.objQueueManager.disconnect();
}
catch( MQException e ){
int codigoTermino = e.completionCode ;
int codigoRazon = e.reasonCode ;

this.manejoErroresMQ.validaErrorMQ( codigoTermino, codigoRazon );
System.exit( 0 );
}
catch( IOException e ){
System.out.println( "SE HA PRODUCIDO UN ERROR DE TIPO 'IOException': " + e );
System.exit( 0 );
}
finally{
}
}

/**
* getObjetoProperties
* @return Properties
*/
public Properties getObjetoProperties(){

String rutaFichero = null;
Properties accesoFichero = null;
FileInputStream streamInput = null;

try{
rutaFichero = SOURCE_FORDER + ARCHIVO_CONFIGURACION; //DESDE ECLIPSE.
//rutaFichero = "ARCHIVO_CONFIGURACION"; //DESDE UNIX.

accesoFichero = new Properties();
streamInput = new FileInputStream( rutaFichero );

//Carga Fichero.
accesoFichero.load( streamInput );
}
catch( IOException e ){
e.printStackTrace();
}

return accesoFichero;
}

/**
* imprimeDatosMQ
*/
public void imprimeDatosMQ(){
System.out.println( "" );
System.out.println( "*************** PARAMETROS DE CONFIGURACION ***************" );
System.out.println( "- QMANAGER: " + this.objetoMQ.getNombreQManager() );
System.out.println( "- COLA IN: " + this.objetoMQ.getColaInParam() );
System.out.println( "- COLA OUT: " + this.objetoMQ.getColaOutParam() );
System.out.println( "- CANAL: " + this.objetoMQ.getCanalParam() );
System.out.println( "- SERVIDOR: " + this.objetoMQ.getServidorParam() );
System.out.println( "- PUERTO: " + this.objetoMQ.getPuertoParam() );
System.out.println( "- ID: " + this.objetoMQ.getIdParam() );
System.out.println( "- PASSWORD: " + this.objetoMQ.getPasswordParam() );
System.out.println( "- MESSAGE ID: " + this.objetoMQ.getMessageIdParam() );
System.out.println( "- CORRELATION ID: " + this.objetoMQ.getCorrelationIdMQ() );
System.out.println( "***********************************************************" );
System.out.println( "" );
}
}

Clase 'PruebaObtieneMQ':

package org.java.mq;

import java.io.IOException;
import java.io.FileInputStream;
import java.util.Properties;
import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;

/**
* @author: cguerraa.
* @clase: PruebaObtieneMQ.java
* @descripción: descripción de la clase.
* @author_web: http://frameworksjava2008.blogspot.com - http://viviendoconjavaynomoririntentandolo.blogspot.com
* @author_email: cesarricardo_guerra19@hotmail.com.
* @author_company: nombre de la compañía del autor.
* @fecha_de_creación: dd-mm-yyyy.
* @fecha_de_ultima_actualización: dd-mm-yyyy.
* @versión: 1.0
*/
public class PruebaObtenerMQ{

private static final String ARCHIVO_CONFIGURACION = "ConfiguracionMQ.properties";
private static final String SOURCE_FORDER = "src/";

private Properties objProperties = null;
private MQQueueManager objQueueManager = null;
private ManejoErroresMQ manejoErroresMQ = null;
private ObjetoMQ objetoMQ = null;

{
this.objProperties = this.getObjetoProperties();
this.manejoErroresMQ = new ManejoErroresMQ();
this.objetoMQ = new ObjetoMQ();
}

//Constructores ...
public PruebaObtenerMQ(){
}

public PruebaObtenerMQ( String nombreQManager, String colaInParam, String colaOutParam,
String canalParam, String servidorParam, String puertoParam,
String idParam, String passwordParam ){
super();
this.objetoMQ.setNombreQManager( nombreQManager );
this.objetoMQ.setColaInParam( colaInParam );
this.objetoMQ.setColaOutParam( colaOutParam );
this.objetoMQ.setCanalParam( canalParam );
this.objetoMQ.setServidorParam( servidorParam );
this.objetoMQ.setPuertoParam( puertoParam );
this.objetoMQ.setIdParam( idParam );
this.objetoMQ.setPasswordParam( passwordParam );
}

/**
* main
* @param argumentos
*/
public static void main( String[] argumentos ){
PruebaObtenerMQ conexionMQ = new PruebaObtenerMQ();
conexionMQ.obtenerMensajeMQ();
}

/**
* cargarConfiguracionMQ
*/
public void cargarConfiguracionMQ(){

//Inicializando Paramentos ...
this.objetoMQ.setTiempoInicioMQ( Long.toString( ( new java.util.Date() ).getTime() ) );
//this.objetoMQ.setCorrelationIdMQ( this.tiempoInicioMQ + new java.util.Date().getTime() );
this.objetoMQ.setCorrelationIdMQ( "COSAPISOFT" ); //HardCode.

this.objetoMQ.setNombreQManager( this.objProperties.getProperty( "propiedad.MQ.QManager" ).trim() );
this.objetoMQ.setColaInParam( this.objProperties.getProperty( "propiedad.MQ.colaIN" ).trim() );
this.objetoMQ.setColaOutParam( this.objProperties.getProperty( "propiedad.MQ.colaOUT" ).trim() );
this.objetoMQ.setCanalParam( this.objProperties.getProperty( "propiedad.MQ.canal" ).trim() );
this.objetoMQ.setServidorParam( this.objProperties.getProperty( "propiedad.MQ.servidor" ).trim() );
this.objetoMQ.setPuertoParam( this.objProperties.getProperty( "propiedad.MQ.puerto" ).trim() );
this.objetoMQ.setIdParam( this.objProperties.getProperty( "propiedad.MQ.id" ).trim() );
this.objetoMQ.setPasswordParam( this.objProperties.getProperty( "propiedad.MQ.password" ).trim() );
this.objetoMQ.setMessageIdParam( this.objProperties.getProperty( "propiedad.MQ.messageId" ).trim().getBytes() );

MQEnvironment.channel = this.objetoMQ.getCanalParam();
MQEnvironment.hostname = this.objetoMQ.getServidorParam();
MQEnvironment.port = Integer.parseInt( this.objetoMQ.getPuertoParam() );
MQEnvironment.userID = this.objetoMQ.getIdParam(); //Normalmente el mismo 'ID' del dominio.
MQEnvironment.password = this.objetoMQ.getPasswordParam(); //Normalmente el mismo 'PASSWORD' del dominio.

MQEnvironment.disableTracing();
}

/**
* obtenerMensajeMQ
*/
public void obtenerMensajeMQ(){
try{
this.cargarConfiguracionMQ();

this.objQueueManager = new MQQueueManager( this.objetoMQ.getNombreQManager() );

int opcionesOutputMQ = MQC.MQOO_INPUT_SHARED;

//--------- Especificar las opciones de mensaje para OBTENER (GET). ---------------------------------------//
//MQQueue objColaIN = this.objetoMQ.accessQueue( this.colaOutParam, opcionesOutputMQ, null, null, null );
MQQueue objColaIN = this.objQueueManager.accessQueue( "MQ.A", opcionesOutputMQ, null, null, null );
//MQQueue objColaIN = this.objetoMQ.accessQueue( "MQ.A", MQC.MQOO_INPUT_AS_Q_DEF );

MQGetMessageOptions opcionesGET = new MQGetMessageOptions();
MQMessage mensajeIN = new MQMessage();

opcionesGET.options = MQC.MQGMO_WAIT;

mensajeIN.messageId = mensajeIN.messageId;
//mensajeIN.correlationId = this.correlationIdMQ.getBytes(); //mensajeInput.correlationId;

if( mensajeIN.correlationId != null ){
System.out.println( "CORRELATION ID DEL MENSAJE 'IN': " + mensajeIN.correlationId );
}

//Obteniendo el mensaje de la COLA MQ.
objColaIN.get( mensajeIN, opcionesGET );

String mensajeObtenido = mensajeIN.readString( mensajeIN.getTotalMessageLength() );
System.out.println( "TRAMA OBTENDIDA [GET]: " + mensajeObtenido );

String tamanoMensajeObtenido = String.valueOf( mensajeIN.getTotalMessageLength() );
System.out.println( "TAMAÑO 'TRAMA OBTENDIDA': [" + tamanoMensajeObtenido + "]" );

//Cerrando Colas MQ.
objColaIN.close();

this.objQueueManager.disconnect();
}
catch( MQException e ){
int codigoTermino = e.completionCode ;
int codigoRazon = e.reasonCode ;

this.manejoErroresMQ.validaErrorMQ( codigoTermino, codigoRazon );
System.exit( 0 );
}
catch( IOException e ){
System.out.println( "SE HA PRODUCIDO UN ERROR DE TIPO 'IOException': " + e );
System.exit( 0 );
}
finally{
}
}

/**
* getObjetoProperties
* @return Properties
*/
public Properties getObjetoProperties(){

String rutaFichero = null;
Properties accesoFichero = null;
FileInputStream streamInput = null;

try{
rutaFichero = SOURCE_FORDER + ARCHIVO_CONFIGURACION; //DESDE ECLIPSE.
//rutaFichero = "ARCHIVO_CONFIGURACION"; //DESDE UNIX.

accesoFichero = new Properties();
streamInput = new FileInputStream( rutaFichero );

//Carga Fichero.
accesoFichero.load( streamInput );
}
catch( IOException e ){
e.printStackTrace();
}

return accesoFichero;
}
}

Clase 'PruebaEnviaObtieneMQ':

package org.java.mq;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;

/**
* @author: cguerraa.
* @clase: PruebaEnviaObtieneMQ.java
* @descripción: descripción de la clase.
* @author_web: http://frameworksjava2008.blogspot.com - http://viviendoconjavaynomoririntentandolo.blogspot.com
* @author_email: cesarricardo_guerra19@hotmail.com.
* @author_company: nombre de la compañía del autor.
* @fecha_de_creación: dd-mm-yyyy.
* @fecha_de_ultima_actualización: dd-mm-yyyy.
* @versión: 1.0
*/
public class PruebaEnviarObtenerMQ{

private static final String ARCHIVO_CONFIGURACION = "ConfiguracionMQ.properties";
private static final String SOURCE_FORDER = "src/";

private static String TRAMA_INPUT = "MENSAJE GUARDADO DE FORMA DIRECTA VIA APLICATIVO JAVA - MQ ...!!!...ENVIO DE TRAMA DESDE LANZADOR EN JAVA.";

private Properties objProperties = null;
private MQQueueManager objQueueManager = null;
private ManejoErroresMQ manejoErroresMQ = null;
private ObjetoMQ objetoMQ = null;

{
this.objProperties = this.getObjetoProperties();
this.manejoErroresMQ = new ManejoErroresMQ();
this.objetoMQ = new ObjetoMQ();
}

//Constructores ...
public PruebaEnviarObtenerMQ(){
}

public PruebaEnviarObtenerMQ( String tramaParam ){
super();
TRAMA_INPUT = tramaParam;
}

public PruebaEnviarObtenerMQ( String nombreQManager, String colaInParam, String colaOutParam, String canalParam,
String servidorParam, String puertoParam, String idParam, String passwordParam ){
super();
this.objetoMQ.setNombreQManager( nombreQManager );
this.objetoMQ.setColaInParam( colaInParam );
this.objetoMQ.setColaOutParam( colaOutParam );
this.objetoMQ.setCanalParam( canalParam );
this.objetoMQ.setServidorParam( servidorParam );
this.objetoMQ.setPuertoParam( puertoParam );
this.objetoMQ.setIdParam( idParam );
this.objetoMQ.setPasswordParam( passwordParam );
}

/**
* main
* @param argumentos
*/
public static void main( String[] argumentos ){
PruebaEnviarObtenerMQ conexionMQ = new PruebaEnviarObtenerMQ();
conexionMQ.enviarObtenerMQ();
}

/**
* enviarObtenerMQ
*/
public void enviarObtenerMQ(){

try{
this.cargarConfiguracionMQ();

System.out.println( "TRAMA ENVIADA [PUT]: " + this.objetoMQ.getMensajeTramaMQ() );

MQEnvironment.channel = this.objetoMQ.getCanalParam();
MQEnvironment.hostname = this.objetoMQ.getServidorParam();
MQEnvironment.port = Integer.parseInt( this.objetoMQ.getPuertoParam() );
MQEnvironment.userID = this.objetoMQ.getIdParam();
MQEnvironment.password = this.objetoMQ.getPasswordParam();

//MQEnvironment.enableTracing( 2 );
MQEnvironment.disableTracing();

this.objQueueManager = new MQQueueManager( this.objetoMQ.getNombreQManager() );

//Configurar las opciones en la cola que se va a abrir...
//Todas las opciones de WebSphere MQ tienen el prefijo MQC en Java.
int opcionesInputMQ = MQC.MQOO_OUTPUT;
int opcionesOutputMQ = MQC.MQOO_INPUT_SHARED;

//--------- Especificar las opciones de mensaje para ESCRIBIR (PUT). ---------------------------------------//
MQQueue objColaOUT = this.objQueueManager.accessQueue( this.objetoMQ.getColaInParam(), opcionesInputMQ, null, null, null );
MQPutMessageOptions opcionesPUT = new MQPutMessageOptions();
MQMessage mensajeOUT = new MQMessage(); //Definir un mensaje WebSphere MQ simple y escribir texto en formato UTF...

mensajeOUT.messageId = this.objetoMQ.getMessageIdParam();
mensajeOUT.correlationId = this.objetoMQ.getCorrelationIdMQ().getBytes();
mensajeOUT.format = MQC.MQFMT_STRING; //Formato que consiste en Solo Caracteres enviados.

//Definir un mensaje WebSphere MQ simple y escribir texto en formato UTF...
mensajeOUT.writeUTF( this.objetoMQ.getMensajeTramaMQ() );

//Escribe el mensaje en la cola MQ.
objColaOUT.put( mensajeOUT, opcionesPUT );

//Cerrando Colas MQ.
objColaOUT.close();

//--------- Especificar las opciones de mensaje para OBTENER (GET). ---------------------------------------//
MQQueue objColaIN = this.objQueueManager.accessQueue( this.objetoMQ.getColaInParam(), opcionesOutputMQ, null, null, null );
MQGetMessageOptions opcionesGET = new MQGetMessageOptions();
MQMessage mensajeIN = new MQMessage();

opcionesGET.options = MQC.MQGMO_WAIT;
mensajeIN.messageId = mensajeOUT.messageId;
mensajeIN.correlationId = mensajeOUT.correlationId;

if( mensajeIN.correlationId != null ){
System.out.println( "CORRELATION ID DEL MENSAJE 'IN': " + mensajeIN.correlationId );
}

//Obteniendo el mensaje de la COLA MQ.
objColaIN.get( mensajeIN, opcionesGET );

System.out.println( "" );

String mensajeObtenido = mensajeIN.readString( mensajeIN.getTotalMessageLength() );
System.out.println( "TRAMA OBTENDIDA [GET]: " + mensajeObtenido );

String tamanoMensajeObtenido = String.valueOf( mensajeIN.getTotalMessageLength() );
System.out.println( "TAMAÑO 'TRAMA OBTENDIDA': [" + tamanoMensajeObtenido + "]" );

//Cerrando Colas MQ.
objColaOUT.close();

//Desconectar del gestor de colas
this.objQueueManager.disconnect();
}
catch( MQException e ){
int codigoTermino = e.completionCode ;
int codigoRazon = e.reasonCode ;

this.manejoErroresMQ.validaErrorMQ( codigoTermino, codigoRazon );
System.exit( 0 );
}
catch( IOException e ){
System.out.println( "SE HA PRODUCIDO UN ERROR DE TIPO 'IOException': " + e );
System.exit( 0 );
}
}

/**
* cargarConfiguracionMQ
*/
public void cargarConfiguracionMQ(){

//Inicializando Paramentos ...
this.objetoMQ.setMensajeTramaMQ( TRAMA_INPUT );
this.objetoMQ.setTiempoInicioMQ( Long.toString( ( new java.util.Date() ).getTime() ) );
this.objetoMQ.setCorrelationIdMQ( this.objetoMQ.getTiempoInicioMQ() + new java.util.Date().getTime() );
this.objetoMQ.setNombreQManager( this.objProperties.getProperty( "propiedad.MQ.QManager" ).trim() );
this.objetoMQ.setColaInParam( this.objProperties.getProperty( "propiedad.MQ.colaIN" ).trim() );
this.objetoMQ.setColaOutParam( this.objProperties.getProperty( "propiedad.MQ.colaOUT" ).trim() );
this.objetoMQ.setCanalParam( this.objProperties.getProperty( "propiedad.MQ.canal" ).trim() );
this.objetoMQ.setServidorParam( this.objProperties.getProperty( "propiedad.MQ.servidor" ).trim() );
this.objetoMQ.setPuertoParam( this.objProperties.getProperty( "propiedad.MQ.puerto" ).trim() );
this.objetoMQ.setIdParam( this.objProperties.getProperty( "propiedad.MQ.id" ).trim() );
this.objetoMQ.setPasswordParam( this.objProperties.getProperty( "propiedad.MQ.password" ).trim() );
this.objetoMQ.setMessageIdParam( this.objProperties.getProperty( "propiedad.MQ.messageId" ).trim().getBytes() );

//Imprimiendo Datos MQ.
this.imprimeDatosMQ();

MQEnvironment.disableTracing();
}

/**
* getObjetoProperties
* @return Properties
*/
public Properties getObjetoProperties(){

String rutaFichero = null;
Properties accesoFichero = null;
FileInputStream streamInput = null;

try{
rutaFichero = SOURCE_FORDER + ARCHIVO_CONFIGURACION; //DESDE ECLIPSE.
//rutaFichero = "ARCHIVO_CONFIGURACION"; //DESDE UNIX.

accesoFichero = new Properties();
streamInput = new FileInputStream( rutaFichero );

//Carga Fichero.
accesoFichero.load( streamInput );
}
catch( IOException e ){
e.printStackTrace();
}

return accesoFichero;
}

/**
* imprimeDatosMQ
*/
public void imprimeDatosMQ(){
System.out.println( "" );
System.out.println( "*************** PARAMETROS DE CONFIGURACION ***************" );
System.out.println( "- QMANAGER: " + this.objetoMQ.getNombreQManager() );
System.out.println( "- COLA IN: " + this.objetoMQ.getColaInParam() );
System.out.println( "- COLA OUT: " + this.objetoMQ.getColaOutParam() );
System.out.println( "- CANAL: " + this.objetoMQ.getCanalParam() );
System.out.println( "- SERVIDOR: " + this.objetoMQ.getServidorParam() );
System.out.println( "- PUERTO: " + this.objetoMQ.getPuertoParam() );
System.out.println( "- ID: " + this.objetoMQ.getIdParam() );
System.out.println( "- PASSWORD: " + this.objetoMQ.getPasswordParam() );
System.out.println( "- MESSAGE ID: " + this.objetoMQ.getMessageIdParam() );
System.out.println( "- CORRELATION ID: " + this.objetoMQ.getCorrelationIdMQ() );
System.out.println( "***********************************************************" );
System.out.println( "" );
}
}




Para mayor detalle descargar el ejemplo completo de: AQUÌ.

domingo, 2 de mayo de 2010

MANEJO DE JAKARTA HTTP CLIENT

Bueno en esta oportunidad postearé sobre un Framework muy útil, para los casos en los que, muchos desarrolladores, en algún momento hemos estado en el escenario en el que teníamos que enviar parámetros a un Servlet pero sin esta necesariamente en un JSP, ni apoyándose en una funciona JavaScript, sino que desde una clase JAVA. Para esto un Framework aparece en nuestro rescate, este se llama: 'Jakarta Commons HttpClient'. Este Framework permite realizar una conexión directa a un JSP o un Servlet enviando fácilmente los parámetros respectivos y identificar rápidamente datos como del Response como: TIPO (GET/POST), URL, SERVLET, PARAMETROS DEL SERVLET, ESTATUS, HTML, etc.

El demo preparado muestra el manejo de 'HttpClient' y se conecta con un 'Servlet' de un demo anteriomente mostrado para manejos de Servlet´s. El ejemplo de Servket lo descargas de aquí:
DEMO MANEJO SERVLET.

Para mayor detalle descargar el ejemplo completo de 'HttpClient': AQUÌ.

sábado, 1 de mayo de 2010

MANEJO DE SERVLETs

Que tal esta oportunidad postearé sobre un tema ya un poco antiguo, pero que nunca pasará 100% de moda, ya que por mas frameworks que utilicemos para nuestros desarrollos en algún momento tendremos la necesidad de recurrir al uso de un Servlet.

Un servlet es un objeto que se ejecuta en un servidor o contenedor JEE, especialmente diseñado para ofrecer contenido dinámico desde un servidor web, generalmente HTML.

Un servlet implementa la interfaz javax.servlet.Servlet o hereda alguna de las clases más convenientes para un protocolo específico (Ejm: javax.servlet.HttpServlet). Al implementar esta interfaz el servlet es capaz de interpretar los objetos de tipo 'HttpServletRequest' y 'HttpServletResponse' quienes contienen la información de la página que invocó al servlet.

Ciclo de vida de un Servlet.

El ciclo de vida de un Servlet se divide en los siguientes puntos:

1. El cliente solicita una petición a un servidor vía URL.
2. El servidor recibe la petición.
2.1. Si es la primera, se utiliza el motor de Servlets para cargarlo y se llama al método init().
2.2. Si ya está iniciado, cualquier petición se convierte en un nuevo hilo. Un Servlet puede manejar múltiples peticiones de clientes.
3. Se llama al método service() para procesar la petición devolviendo el resultado al cliente.
4. Cuando se apaga el motor de un Servlet se llama al método destroy(), que lo destruye y libera los recursos abiertos.

Asi mismo un Servlet permite el acceso por medio de unos objetos, para el acceso al contexto de la aplicación.

-------------
ServletConfig
-------------

- Para el acceso al contexto actual de una aplicación Web corriendo en una JVM.
- Un ServletConfig por 'Servlet'.
- Es usado para el acceso al 'ServletContext'.
- Se accede al objeto mediante: getServletConfig().getInitParameter( "nombreParametro" );

--------------
ServletContext
--------------

- Para el acceso al contexto actual de una aplicación Web corriendo en una JVM.
- Usado para el acceso a la configuración de elemento deployado.
- Se acceder al objeto mediante: getServletContext().getInitParameter( "nombreParametro" );

El ejemplo preparador muestra una aplicación dividida en 2 partes:

La primera muestra un Login que valida un usuario y password, aqui se muestra el manejo de metodos como: doGet(), doPost(), service(), destroy(), etc.Mientras que el segundo ejemplo muestra el manejo de un muy útil ImageServlet.







Para mayor detalle descargar el ejemplo completo: AQUÌ.

viernes, 6 de noviembre de 2009

MANEJO DE 'WEB SERVICE' CON 'AXIS2'.

Hace un tiempo posteè sobre el manejo de Web Service con AXIS1, esta vez mostraré el manejo de Web Service (Su consumo) pero con AXIS2. Este Framework AXIS2 a diferencia de su versión anterior AXIS1 permite un mejor manejo de los Web Service Orientados a Objetos, ya que en la versión anterior de AXIS los Objetos del Service enviados como parámetros por el Web Service, se podían regenerar desde un cliente WS pero para poder parsearlos se necesita de forma obligada el número de serialVersionUID (Para poder comprobar que es el mismo objeto) , aquí AXIS1 era débil. AXIS2 supero eso ya que no tiene este traspié. AXIS2 solamente posee un problema al momento de la generación del cliente WS que mas adelante mostraremos y solucionaremos.

Al igual que el ejemplo posteado con AXIS1 mostraré la generación del Cliente WS y consumo de dichos procesos:

/********** PROCESOS 'WS' **********/
//Probando 'SUMA'.
clienteWS.getResultadoSuma( numero_01, numero_02, accesoWS );

//Probando 'RESTA'.
//clienteWS.getResultadoResta( numero_01, numero_02, accesoWS );

//Probando 'MULTIPLICACION'.
//clienteWS.getResultadoMultiplicacion( numero_01, numero_02, accesoWS );

//Probando 'DIVISION'.
//clienteWS.getResultadoDivision( numero_01, numero_02, accesoWS );

//Probando 'obtenerUsuario'.
//clienteWS.getObjetoUsuario( accesoWS );

//Probando 'obtenerListaUsuarios'.
//clienteWS.getListaUsuarios( accesoWS );;
/***********************************/

Los pasos son los siguientes:

1.- Tenemos el WSDL ya generado del servidor “UsuarioServiceImpl.wsdl” , este WSDL esta en la ruta: WebContent/wsdl/UsuarioServiceImpl.wsdl. En base a esta ruta generaremos por medio de consola el Cliente AXIS2, pero tendremos que configurar las variables de entorno antes.

2.- Bajarte la ultima versión de AXIS2: http://ws.apache.org/axis2/1_5_1/installationguide.html

3.- Ubicarla en una ruta en tu PC: “D:\JAVA\Axis\axis2-1.5.1”

4.- Registrar las variables de entorno (Tanto en Usuario como en Sistema):



5.- Generar el cliente AXIS2 desde consola aplicando el siguiente còdigo desde la ruta raiz del proyecto trabajado:

%AXIS2_HOME%/bin/WSDL2Java -p org.java.service -uri WebContent/wsdl/UsuarioServiceImpl.wsdl -s



6.- En este momento AXIS2 genera un error:

Es posible que cuando se desee generar un cliente JAVA con AXIS2 en base a un WSDL, uno encuentre con un error así:

Unexpected subelement 'XXXX'

Esto se debe a que AXIS2 genera el Cliente WS de una forma no totalmente correcta. Ya que confunde los NameSpaceURI. Supongamos como en este caso que el Servidor WS posee dos paquetes:

- PAQUETE DEL OBJETO: org.java.bean
- PAQUETE DEL WS: org.java.servidor.ws

Al momento de la generación del Cliente WS con AXIS2, los NameSpaceURI se invierten y quedan de la siguiente manera:

- NAMESPACE APUNTANDO AL OBJETO: “http://bean.java.org"
- NAMESPACE APUNTANDO AL WS: "http://ws.servidor.java.org"

Aquí esta el problema y la solución seria buscar la clase 'Stub' generada, en este caso 'ConsultaWSServiceStub' y en ella buscar por cada Objeto que se trabaje su:

static MY_OBJETO parse:

/**
* Factory class that keeps the parse method
*/
public static class Factory{

/**
* static method to create the object Precondition: If this object is an element, the
* current or next start element starts this object and any intervening reader events
* are ignorable If this object is not an element, it is a complex type and the reader
* is at the event just after the outer start element Postcondition: If this object is
* an element, the reader is positioned at its end element If this object is a complex
* type, the reader is positioned at the end element of its outer element
*/
public static Usuario parse( javax.xml.stream.XMLStreamReader reader ) throws java.lang.Exception{

Y cambiar el NameSpace para cada campo de > cada Objeto trabajado, de la siguiente forma:

AQUI SE DA EL 'ERROR':

while( !reader.isStartElement() && !reader.isEndElement() )
reader.next();
if( reader.isStartElement() &&
new javax.xml.namespace.QName( "http://bean.java.org", "nombre" ).equals( reader.getName() ) ){
nillableValue = reader.getAttributeValue( "http://www.w3.org/2001/XMLSchema-instance", "nil" );
if( !"true".equals( nillableValue ) && !"1".equals( nillableValue ) ){
java.lang.String content = reader.getElementText();
object.setNombre( org.apache.axis2.databinding.utils.ConverterUtil.convertToString( content ) );
}
else{
reader.getElementText(); // throw away text nodes if any.
}
reader.next();
} // End of if for expected property start element
else{
// A start element we are not expecting indicates an invalid parameter was
// passed throw new org.apache.axis2.databinding.ADBException( "Unexpected subelement " + reader.getLocalName() );
}

AQUI SE DA EL 'SOLUCION':

while( !reader.isStartElement() && !reader.isEndElement() )
reader.next();
if( reader.isStartElement() &&
new javax.xml.namespace.QName( "http://ws.servidor.java.org", "nombre" ).equals(
reader.getName() ) ){
nillableValue = reader.getAttributeValue( "http://www.w3.org/2001/XMLSchema-instance", "nil" );
if( !"true".equals( nillableValue ) && !"1".equals( nillableValue ) ){
java.lang.String content = reader.getElementText();
object.setNombre(
org.apache.axis2.databinding.utils.ConverterUtil.convertToString( content ) );
}
else{
reader.getElementText(); // throw away text nodes if any.
}
reader.next();
} // End of if for expected property start element
else{
// A start element we are not expecting indicates an invalid parameter was
// passed throw new org.apache.axis2.databinding.ADBException( "Unexpected subelement " + reader.getLocalName() );
}

7.- Creamos la clase: org/java/client/ClienteWS_Generado.java y vamos descomentando y ejecutando los procesos anteriormente nombrados uno por uno para probar su manejo. Recordar que primero se tiene que desplegar el demo del 'Proyecto Servidor' que es parte del demo posteado llamado: Ejemplo Web Service con JAX-WS , para poder probar sin problemas el Cliente WS con AXIS2.

Para mayor detalle descargar el ejemplo completo: AQUÌ.

jueves, 15 de octubre de 2009

MANEJO DE FECHAS CON JODA API

El manejo de Fechas en JAVA siempre a sido un poco molestoso ya que uno por muchos motivos tiende al manejo de dichas fechas de diferentes formas:

En String, Date, Calendar, GregorianCalendar, etc.

Y porque no hay un estándar en dicho manejo de fechas, las tendencias son siempre convertir formatear, reconvertir y volver a formatear para manipular los datos de un lado a otro. Bueno en esta oportunidad presento esta API Java que puede ayudar en algo dichos problemas ya que proporción objetos (No Deprecated) que son fáciles de manipular, que permiten muchas conversiones: StringToDate, DateToString, etc. y que con una sola línea te devuelve lo deseado, el API se llama JODA y aquí les comparto una clase JAVA donde muestro su manejo. El manejo es tan fácil como decir:

int anos = Years.yearsBetween( fechaInicio, fechaFin ).getYears();

Aquí maestro el resumen informativo de un demo en donde trabajo el cálculo de 2 fechas:


FECHA INICIO [DateTime]: 1983-01-04T00:00:00.000-05:00
FECHA FIN [DateTime]: 2009-10-15T14:23:30.093-05:00

FECHA INICIO [Date]: Tue Jan 04 00:00:00 COT 1983
FECHA FIN [Date]: Thu Oct 15 14:23:30 COT 2009

FECHA INICIO [Date MGT]: 4 Jan 1983 05:00:00 GMT
FECHA FIN [Date MGT]: 15 Oct 2009 19:23:30 GMT

FECHA INICIO [Date LOCALE]: 04-ene-1983 0:00:00
FECHA FIN [Date LOCALE]: 15-oct-2009 14:23:30

FECHA INICIO [Calendar]: java.util.GregorianCalendar[time=410504400000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Bogota",offset=-18000000,dstSavings=0,useDaylight=false,transitions=5,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=1983,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=1,DAY_OF_MONTH=4,DAY_OF_YEAR=4,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0]

FECHA FIN [Calendar]: java.util.GregorianCalendar[time=1255634610093,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Bogota",offset=-18000000,dstSavings=0,useDaylight=false,transitions=5,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2009,MONTH=9,WEEK_OF_YEAR=42,WEEK_OF_MONTH=3,DAY_OF_MONTH=15,DAY_OF_YEAR=288,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=2,HOUR_OF_DAY=14,MINUTE=23,SECOND=30,MILLISECOND=93,ZONE_OFFSET=-18000000,DST_OFFSET=0]

//VALIDANDO
[F.INICIO] ES ANTES [F.FIN]
[F.FIN] ES DESPUES [F.INICIO]


DATOS [FECHA INICIO]
--------------------
AÑO: 1983
AÑO DE LA CENTURIA: 83
AÑO DE LA ERA: 1983
MES DEL AÑO: 1
DIA DEL MES: 4
DIA DE LA SEMANA: 2
DIA DEL AÑO: 4
MINUTO DEL DIA: 0
MINUTO DE LA HORA: 0
SEGUNDO DEL DIA: 0
SEGUNDO DEL MINUTO: 0


DATOS [FECHA FIN]
-----------------
AÑO: 2009
AÑO DE LA CENTURIA: 9
AÑO DE LA ERA: 2009
MES DEL AÑO: 10
DIA DEL MES: 15
DIA DE LA SEMANA: 4
DIA DEL AÑO: 288
MINUTO DEL DIA: 863
MINUTO DE LA HORA: 23
SEGUNDO DEL DIA: 51810
SEGUNDO DEL MINUTO: 30

//OTROS DATOS
DIAS ENTRE [F.INICIO] & [F.FIN]: 9781
MESES ENTRE [F.INICIO] & [F.FIN]: 321
AÑOS ENTRE [F.INICIO] & [F.FIN]: 26
MINUTOS ENTRE [F.INICIO] & [F.FIN]: 14085503
SEGUNDOS ENTRE [F.INICIO] & [F.FIN]: 845130210


Para descargar El demo pulsar:
AQUÌ.

jueves, 8 de octubre de 2009

OBTENCIÒN DE DATOS DE XML CON XPATH Y JAVA

El otro dìa me encontre con un post que hablaba muy bien de un lenguaje de programaciòn para el ràpido acceso a datos embebidos en un fichero XML, este lenguaje se llama XPATH
y es una versiòn superior a otro conocido pero màs antiguo lenguaje llamado XQL, el cual su logica era en base a consultas tipo SQL acceder a los datos pero no de una BD sino de XML propiamente. XPATH heredò toda la sintaxis de este lenguaje como predecesor que es y le ha puesto varias mejoras. XPATH como lenguaje esta orientado a buscar información dentro de
documentos con esctructura en XML. Uno de sus ùnicos defectos que le he podido encontrar es que no se pueden realizar JOINs, pero se puede jugar con los datos obtenidos y cargar listas de datos por ejemplo de còdigos que pueden servir en entrada para la obtenciòn de datos de otra tabla (si lo orientamos a SQL por decir) y que finalmente da un resultado similar al de un JOIN. Este lenguaje es verdaderamente ràpido y lo mejor es que podemos trabajarlo simultaneamente con JAVA, ya que JAVA posee librerìas que soportan las consultas generadas con los XPATH Querys y por ser un lenguaje superior JAVA te permite lo anteiormente hablado de simular un JOIN cargando
listas y recorriendolas.

Al comienzo XPATH puede causar un poco de molestia, ya que su sintaxis no es SQL, pero poco a poco uno le agarra el truco, yo en medio dìa lo aprendì y para probarme que tan bien lo aprendì, busquè y encontre una muy buena WEB donde explican todo en Español sobre XPATH y posse un SIMULADOR donde te toman un TEST de sintaxis
que en base a preguntas y con un gran XML a tu costado, tienes que demostrar que sabes y codificar tu Query y comparar el resultado que tienes con el resultado correcto, que tambien se muestra al lado.

Los links son los siguientes:

- TUTORIAL: http://geneura.ugr.es/~victor/cursillos/xml/XPath
- FICHERO XML: http://geneura.ugr.es/~victor/cursillos/xml/XPath/ejercicios_xpath_xml.html
- SIMULADOR: http://geneura.ugr.es/~victor/cursillos/xml/XPath/ejercicios_xpath.html

Pero como este es un BLOG de JAVA, tenemos que hablar de JAVA, asi voy a mostrar la soluciòn de este simulador pero dentro de una aplicaciòn JAVA que yo mismo cree y que de paso muestra el facil manejo de lentura de XML que este XPATH con JAVA de manera conjunta hacen.

Para descargar la aplicaciòn demo pulsar:
AQUI.