Buscar en el Blog

martes, 14 de diciembre de 2010

Cómo instalar Apache Tomcat 6 en Ubuntu Server

En ésta publicación explicaré cómo instalar Apache Tomcat 6 en un servidor Ubuntu v10.04.

1. En la consola de comandos (shell) usar el comando apt-get install

sudo apt-get install tomcat6

NOTA: es necesario que el servidor tenga acceso a Internet, ya que el comando apt-get install obtiene los paquetes de instalación de un servidor de Internet.

2. Para instalar la documentación de Apache Tomcat 6 ejecutar el siguiente comando:

sudo apt-get install tomcat6-docs

3. Para instalar la aplicación de administración de Apache Tomcat 6 (Tomcat Manager) ejecutar el siguiente comando:

sudo apt-get install tomcat6-admin

Como se describe anteriormente, la instalación de Apache Tomcat 6 no es complicada pero sí es importante conocer los siguientes aspectos relacionados con la instalación.

Ubicación de los archivos de configuración

Los archivos de configuración se crean en el directorio /etc/tomcat6. Aquí se podrán encontrar los archivos server.xml para poder cambiar el puerto del servidor Tomcat y tomcat-users.xml para poder crear usuarios que utilizarán el Tomcat Manager.

Para editar los archivos de configuración es necesario usar el comando sudo seguido de un editor de texto que puede ser vi o nano. Sí no se tiene experiencia con vi, recomiendo 100% usar el editor de texto nano como se muestra a continuación:

cd /etc/tomcat6 
sudo nano server.xml

cd /etc/tomcat6 
sudo nano tomcat-users.xml

Gestión de los servicios [Iniciar | Detener | Reiniciar]

Para detener el servicio de Apache Tomcat 6 ejecutar el siguiente comando:

sudo /etc/init.d/tomcat6 stop

Para iniciar el servicio ejecutar el comando:

sudo /etc/init.d/tomcat6 start

Para reiniciar el servicio ejecutar el comando:

sudo /etc/init.d/tomcat6 restart

Permisos para el Administrador de Tomcat (Tomcat Manager)

Para que el Tomcat Manager corra sin problemas, es necesario darle los siguientes permisos:

sudo chgrp -R tomcat6 /etc/tomcat6
sudo chmod -R gtw /etc/tomcat6

Además, es necesario crear por lo menos un usuario en el archivo de configuración tomcat-users.xml con el rol manager como se muestra a continuación:


<role rolename="manager"> 
<user username="ingmmurillo" password="1234" roles="manager">

viernes, 29 de octubre de 2010

Cómo instalar el JDK en la distribución de GNU/Linux: Ubuntu

En ésta publicación explico cómo instalar el Java Development Kit (JDK) v1.6 en la distribución de GNU/Linux: Ubuntu.

1. Descargar el JDK para la plataforma Linux jdk-6u22-linux-i586.bin

2. Copiar el archivo jdk-6u22-linux-i586.bin a la carpeta /usr. En mi caso el archivo fue descargado en el escritorio de Ubuntuen la ubicación /home/ingmmurillo/Desktop.

    - Abrir la consola de comandos (Shell)
    - Ingresar como superusuario (su)
ingmmurillo@ubuntu:~# cd /home/ingmmurillo/Desktop
ingmmurillo@ubuntu:/Desktop~# su
    - Copiar el archivo jdk-6u22-linux-i586.bin a la carpeta /usr
root@ubuntu:/home/ingmmurillo/Desktop# cp jdk-6u22-linux-i586.bin /usr 

3. Ir al directorio /usr y ejecutar el comando sh jdk-6u22-linux-i586.bin
root@ubuntu:/home/ingmmurillo/Desktop#cd /usr 
root@ubuntu:/usr# sh jdk-6u22-linux-i586.bin

4. Se comenzará a desempaquetar los archivos y al final pedirá la aceptación de los términos y condiciones. Una vez que se tenga todo listo el JDK estará instalado en el directorio /usr/jdk1.6.0_22

5. Por último se tiene que configurar la variable de entorno JAVA_HOME y agregar los binarios de Java al PATH del sistema operativo de la siguiente manera.

   - Ir al directorio /home/
   - Abrir el archivo _bashrc con un editor de texto
   - Colocar al final del archivo lo siguiente:
export JAVA_HOME='/usr/jdk1.6.0_22'
PATH=.:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH

Para probar que la instalación del JDK y la configuración de las variables de entorno fue exitosa, abrir una terminal de comandos y ejecutar el comando java -version que deberá mostrar un mensaje similar al siguiente:
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode)

martes, 21 de septiembre de 2010

Recomendaciones para trabajar con aplicaciones Flex

Adobe Flex es una tecnología super interesante para construir interfaces gráficas de usuario web ricas en contenido, lo que se conoce como RIA (Rich Internet Application). La tecnología Flex trabaja con archivos de extensión .swf (ShockWave Flash) para lo cuál es necesario tener instalado Adobe Flash Player en cada navegador web del cliente que accederá a la aplicación.

Con la experiencia que he tenido con las aplicaciones desarrolladas en Flex, comparto algunas recomendaciones para subir los aplicativos a la nube (Internet).

1. De preferencia usar un servidor proxy como BlazeDS a diferencia de configurar el archivo crossdomain.xml

2. La configuración de las propiedades del proyecto en el IDE son claves. Una vez que se haya definido el domino en el cuál estará la aplicación por ejemplo http://www.midominio.com/flex, configurar las propiedades del Flex Server como: 

Root URL = http://www.midominio.com/flex
Context Root = /flex

3. Es recomendable hacer primero un Clean y luego un Build del proyecto.

4. Sí se tiene problemas con la compilación del proyecto y el nuevo dominio configurar el archivo hosts del sistema operativo.

En Windows > C:\Windows\System32\drivers\etc\hosts
En Linux /etc/hosts
5. Configurar adecuadamente los archivos de configuración de BlazeDS: services-config.xml y proxy-config.xml.

6. Cuando se trabaja con balanceadores de carga, es recomendable hacer un loopback al mismo servidor en base al dominio con el cuál se está trabajando.

Espero que éstas recomendaciones les sea de mucha utilidad, sí tienen alguna pregunta no duden en contactarme.

viernes, 17 de septiembre de 2010

The Java Song - Lady Java

Les comparto un video musical que encontre sobre Java, titulado "Lady Java" espero les guste.


miércoles, 11 de agosto de 2010

Utilización de JAXB para mapear clases Java a representaciones XML

JAXB es una tecnología Java que permite mapear clases de Java a representaciones XML. JAXB provee dos funciones fundamentales:

  1. marshal. Consiste en presentar un objeto Java en XML. Java Object > XML
  2. unmarshal. Consiste en presentar XML en un objeto Java. XML > Java Object
La versión 2.2.1 del API de JAXB puede ser descargada desde el siguiente link: https://jaxb.dev.java.net/2.2.1/JAXB2_20100511.jar

Esta versión trabaja con anotaciones con las cuáles se indica cuál será la raíz del documento XML, los elementos y los atributos. Las principales anotaciones son:

  • @XmlRootElement
  • @XmlElement
  • @XmlAttribute
En mi publicación anterior de "cómo exponer un servicio web en Mule" en el Bean Message sobrescribí el método toString para mostrar el contenido del objeto usando tags XML. Con el uso del API de JAXB ésto ya no es necesario y es reemplazado por anotaciones, como se muestra a continuación:

package com.blogspot.ingmmurillo.axisws;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;

@XmlRootElement
public class Message implements Serializable {

    private Field[] fields;
    private String from;
    private String to;   

    @XmlAttribute
    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    @XmlAttribute
    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public Field[] getFields() {
        return fields;
    }

    public void setFields(Field[] fields) {
        this.fields = fields;
    }

    @Override
    public String toString() {

        OutputStream xmlOutput = new OutputStream() {
            private StringBuilder string = new StringBuilder();

            @Override
            public void write
                    (
                            int b) throws IOException {
                this.string.append((char) b);
            }

            @Override
            public String toString
                    () {
                return this.string.toString();
            }
        };

        JAXBContext contextObj = null;
        Marshaller marshallerObj = null;
        try {
            contextObj = JAXBContext.newInstance(Message.class);
            marshallerObj = contextObj.createMarshaller();
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshallerObj.marshal(this, xmlOutput);
            xmlOutput.flush();
            xmlOutput.close();
        } catch (JAXBException e) {
            e.printStackTrace();
            return e.getMessage();
        } catch (IOException e) {
            e.printStackTrace();
            return e.getMessage();
        } finally {
            if (contextObj != null) {
                contextObj = null;
            }
            if (marshallerObj != null) {
                marshallerObj = null;
            }
        }

        return xmlOutput.toString();
    }    
}

Al realizar la invocación del servicio web la respuesta obtenida es la siguiente:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:sendMessageResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ingmmurillo.blogspot.com/webservices/axis">
         <sendMessageReturn xsi:type="xsd:string"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message to="The World" from="My Blog">
    <fields>
        <name>FirstName</name>
        <value>Mauricio</value>
    </fields>
    <fields>
        <name>LastName</name>
        <value>Mauricio</value>
    </fields>
</message>]]></sendMessageReturn>
      </ns1:sendMessageResponse>
   </soapenv:Body>
</soapenv:Envelope>


El XML de respuesta ahora fue generado automáticamente usando JAXB. En conclusión, JAXB permite ahorrar tiempo para realizar los procesos de marshal y unmarshal. Además, JAXB permite que el mantenimiento de un bean sea menos costoso, ayudando a los desarrolladores a trabajar de forma más ágil.

jueves, 22 de julio de 2010

Cómo exponer un servicio web en Mule 2 usando Apache Axis - Parte 2

En mi anterior publicación explicaba cómo exponer un servicio web en Mule 2 usando Apache Axis. Este servicio web tenía el método helloAxis() el cuál recibía y devolvía cadenas de texto (java.lang.String). En ésta parte 2 de mi publicación explico cómo exponer un servicio web usando objetos (beans) que no forman parte del API de Java. Estos objetos son los siguientes:


Bean Field

package com.blogspot.ingmmurillo.axisws;

import java.io.Serializable;

public class Field implements Serializable{

    private String name;
    private String value;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        String result = "";
        result += "" + name + "";
        result += "" + value + "";
        result += "";
        return result;
    }
}

Como se puede observar se sobreescribe el método toString() usando tags XML para mostrar el contenido de las variables de instancia del objeto. Además, es importante que los beans que se definan implementen la interface java.io.Serializable.

Bean Message

package com.blogspot.ingmmurillo.axisws;

import java.io.Serializable;

public class Message implements Serializable {

    private Field[] fields;
    private String from;
    private String to;

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public Field[] getFields() {
        return fields;
    }

    public void setFields(Field[] fields) {
        this.fields = fields;
    }

    @Override
    public String toString() {
        String result = "";
        if (fields != null) {
            if (fields.length > 0) {

                for (Field f : fields) {
                    result += f;
                }
            }
        }
        result += "" + from + "";
        result += "" + to + "";
        result += "";

        return result;
    }
}

Como se puede observar este bean tiene un arreglo de objetos de tipo Field. De igual forma se sobreescribe el método toString() usando tags XML.

Interface WSComplexDataTypes

package com.blogspot.ingmmurillo.axisws;

public interface WSComplexDataTypes {

    public String sendMessage(Message msg);

}

La interface define el método sendMessage() el cúal recibe como parámetro un objeto de tipo com.blogspot.ingmmurillo.axisws.Message.

Clase WSComplexDataTypesImpl

package com.blogspot.ingmmurillo.axisws;

public class WSComplexDataTypesImpl implements WSComplexDataTypes {

    public String sendMessage(Message msg) {
        return msg.toString();
    }
}


Esta clase contiene la implementación del método sendMessage() el cual hace una llamada al método toString() el cual fue redefinido para cada Bean. Cuando se invoque al servicio web se devolverá el contenido en XML.

Configuración en Mule

<service name="wsComplexData">
            <inbound>
                <axis:inbound-endpoint
                        address="http://localhost:8282/webservices/axis"
                        serviceNamespace="http://ingmmurillo.blogspot.com/webservices/axis"
                        synchronous="true">
                </axis:inbound-endpoint>
            </inbound>
            <component class="com.blogspot.ingmmurillo.axisws.WSComplexDataTypesImpl"/>
        </service>


Pruebas

El servicio web será publicado en Mule bajo el siguiente URL:
http://localhost:8282/webservices/axis/wsComplexData?wsdl Obsérvese que el URL del servicio web se compone de la siguiente forma:

[address]/[service name]?wsdl

Se usó soapUI v3.5 para realizar las pruebas de invocación al servicio web como se puede observar a continuación:



Nótese cómo se arma el XML de invocación al servicio web:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:axis="http://ingmmurillo.blogspot.com/webservices/axis" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
   <soapenv:Header/>
   <soapenv:Body>
      <axis:sendMessage soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <in0>
            <fields>
               <field>
                  <name>FirstName</name>
                  <value>Mauricio</value>
               </field>
               <field>
                  <name>LastName</name>
                  <value>Mauricio</value>
               </field>
            </fields>
            <from>My Blog</from>
            <to>The World</to>
         </in0>
      </axis:sendMessage>
   </soapenv:Body>
</soapenv:Envelope>



Obteniéndose la siguiente respuesta del servicio web publicado en Mule:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:sendMessageResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ingmmurillo.blogspot.com/webservices/axis">
         <sendMessageReturn xsi:type="xsd:string"><![CDATA[<fields><field><name>Nombre</name><value>Mauricio</value></field><field><name>Apellido</name><value>Mauricio</value></field><from>Blog</from><to>El mundo</to></fields>]]></sendMessageReturn>
      </ns1:sendMessageResponse>
   </soapenv:Body>
</soapenv:Envelope>

miércoles, 21 de julio de 2010

Java otra vez Nro. 1 en los índices de TIOBE

De acuerdo a los índices de TIOBE para la comunidad de programadores, Java ha recuperado su posición Nro. 1 después de haber bajado su posición hace unos meses. Esto es un buen indicio de que se está retornando la calma a la comunidad Java después de la adquisición de Oracle a Sun Microsystems.

Para el primer semestre del año 2010, los índices de popularidad son:

Ganadores
  1. C (+2.3%)
  2. Java (+1.2%)
  3. Objective-C (+1.1%)
Perdedores
  1. Visual Basic (-1.8%)
  2. PHP (-1.5%)
  3. Go (-0.8%)
En la siguiente tabla se muestran los resultados de índices de popularidad para el mes de Julio.

lunes, 28 de junio de 2010

Cómo exponer un servicio web en Mule 2 usando Apache Axis

Para crear servicios web existen 2 estilos de desarrollo:
  1. Contract-Last. Se comienza con el código Java y se genera el contrato del servicio web (WSDL) a partir de éste.
  2. Contract-First. Se comienza con el contrato del servicio web (WSDL) y se usa Java para implementar dicho contrato.
Mule 2 provee de dos tecnologías para trabajar con servicios web: Apache Axis y Apache CXF. En éste post explicaré como exponer un servicio web en Mule usando Apache Axis y el estilo de desarrollo Contract-Last.

En el siguiente código expondré un servicio web muy simple que solicita como entrada un nombre y un apellido y devuelve de respuesta una cadena de texto. Para trabajar con el estilo de desarrollo  Contract-Last, primero se debe de partir con la codificación Java, creando una interface con la firma de o los métodos a exponer en el servicio web y una o varias clases que implementen la interface como se muestra a continuación:


Interface HelloAxis

package com.blogspot.ingmmurillo.axisws;

public interface HelloAxis {

    public String helloAxis(String firstName, String lastName);

}

Clase HelloAxisImpl

package com.blogspot.ingmmurillo.axisws;

public class HelloAxisImpl implements HelloAxis {

    public String helloAxis(String firstName, String lastName) {

        String greeting = "Welcome to Axis " + firstName + " " + lastName;

        return greeting; 
    }
}


Una vez que se tenga codificado el código Java se usará la siguiente configuración en Mule para exponer el servicio web usando Axis, es decir para que Mule genere automáticamente el contrato (WSDL).

Configuración en Mule

<service name="helloaxis">
            <inbound>
                <axis:inbound-endpoint
                        address="http://localhost:8282/webservices/axis"
                        serviceNamespace="http://ingmmurillo.blogspot.com/webservices/axis"
                        synchronous="true">
                    <axis:soap-method method="helloAxis">
                        <axis:soap-parameter parameter="firstName" type="string" mode="IN"/>
                        <axis:soap-parameter parameter="lastName" type="string" mode="IN"/>
                        <axis:soap-return type="string"/>
                    </axis:soap-method>
                </axis:inbound-endpoint>
            </inbound>
            <component class="com.blogspot.ingmmurillo.axisws.HelloAxisImpl"/>
        </service>


En la siguiente captura de pantalla se muestra comó se consumiría el servicio web, las parámetros de entrada y la respuesta del mismo usando el cliente de servicios web SoapUI. Tomése en cuenta que la invocación al WSDL es de la siguiente forma: http://localhost:8282/webservices/axis/helloaxis?wsdl


    jueves, 3 de junio de 2010

    Cómo verificar la versión del JDK con el cúal se compilo una clase

    Existen 2 formas para verificar la versión del JDK (Java Development Kit) con el cúal fue compilada una clase.
    1. Usando el comando javap
    2. Codificando en Java para leer los 8 primeros bytes, usando clases del paquete java.io
    Los archivos de clase Java (.class) tienen 3 elementos iniciales importantes que se encuentran distribuídos en los primeros 8 bytes del archivo.


    4 Bytes
    2  Bytes
    2 Bytes
    Número Mágico
    Versión Menor
    Versión Mayor
    0xCAFEBABE
    {0,3}
    {45,46,47,48,49,50}
    11001010111111101011101010111110
     
    Los primeros 4 bytes corresponden a un número único que identifica que el archivo corresponde a un archivo de clase Java, éste número se lo conoce como número mágico y en hexadecimal corresponde al número  0xCAFEBABE.
    Los 2 bytes siguientes representan la versión menor  y los 2 bytes subsiguientes representan la versión mayor del JDK con el cuál fue compilada la clase. En la siguiente tabla se describen las versiones de la plataforma Java:


    Minor Version
    Major Version
    Java Platform
    Version
    Release Date
    3
    45
    1.0
    23-ENE-1996
    3
    45
    1.1
    19-FEB-1997
    0
    46
    1.2
    08-DIC-1998
    0
    47
    1.3
    08-MAY-2000
    0
    48
    1.4
    06-FEB-2002
    0
    49
    1.5
    30-SEP-2004
    0
    50
    1.6
    11-DIC-2006
      Utilización del comando javap

    Para utilizar el comando javap, es necesario abrir la consola de comandos del sistema operativo y ubicarse en dónde se encuentra el archivo de clase compilado, por ejemplo: suponiendo que la clase MiClase.class se encuentre en el paquete com.mypackage, el comando se usaría de la siguiente forma:

    javap -verbose MiClase

    Y se obtendría el siguiente resultado.



    Como se puede observar aquí se muestra los valores de minor version y major version, con los cuáles se pueden identificar con cuál JDK fue compilada la clase. 

    Código fuente para leer los 8 primeros bytes del archivo de clase

    Adicional al comando se podría usar el siguiente code snippet para leer los 8 bytes del archivo de clase Java:

    try {
    
        String nombreArchivo = "c:\java\src\com\mypackage\MiClase.class";
        DataInputStream in = new DataInputStream(new FileInputStream(nombreArchivo));
    
        int numeroMagico = in.readInt();
        
        if (numeroMagico != 0xCAFEBABE) {
            System.out.println(nombreArchivo + " no es una clase valida...");
        }
    
        int versionMenor = in.readUnsignedShort();
        int versionMayor = in.readUnsignedShort();
    
        System.out.println("major version = " + versionMayor);
    
        in.close();
    
    } catch (IOException e) {
        System.err.println(e);
    }
    
    

    martes, 1 de junio de 2010

    Cumpleaños Nro. 15 de Java

    James Gosling, uno de los creadores de la plataforma Java, publica en su blog que Java cumple hoy 15 años. Durante éste tiempo Java ha evolucionado bastante, lo que sí me preocupa es cómo ha caído la popularidad en los últimos años según los índices de TIOBE. Sin embargo, el futuro y destino de Java sigue en manos de nosotros los desarrolladores de software y sobre todo de las decisiones que Oracle tome para que Java siga cumpliendo muchísimos años más.


    HAPPY 15th BIRTHDAY JAVA!!!!!


    viernes, 21 de mayo de 2010

    Tarea de Ant para generar clientes de servicios web usando Apache Axis

    A continuación comparto la tarea de Apache Ant para poder crear los client stubs para consumir servicios web usando Apache Axis.

    La última versión de Apache Axis es la v1.4, se lo puede descargar del siguiente link: http://www.apache.org/dyn/closer.cgi/ws/axis/1_4

    La tarea de Ant para crear los client stubs de un servicio web es la siguiente:

    <property name="axis.home" location="${lib.home}/apache-axis-1.4"/>
    
        <target name="axis-generate-client-stubs" depends="init"
                description="Generate the client stubs for a web service">
            <path id="axis.path">
                <fileset dir="${axis.home}/lib">
                    <include name="*.jar"/>
                </fileset>
            </path>
            <java classname="org.apache.axis.wsdl.WSDL2Java" fork="true">
                <arg value="-client"/>
                <arg value="-o"/>
                <arg value="${javaproject.home}/src-generated"/>
                <arg value="http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"/>
                <arg value="-p"/>
                <arg value="com.myapplication.webservices"/>
                <classpath>
                    <path refid="axis.path"/>
                </classpath>
            </java>
        </target>
    
    

    En dónde:

    •  axis.home direcciona al directorio que contiene las librerías de Apache Axis
    •  -o  para configurar la ubicación en dónde se crearán las clases Java para el cliente del servicio web, en éste ejemplo: ${javaproject.home}/src-generated
    • La URL dónde se encuentra publicado el servicio web, en éste caso:  http://www.webservicex.net/CurrencyConvertor.asmx?WSDL
    • -p para definir el paquete Java en el cuál se crearán las clases del cliente del servicio web, por ejemplo: com.myapplication.webservices

    lunes, 17 de mayo de 2010

    Consulta de Estadísticas en los metadatos de BusinessObjects Data Integrator

    Otra vez trabajando con las herramientas de BusinessObjects me encontré con la necesidad de consultar las estadísticas de Data Integrator directamente en el repositorio de metadatos.

    La versión del repositorio con la cuál expongo el siguiente ejemplo es:

    BODI-20031: The local repository version: 11.5.2.0000

    Al consultar directamente en las tablas del repositorio de metadatos puedo conocer la historia de las ejecuciones de los flujos de datos y el detalle de ejecución de los mismos. Por ejemplo, es posible conocer el nombre del flujo de datos (dataflow), el nombre del objeto, eltipo, el número de registros cargados y el tiempo de ejecución.

    Para realizar la consulta de las estadísticas se puede usar la siguiente consulta SQL:

    select dataflow_name, object_name, object_type, execution_time as exec_time, row_count from (
    select  
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '2' and x.key2 = y.key2) as object_name,
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '3' and x.key2 = y.key2) as object_type,
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '4' and x.key2 = y.key2) as row_count,
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '5' and x.key2 = y.key2) as start_time,
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '6' and x.key2 = y.key2) as end_time,
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '7' and x.key2 = y.key2) as execution_time,
             (select x.value from al_statistics x 
             where x.object_key = y.object_key and x.seqnum= '8' and x.key2 = y.key2) as dataflow_name
    from al_statistics y
    where y.object_key = '5' and y.seqnum= '8' 
    )  order by dataflow_name; 

    En donde object_key hace referencia a la clave primaria de la tabla al_history. Para consultar ésta tabla se puede usar la siguiente consulta SQL:


    select object_key,service,start_time,end_time, status, has_error from al_history order by object_key desc;
    

    martes, 11 de mayo de 2010

    Cómo eliminar un salto de línea LF(Line feed, '\n', 0x0A, 10 en decimal) en los datos de una columna de Oracle

    Muchas veces nos encontramos con columnas de tipo de dato VARCHAR con valores que poseen saltos de línea (LF - Line Feed). Por ejemplo, supongamos que se tiene la siguiente tabla de base de datos, creada con el siguiente script SQL:

    CREATE TABLE TABLA (COLUMNA VARCHAR2(128));
    INSERT INTO TABLA VALUES ('MAURICIO MURILLO' || CHR(10) || 'INGMMURILLO');
    COMMIT;
    SELECT * FROM TABLA;
    

    Al consultar el registro de la tabla se obtendrá lo siguiente:








    Como se puede observar, los datos de la columna COLUMNA contienen un salto de línea representado por /n. Para reemplazar los saltos de línea que se encuentren en la cadena de texto por un espacio en blanco se usa la función SQL REPLACE como se muestra a continuación:

    SELECT 
    REPLACE(REPLACE(REPLACE(COLUMNA,CHR(10),' ') ,CHR(13),' ') ,'  ',' ') AS COLUMNA_NUEVA FROM TABLA;
    


    El script SQL anterior me permitirá reemplazar los saltos de línea por espacios en blanco.


    lunes, 3 de mayo de 2010

    Criterios de decisión para una solución de integración

    Algunos de los siguientes son criterios de decisión para construir soluciones de integración. Tomado del libro de Gregor Hohpe y Bobby Woolf, Enterprise Integration Patterns.
    1. Acoplamiento de aplicaciones. Las aplicaciones que se integran tienen que minimizar sus dependencias (Loosely Coupled)
    2. Soluciones NO INTRUSIVAS. Se tiene que minimizar los cambios en las aplicaciones y en el código de integración.
    3. Tecnología.
    4. Formato de datos. Acordar el formato de datos con el que se transportarán los mensajes.
    5. Tiempo y tamaño. Minimizar el tiempo de intercambio de datos, intercambiarlos frecuentemente y en fracciones pequeñas.
    6. Decidir sí la integración será de datos o funcionalidad (procesos)
    7. Comunicación Remota. Una solución asíncrona puede ser más eficiente pero se convierte en compleja de diseñar, desarrollar y depurar.
    8. Confiabilidad. Las soluciones de integración tienen que ser confiables. Se tiene que asegurar el despacho de todos los mensajes que se transporten.

    jueves, 29 de abril de 2010

    Estrés Informático

    Leyendo algo de noticias en la red, me encontré con el término "estrés informático", primera vez que escucho el término pero que su definición tiene mucho que ver con lo que realmente suele pasar a los usuarios de los sistemas informáticos.

     Algunas de las causas del estrés informático en los usuarios son las siguientes:
    • El sistema es lento, no se tiene una respuesta rápida
    • No se abren las páginas web
    • No se puede imprimir
    • No se cargó correctamente los datos para generar un reporte
    • No sé cómo usar bien el sistema, tengo muchos pasos que seguir
    • Interfaces no amigables,
    • La información se pierde, no hay consistencia, etc. etc. etc.

    Estas causas y muchísimas más, son el pan de cada día, cuando se da soporte técnico de un sistema informático. Pero realmente, ¿nos preocupamos por el estrés informático en los usuarios? Un buen porcentaje o me atrevería a decir casi todos responderíamos que NO.

    El estrés informático en un usuario causa desmotivación, falta de productividad y mala actitud. Como diseñadores y programadores de software deberíamos hacer lo imposible para evitar que los sistemas informáticos que construyamos se conviertan en la fuente de estrés de nuestros usuarios. Es importante que las herramientas de software que construyamos se conviertan en aceleradores de los procesos de una empresa y no en sus frenos.

    viernes, 23 de abril de 2010

    Web Frameworks Timeline

    Comparto una línea del tiempo de los frameworks web que han aparecido en toda ésta decada. Realmente es muy complejo decidir cuál es el mejor framework web, considero que depende de muchos aspectos. Por ejemplo, cómo decir que un framework web es el mejor sin una herramienta que lo respalde.

    El siguiente gráfico que comparto fue realizado por Matt Raible, y publicado en DZone, considero que es de mucha utilidad y muy informativo.

    miércoles, 21 de abril de 2010

    Lectura de un archivo de propiedades que se encuentra dentro de un mismo JAR

    El siguiente código de Java sirve para leer un archivo de propiedades que se encuentra en un mismo JAR. Por ejemplo, sí se tiene el archivo de Java my-app-0.0.1.jar y dentro de éste un archivo de propiedades de nombre config.properties como se muestra a continuación:

    my-app-0.0.1.jar
    |_ META-INF
       |_ config.properties

    El siguiente código me permitirá leer el archivo de propiedades y obtener una propiedad del mismo:

    try {
    
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("META-INF/config.properties");
        Properties props = new Properties();
        String wsURL = null;    
    
        if (inputStream != null) {
            props.load(inputStream);
            wsURL = props.getProperty("myApp.webServiceURL");
            inputStream.close();   
        }
    } catch(IOException e) {}
    

    Convertir un objeto GregorianCalendar a XMLGregorianCalendar

    Cuando se trabaja con servicios web en Java las fechas son manejadas a través de instancias de la clase javax.xml.datatype.XMLGregorianCalendar. Sin embargo, generalmente se trabaja con instancias de la clase java.util.GregorianCalendar para trabajar con fechas.

    Al generar un client stub para un servicio web usando Apache Axis los tipos de dato fecha del WSDL se mapean a objetos del tipo XMLGregorianCalendar. Sí se dispone de un objeto GregorianCalendar con el siguiente código se puede realizar la conversión a un objeto del tipo XMLGregorianCalendar.

    try {
    
    GregorianCalendar fechaX = new GregorianCalendar();
    fechaX.setTime(objetoTipoDate);
    XMLGregorianCalendar fechaXML = DatatypeFactory.newInstance().newXMLGregorianCalendar(fechaX);
    
    } catch (DatatypeConfigurationException e) {}
    

    jueves, 15 de abril de 2010

    James Gosling abandona Oracle

    James Gosling, conocido como el padre de Java, ha decidido abandonar Oracle, después de que el proceso de transición entre Sun y Oracle finalizó hace un par de meses. Realmente es preocupante como Oracle está perdiendo a personas claves que aportaron y trabajaron por la tecnología Java. James, menciona en su blog lo siguiente:

    "Yes, indeed, the rumors are true: I resigned from Oracle a week ago (April 2nd). I apologize to everyone in St Petersburg who came to TechDays on Thursday expecting to hear from me. I really hated not being there. As to why I left, it's difficult to answer: Just about anything I could say that would be accurate and honest would do more harm than good. The hardest part is no longer being with all the great people I've had the privilege to work with over the years. I don't know what I'm going to do next, other than take some time off before I start job hunting."

    Good Luck James, 




    miércoles, 14 de abril de 2010

    Índices de popularidad de lenguajes de programación TIOBE - ABRIL 2010

    TIOBE, ha publicado sus índices de popularidad de lenguajes de programación para lo que va de éste mes [1]. Es preocupante apreciar como el lenguaje de programación Java ha ocupado el 2do lugar, y su tendencia en popularidad está a la baja. Sinceramente desconozco cómo sea la forma de trabajar y operar de Oracle, pero lo que sí me preocupa es que está perdiendo poco a poco talentos clave que pertenecían al difunto Sun, como son Sang Shin, Jonathan I. Schwartz, por nombrar algunos. Adicional a ésto leí también que James Gosling, "Java Father" ha decidido abandonar el JCP (Java Community Process) mencionando que se ha convertido en un infierno político ("political nightmare")[2]. Comparto la tabla de índices de popularidad de TIOBE y las tendencias hasta Abril 2010.




    [1] http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
    [2] http://www.theserverside.com/news/thread.tss?thread_id=59920

    jueves, 1 de abril de 2010

    Conexión a una base de datos Oracle usando JDBC OCI

    En el siguiente artículo explico cómo configurar Mule para conectarse a una base de datos Oracle usando las librerías de Oracle Instant Client.

    1. Descargar Oracle Instant Client para la plataforma sobre la cuál se va a trabajar.
        http://www.oracle.com/technology/software/tech/oci/instantclient/index.html

       NOTA: Para Oracle 10g sobre plataforma Windows, descargar del siguiente link:
       http://download.oracle.com/otn/nt/instantclient/10204/instantclient-basic-win32-10.2.0.4.zip

    2. Una vez descargado, descomprimir el archivo.
    3. Copiar las siguientes DLLs al directorio MULE_HOME/lib/boot
    • oraociei10.dll
    • oci.dll
    • oraocijdbc10.dll
    • orannzsbb10.dll
    4. Copiar el JDBC ojdbc14.jar al directorio MULE_HOME/lib/user
    5. Incluir el Spring Bean y el conector JDBC en el archivo de configuración de MULE.


    <?xml version="1.0" encoding="UTF-8"?>
    <mule 
    ... >
    <spring:bean id="oracleDataSource" class="oracle.jdbc.pool.OracleOCIConnectionPool" destroy-method="close">
            <spring:property name="user" value="user"/>
            <spring:property name="password" value="password"/>
            <spring:property name="URL" value="jdbc:oracle:oci:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 192.168.10.196)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = DBNAME)))"/>
            <spring:property name="poolConfig" ref="oraclePoolProperties"/>
    
        </spring:bean>
    
        <spring:bean id="oraclePoolProperties"
                     class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <spring:property name="properties">
                <spring:props>
                    <spring:prop key="connpool_min_limit">1</spring:prop>
                    <spring:prop key="connpool_max_limit">5</spring:prop>
                    <spring:prop key="connpool_increment">2</spring:prop>
                    <spring:prop key="connpool_timeout">10</spring:prop>
                    <spring:prop key="connpool_nowait">true</spring:prop>
                </spring:props>
            </spring:property>
        </spring:bean>
    ...
    <jdbc:connector name="OracleJDBCOCIConnector" dataSource-ref="oracleDataSource">
        </jdbc:connector>
    ...
    </mule>
    

    jueves, 25 de marzo de 2010

    Desconferencia realizada en el barcamp Quito, Ecuador 2010 - Detalles

    Estuvo interesante la desconferencia que di en el barcamp 2010, fue mi primera experiencia en éste tipo de eventos, pero siento que todo salio bien. Expuse sobre el tema de "Integrando aplicaciones en Mule", hablé sobre ESBs, Mule, su arquitectura y su configuración.

    El ejemplo que se mostró fue sobre la integración de una aplicación heredada (archivos planos), con un web service que convertía monedas, y una base de datos para un Data Warehouse.

    Mule permite integrar varias tecnologías y protocolos de forma fácil ya que ofrece a los desarrolladores mucha de ésta lógica abstraída en los tags XML de su archivo de configuración. Además, Mule separa la lógica del negocio de la lógica de mensajería, haciendo énfasis en la Reusabilidad y Flexibilidad.

    Resumo las respuestas a las preguntas realizadas sobre la desconferencia.


    1. Sobre BPMs. El ESB es el punto de entrada para una arquitectura SOA, dentro de un modelo de madurez de SOA, el ESB actúa como el backbone o componente de integración, por lo que arriba de éste podrían estar un motor de reglas, un BPM o lo que se requiera.

    2. Sobre BPEL. BPEL es un lenguaje estándar de ejecución de procesos de negocios que tiene relación con los BPMs, entonces al ser el ESB el componente integrador se podría tener un BPM que use BPEL u otro que no de forma independiente.

    3. Sobre la Transaccionalidad. Mule se conecta a través de endpoints, un endpoint podría ser un directorio, una cola de mensajería, un web service, una base de datos, etc. Mule permite controlar la transaccionalidad por endpoint asegurando que una transacción se comprometa siempre y cuando haya llegado desde su enpoint de entrada hasta su endpoint de salida.

    Comparto algunas de las fotos de la desconferencia.


    miércoles, 17 de marzo de 2010

    Desconferencia en el barcamp Quito, Ecuador 2010

    El día sábado 20 de marzo del 2010 estaré exponiendo como desconferencista en el barcamp, el tema de Integración de Aplicaciones con Mule. El barcamp de éste año será en la PUCE, Auditorios de la Torre 1. Les hago llegar una cordial invitación y les comparto las diapositivas con las cuáles estaré exponiendo ese día.

    viernes, 26 de febrero de 2010

    Representación gráfica en UML de las relaciones entre clases básicas

    UML es el lenguaje de modelado de-facto para realizar análisis y diseño orientado a objetos. En el siguiente diagrama realizado a través de la herramienta libre astah* community se resumen las relaciones básicas entre clases y sus notaciones gráficas.

    Las principales relaciones entre clases son:
    1. Agregación. La ClaseA es parte de la ClaseB
    2. Asociación. La ClaseD tiene una ClaseC o la ClaseC tienen una ClaseD
    3. Asociación Directa. La ClaseF tiene una ClaseE
    4. Composición. La ClaseH está compuesta de la ClaseG
    5. Dependencia. La ClaseJ depende de la ClaseI
    6. Generalización. La ClaseL es una ClaseK
    7. Realización. La ClaseH implementa la interface Interface

    viernes, 19 de febrero de 2010

    Estructura de una clase Java

    Una clase básica de Java posee la siguiente estructura:


    Componente
    Palabra Reservada
    Cardinalidad
    1
    Declaración de paquete
    package
    0..1
    2
    Importación de librerías del API de Java o externas
    import
    0..*
    3
    Definición de clase
    [public|package] class NombreClase {...}
    1
    4
    Declaración de variables de instancia
    [public|private|protected] [Dato Primitivo|Referencia] nombreVariable
    0..*
    5
    Definición de constructores
    public NombreClase() {...}
    0..*
    6
    Definición de métodos
    [public|private|protected] [void|Dato Primitivo|Referencia] nombreMetodo
    1..*