martes, 3 de junio de 2014

Importar clases estáticas en Java

Con la finalidad de acceder a métodos estáticos, es necesario especificar la clase de la que ellos provienen. A partir del JDK 1.5, Java nos proporciona un mecanismo que nos permite acceder a miembros estáticos sin la necesidad de especificar la clase a la que pertenecen.
El siguiente ejemplo nos muestra cómo sería un programa normal en Java:
public class Demo {

    public static void main(String[] args) {

        try {
            double r = Math.cos(Math.PI * 5.0);
            System.out.println("El valor de r es = " + r);
        } catch (Exception ex) {
            System.err.println("Error: " + ex);
        }

    }
}
Y utilizando la declaración static import:
import static java.lang.System.out;
import static java.lang.System.err;
import static java.lang.Math.*;

public class Demo {

    public static void main(String[] args) {

        try {
            double r = cos(PI * 5.0);
            out.println("El valor de r es = " + r);
        } catch (Exception ex) {
            err.println("Error: " + ex);
        }

    }
}
La declaración static import es análoga a la declaración import, pues mientras la segunda importa toda clases desde paquetes permitiendo su uso sin la especificación de los paquetes de donde provienen, la declaración static import permite la importación de clases permitiendo el uso de sus miembros estáticos sin la especificación de la clase de la que provienen.

lunes, 2 de junio de 2014

Controlar el tiempo de espera al consumir un webservice

Durante los últimos días, al consumir los Webservice del SRI hemos podido notar que muchas veces se queda en espera sin retornar el objeto de respuesta. Es por eso que es importante controlar el tiempo de espera máximo en nuestra aplicación (Timeout). Para aquellos quienes estén usando el JDK 1.6 este código les servirá para poder establecer un mecanismo de control:
port = service.getRecepcionComprobantesPort();
((BindingProvider) port).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", 5000);
((BindingProvider) port).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 5000);
Espero que este código les sea de utilidad y no se olviden de seguirnos a través de nuestra página en Facebook.

domingo, 1 de junio de 2014

Dibujar circunferencia que pasa por tres puntos en Java

Dados tres puntos no alineados, existe una y solo una circunferencia que pasa por los tres. En este artículo voy a mostrarles la manera cómo poder determinar la ecuación de la circunferencia que pasa por estos puntos de tal forma que podamos graficarla utilizando el API Java2D.

Dada la circunferencia cuya ecuación es:


Y tres puntos que pertenecen a dicha circunferencia:


Al reemplazar los puntos por X e Y obtendremos las siguientes equivalencias [1]:

h = (1/2)((a²+b²)(f-d) + (c²+d²)(b-f) + (e²+f²)(d-b)) / (a(f-d)+c(b-f)+e(d-b)) 
k = (1/2)((a²+b²)(e-c) + (c²+d²)(a-e) + (e²+f²)(c-a)) / (b(e-c)+d(a-e)+f(c-a)) 

Calculando los valores de h y k podemos calcular el valor del radio r hallando la distancia entre los puntos (h,k) y cualquiera de los tres puntos dados inicialmente.


import java.awt.Color;
import java.awt.Graphics2D;

/**
 *
 * @author Rolando
 */
public class Circunferencia {

    private Punto centro;
    private double radio;

    public Circunferencia() {
    }

    public Circunferencia(Punto centro, int radio) {
        this.centro = centro;
        this.radio = radio;
    }

    public Punto getCentro() {
        return centro;
    }

    public void setCentro(Punto centro) {
        this.centro = centro;
    }

    public double getRadio() {
        return radio;
    }

    public void setRadio(double radio) {
        this.radio = radio;
    }

    public void dibujar(Graphics2D g2) {
        int x = (int) centro.getPunto().getX();
        int y = (int) centro.getPunto().getY();
        int r = (int) radio;
        centro.dibujar(g2);
        g2.setColor(Color.red);
        g2.drawOval(x - r, y - r, 2 * r, 2 * r);
    }
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;

/**
 *
 * @author Rolando
 */
public class Punto {

    private Point2D punto;

    public Punto() {
        punto = new Point2D.Double(0, 0);
    }

    public Punto(int x, int y) {
        punto = new Point2D.Double(x, y);
    }

    public Point2D getPunto() {
        return punto;
    }

    public void setPunto(Point2D punto) {
        this.punto = punto;
    }

    public void dibujar(Graphics2D g2) {
        g2.setColor(Color.blue);
        int x = (int) punto.getX();
        int y = (int) punto.getY();
        g2.fillOval(x - 2, y - 2, 4, 4);
    }
}
public static Circunferencia calcularCentro(Punto x1, Punto x2, Punto x3) {
    Circunferencia circunferencia = new Circunferencia();
    double a, b, c, d, e, f, h, k, r;
    a = x1.getPunto().getX();
    b = x1.getPunto().getY();
    c = x2.getPunto().getX();
    d = x2.getPunto().getY();
    e = x3.getPunto().getX();
    f = x3.getPunto().getY();
    h = (0.5) * ((Math.pow(a, 2) + Math.pow(b, 2)) * (f - d) + (Math.pow(c, 2) + Math.pow(d, 2)) * (b - f) + (Math.pow(e, 2) + Math.pow(f, 2)) * (d - b)) / (a * (f - d) + c * (b - f) + e * (d - b));
    k = (0.5) * ((Math.pow(a, 2) + Math.pow(b, 2)) * (e - c) + (Math.pow(c, 2) + Math.pow(d, 2)) * (a - e) + (Math.pow(e, 2) + Math.pow(f, 2)) * (c - a)) / (b * (e - c) + d * (a - e) + f * (c - a));
    r = Math.sqrt(Math.pow((h - a), 2) + Math.pow((k - b), 2));
    circunferencia.setRadio(r);
    circunferencia.setCentro(new Punto((int) h, (int) k));
    return circunferencia;
}

También les comparto el proyecto de Netbeans pues siempre he dicho que un artículo sin código fuente es como un libro sin hojas.


Hasta una próxima publicación y no se olviden de seguirnos a través de nuestra página en Facebook.

sábado, 31 de mayo de 2014

Cálculo de la determinante de una matriz de Orden n

En este artículo voy a mostrarles la manera de calcular la determinante de una matriz de orden n. Cuando la matriz es de orden 2 o 3, es sencillo calcular la determinante pero ya cuando hablamos de matrices de órdenes superiores, apoyarnos en algún algoritmo computacional es una excelente idea. Para éste ejemplo, vamos a calcular al determinante de la siguiente matriz:


La idea es convertir a la matriz mediante operaciones elementales en una matriz triangular equivalente, pues en este caso la determinante estará dada por el producto de todos los términos de la diagonal principal, multiplicada por -1 si se hizo un número impar de cambios.

El algoritmo es el siguiente:

1.- Buscamos la fila con el mayor elemento en valor absoluto de la primera columna. En nuestro ejemplo, el mayor elemento de 1, 2 y 1 es 2, ubicado en la segunda fila. Ahora intercambiamos la segunda fila con la primera obteniendo la siguiente matriz:


2.- Mediante operaciones elementales, hacemos ceros todos los elementos de la primera columna, excepto la primera fila.



Ahora hacemos cero la primera columna de la tercera fila.


3.- Ahora buscamos la fila con el mayor elemento en valor absoluto de la segunda columna, excepto la primera fila pues ya ha sido procesada. En este caso, como ambos son igual, no es necesario hacer un cambio.

4.- Mediante operaciones elementales hacemos ceros todos los elementos de la segunda columna pero sin alterar la primera y segunda fila. Con esto la matriz nos quedaría de la siguiente manera:


Ahora calculamos la matriz multiplicando los elementos de la diagonal. El resultado obtenido es -2 y como el número de cambios fue impar, entonces multiplicamos por .1 obteniendo 2 como resultado final. La implementación en Java de este algoritmo es la siguiente:

public class MatrizUtil {

    public static double[][] intercambiarFilasMatriz(double[][] matriz, int i, int j) {
        double temp;
        for (int k = 0; k < matriz[0].length; k++) {
            temp = matriz[i][k];
            matriz[i][k] = matriz[j][k];
            matriz[j][k] = temp;
        }
        return matriz;
    }

    public static void imprimirMatriz(double[][] matriz) {
        for (int i = 0; i < matriz.length; i++) {
            for (int j = 0; j < matriz[0].length; j++) {
                System.out.print(matriz[i][j] + " ");
            }
            System.out.println("");
        }
    }

    public static int pivoteMatriz(double[][] matriz, int i) {
        int piv = i;
        double v = matriz[i][i];
        for (int j = i + 1; j < matriz.length; j++) {
            if (Math.abs(matriz[j][i]) > v) {
                v = matriz[j][i];
                piv = j;
            }
        }
        return piv;
    }

    /**
     * 
     * @param m es una matriz cuadrada
     * @return 
     */
    public static int eliminaAdelante(double[][] m) {
        int numeroIntercambios = 0;
        int filaPivote = -1;
        for (int columnaEvaluada = 0; columnaEvaluada < m.length; columnaEvaluada++) {
            filaPivote = pivoteMatriz(m, columnaEvaluada);
            if (filaPivote != columnaEvaluada) {
                m = intercambiarFilasMatriz(m, columnaEvaluada, filaPivote);
                numeroIntercambios++;
            }
            for (int i = columnaEvaluada + 1; i < m.length; i++) {
                for (int j = columnaEvaluada + 1; j < m.length; j++) {
                    if (m[columnaEvaluada][columnaEvaluada] == 0) {
                        System.out.println("Error, división por cero");
                        System.exit(1);
                    } else {
                        m[i][j] = m[i][j] - (m[i][columnaEvaluada] * m[columnaEvaluada][j] / m[columnaEvaluada][columnaEvaluada]);
                    }
                }
                m[i][columnaEvaluada] = 0;
            }
        }
        return numeroIntercambios;
    }

    public static double det(double[][] m) {
        int numeroIntercambios = MatrizUtil.eliminaAdelante(m);
        double det = 1;
        for (int i = 0; i < m.length; i++) {
            det *= m[i][i];
        }
        if (numeroIntercambios % 2 == 1) {
            det = -det;
        }
        return det;
    }
}
Ahora, podemos percatarnos que para convertir a cero algunos elementos de la matriz utilizamos una fórmula la cual se muestra a continuación:
m[i][j] = m[i][j] - (m[i][columnaEvaluada] * m[columnaEvaluada][j] / m[columnaEvaluada]
Esta fórmula se obtiene de la siguiente manera:

Dada la matriz:


Para convertir a 0 un determinado elemento debemos hacer la siguiente operación elemental: 


La constante obtenida se aplicará a toda la fila pues es una operación elemental, quedando de la fórmula tal como está en la implementación:


También les comparto el método main de prueba:
public static void main(String[] args) {
    double[][] matriz = {{1, 0, 2}, {2, 1, 1}, {1, 1, 1}};
    System.out.println(MatrizUtil.det(matriz));
}
Espero que este artículo les sea de utilidad, hasta una próxima publicación.

jueves, 29 de mayo de 2014

Verificar la disponibilidad de los webservices del SRI

Muchas veces, mientras desarrollamos nuestras aplicaciones de facturación electrónica, precisamos de saber el estado de los servicios web del SRI. En este artículo les presento una manera de poder verificar su disponibilidad para poder emitir nuestros comprobantes bajo un tipo de emisión normal o en contingencia, según sea el caso. Luego de haber creado nuestro cliente proxy, podemos hacer uso de las clases que se generan para poder determinar el estado de conexión mediante el siguiente método:
public static Object getWebService(String wsdlLocation) {
    try {
        QName qname = new QName("http://ec.gob.sri.ws.recepcion", "RecepcionComprobantesService");
        URL url = new URL(wsdlLocation);
        RecepcionComprobantesService service = new RecepcionComprobantesService(url, qname);
        return null;
    } catch (MalformedURLException ex) {
        return ex;
    } catch (WebServiceException ws) {
        return ws;
    }
}

public static boolean existeConexion(String url) {
    int i = 0;
    boolean respuesta = false;
    while (i < 3) {
        Object obj = getWebService(url);
        if (obj  == null) {
            return true;
        }
        if ((obj  instanceof WebServiceException)) {
            respuesta = false;
        }
        i++;
    }
    return respuesta;
}
El código podemos ejecutarlo de la siguiente manera:
public static void main(String[] args) {
    System.out.println(existeConexion("https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantes?wsdl"));
}
Espero que este método les sea de utilidad. No se olviden de seguirnos a través de nuestra página en Facebook.

martes, 27 de mayo de 2014

Implementación en Java de un perceptrón simple

Un perceptrón es la unidad básica de inferencia, siendo capaz de realizar tareas de clasificación de forma automática. En la red podemos encontrar bastante información relacionada al perceptrón simple, sin embargo en este artículo vamos a poner énfasis en su implementación utilizando el lenguaje Java. La arquitectura básica de un perceptrón es la que se muestra a continuación:


Vamos a describir el algoritmo que emplearemos para implementar nuestro perceptrón simple. En primer lugar vamos a conocer cuáles son las entradas; la siguiente imagen muestra los inputs de nuestro algoritmo.


La constante de proporcionalidad η es un parámetro positivo que se llama tasa de aprendizaje puesto que cuanto mayor es, más se modifica el peso sináptico y viceversa. Es decir, es el parámetro que controla el proceso de aprendizaje. Cuando es muy pequeño la red aprende poco a poco. Cuando se toma constante en todas las iteraciones, η(k) =η > 0 tendremos la regla de adaptación con incremento fijo.

También podemos notar que tanto los vectores de pesos como de valores de entrada tienen como cantidad de elementos a n+1. Esto se debe a que hemos agregado al nivel de umbral como una entrada más. El umbral se puede considerar como el peso sináptico correspondiente a un nuevo sensor de entrada que tiene siempre una entrada igual a Xn+1=−1 y como peso sináptico el valor del umbral.

Ahora vamos a empezar con la inicialización de variables. Recordemos que es muy importante incializar nuestro vector de pesos siempre con valores diferentes en cada ejecución del programa.


Y el proceso queda descrito de la siguiente manera:


Y ahora la codificación:
public class Perceptron {

    private double[] pesos;
    private double[] objetivos;
    private double[][] entradas;
    private int numeroEntradas;
    private static final double TASA_APRENDIZAJE = 0.5d;

    public double[][] getEntradas() {
        return entradas;
    }

    public void setEntradas(double[][] entradas) {
        this.entradas = entradas;
        this.numeroEntradas = entradas[0].length;
    }

    public double[] getObjetivos() {
        return objetivos;
    }

    public void setObjetivos(double[] objetivos) {
        this.objetivos = objetivos;
    }

    public double[] getPesos() {
        return pesos;
    }

    public void setPesos(double[] pesos) {
        this.pesos = pesos;
    }

    /**
     * Inicializar los pesos sinápticos con números aleatorios del intervalo [-1, 1]
     */
    public void inicializarPesos() {
        pesos = new double[numeroEntradas];
        for (int i = 0; i < numeroEntradas; i++) {
            pesos[i] = Math.random();
        }
    }

    public void imprimirPesos() {
        for (int i = 0; i < numeroEntradas; i++) {
            System.out.println("W[" + i + "] = " + pesos[i]);
        }
    }

    /**
     * wj(k+1)=wj(k)+&#951;[z(k)&#8722;y(k)]xj(k), j =1,2,...,n+1
     */
    public void recalcularPesos(int posicionEntrada, double y) {
        for (int i = 0; i < pesos.length; i++) {
            pesos[i] = pesos[i] + TASA_APRENDIZAJE * (objetivos[posicionEntrada] - y) * entradas[posicionEntrada][i];
        }
    }

    public void entrenar() {
        int indice = 0;
        double yi = 0;
        while (indice < entradas.length) {
            double suma = 0;
            for (int i = 0; i < numeroEntradas; i++) {
                suma += (pesos[i] * entradas[indice][i]);//&#8721; x[i] * W[i] 
            }
            yi = suma >= 0 ? 1 : -1;
            if (yi == objetivos[indice]) {
                //Correcto
                for (int i = 0; i < numeroEntradas; i++) {
                    System.out.print(entradas[indice][i] + "t");
                }
                System.out.print(" => Esperada = " + objetivos[indice] + ", Calculada = " + yi + "n");
            } else {
                //Incorrecto
                for (int i = 0; i < numeroEntradas; i++) {
                    System.out.print(entradas[indice][i] + "t");
                }
                System.out.print(" => Esperada = " + objetivos[indice] + ", Calculada = " + yi + " [Error]n");
                System.out.println("Corrección de pesos");
                recalcularPesos(indice, yi);
                imprimirPesos();
                System.out.println("--");
                indice = -1;
            }
            indice++;
        }
    }
}
Ahora hagamos una prueba con entrenando a nuestro perceptrón para que reconozca la función lógico OR, tal como se tabula a continuación:

Para esto desarrollamos una clase de prueba.
public class Test {

    public static void main(String[] args) {
        Perceptron p = new Perceptron();
        //Salidas esperadas
        double[] objetivos = {1, 1, 1, -1};
        //Entradas
        //x1, x2, &#952;
        double[][] entradas = {
            {1, 1, -1},
            {1, -1, -1},
            {-1, 1, -1},
            {-1, -1, -1}
        };
        p.setEntradas(entradas);
        p.setObjetivos(objetivos);
        p.inicializarPesos();
        p.entrenar();
        System.out.println("********** Pesos Finales **********");
        p.imprimirPesos();
    }
}
Obteniendo el siguiente resultado:
1.0 1.0 -1.0  => Esperada = 1.0, Calculada = 1.0
1.0 -1.0 -1.0  => Esperada = 1.0, Calculada = -1.0 [Error]
Corrección de pesos
W[0] = 1.9944020684085446
W[1] = -0.4272180776608493
W[2] = -0.3794857322622548
--
1.0 1.0 -1.0  => Esperada = 1.0, Calculada = 1.0
1.0 -1.0 -1.0  => Esperada = 1.0, Calculada = 1.0
-1.0 1.0 -1.0  => Esperada = 1.0, Calculada = -1.0 [Error]
Corrección de pesos
W[0] = 0.9944020684085446
W[1] = 0.5727819223391507
W[2] = -1.3794857322622547
--
1.0 1.0 -1.0  => Esperada = 1.0, Calculada = 1.0
1.0 -1.0 -1.0  => Esperada = 1.0, Calculada = 1.0
-1.0 1.0 -1.0  => Esperada = 1.0, Calculada = 1.0
-1.0 -1.0 -1.0  => Esperada = -1.0, Calculada = -1.0
********** Pesos Finales **********
W[0] = 0.9944020684085446
W[1] = 0.5727819223391507
W[2] = -1.3794857322622547
Con los pesos finales, tenemos a nuestra red neuronal entrenada. Los campos de aplicación del perceptrón simple son muy reducidos pues su aprendizaje llega a un estado de convergencia solo cuando los elementos separables y los no separables pueden ser llevados a un plot en el cual puedan ser separados por un hiperplano. En la siguiente imagen, el caso a sí puede ser aprendido por un perceptrón simple mientras que el caso b no podría ser aprendido por un solo perceptrón. 


Espero que este articulo les sea de utilidad. Cualquier consulta, no duden en comentarla.

sábado, 24 de mayo de 2014

Creación de un datasource en Websphere Application Server

IBM WebSphere Application Server (WAS, servidor de aplicaciones WebSphere),un servidor de aplicaciones de software, es el producto estrella dentro de la familia WebSphere de IBM. WAS está construido usando estándares abiertos tales como J2EE, XML, y Servicios Web[1].
En éste artículo veremos, paso a paso, la manera cómo crear un origen de datos en este servidor de aplicaciones.


Entramos a seguridad luego seguridad global.


Luego jaas y datos de autenticación de j2c.


Aquí le damos click en nuevo.


Y se desplega una ventana donde llenar data para autenticar con el Server.


Le damos aceptar y luego nos lleva a la pantalla anterior donde le damos guardar.


Luego nos vamos a recursos → jdbc → proveedores de jdbc.


Click en nuevo y llenamos el formulario, en este caso es una db oracle.


Click en siguiente y nos aparece una pantalla donde debemos dar la ruta para el jar oracle, en este caso uso oracle6.jar y lo ubicaremos en el disco D.


Click en siguiente y veremos la configuración.


Click en finalizar y luego en la nueva ventana click en guardar.


Luego en jdbc → origenes de datos.


Click en nuevo y llenamos el formulario


Click en siguiente y elegir un proveedor de jdbc, en este caso ya tengo 2 y puedo usar cualquiera.


Click en siguiente y ahora nos pedirá la ruta de nuestra base de datos en el campo valor colocamos toda la ruta.


Click en siguiente y sólo llenamos el primer y ultimo campo.


Click en siguiente.


Click en finalizar y en la nueva pantalla guardar.


Y ya tenemos configurado nuestro Websphere Application Server. Gracias a nuestro colaborador Larry Valderrama.

jueves, 22 de mayo de 2014

Introducción a Scheme y la Programación Funcional

Scheme es un lenguaje de programación basado en el paradigma funcional, es uno de los dialectos más conocidos de Lisp y la esencia de su implementación se basa en el siguiente principio: "Los lenguajes no se deberían desarrollar añadiendo muchas características, sino quitando las debilidades y las limitaciones que hacen que las características adicionales parezcan necesarias". Para poder comprender a este lenguaje es importante entender el concepto de lista que, si bien es cierto no es la única estrucutura de datos, sí es la más importante.

En este primer artículo mostraré el uso de algunos conceptos básicos como son los operadores, las condicionales y la recursión, los cuales servirán para familiarizarnos un poco con la sintaxis de Scheme.

1.- El clásico ejemplo del factorial de un número
En este ejemplo podemos apreciar el uso de la ejecución condicional a través de la función cond cuya sintaxis es la siguiente:

(cond (<condition1> <result1>)
(<condition2> <resultt2>) …
(<conditionn> <resultn>)
(else <else-result>) ;optional else clause
)
(define (factorial n)
  (cond ((= n 1) 1)
        (else (* n (factorial (- n 1))))
        )
  )
2.- Sumatoria desde 1 hasta n
(define (suma n)
  (cond ((= n 0) 0)
        (else (+ n (suma (- n 1))))
    )
  )
3.- Valor absoluto
(define (valor_absoluto x)
  (cond ((< x 0) (* -1 x))
        (else x)
        )
  )
4.- Longitud de una lista
(define (longitud x)
  (cond ((null? x) 0)
        (else (+ 1 (longitud (cdr x))))
  )
  )
5.- Sumatoria de los elementos de una lista
La función car devuelve el primer elemento de una lista.
(define (suma_lista x)
  (cond ((null? x) 0)
        (else (+ (car x) (suma_lista (cdr x))))
    )
  )
6.- Concatenación de dos listas
(define (concatenar x y)
  (cond ((null? x) y)
        (else (cons (car x)
                    (concatenar (cdr x) y)
               )
              )
        )
 )
7.- Determinar si un elemento es atómico
(define (atom? x)
 (cond ((symbol? x) #t)
 ((number? x) #t)
 ((char? x) #t)
 ((string? x) #t)
 ((null? x) #t)
 (else #f)
 )
 )
8.- Contar la cantidad de elementos atómicos de una lista
(define (cantidad_elementos_atomicos x)
  (cond ((null? x) 0)
        ((atom? x) 1)
        (else (+ (cantidad_elementos_atomicos (car x)) (cantidad_elementos_atomicos (cdr x))
                 )
              )
    )
  )
En un siguiente artículo hablaremos acerca del lenguaje de programación Racket, el cual usaremos para implementar fractales.

lunes, 28 de abril de 2014

Configurando Log4j en Eclipse

Log4j es una biblioteca open source desarrollada en Java por la Apache Software Foundation que permite a los desarrolladores de software elegir la salida o appender (FileAppender, RollingFileAppender, SocketAppender, SMTPAppender, JDBCAppender, ConsoleAppender), el formato o layaout (SimpleLayout, PatternLayout, HTMLLayout, XMLLayout) y el nivel (OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL) de los mensajes o “logs” (data logging) a tiempo de ejecución y no a tiempo de compilación, como es comúnmente realizado, mediante el uso de archivos de configuración externos [1].

Configurando Log4j
La API es de fácil configuración; en este artículo les mostraré la manera de hacerlo a través de un archivo de propiedades de Java llamado log4j.properties. Debemos crear el archivo log4j.properties en la raíz de nuestro proyecto.


Vamos a configurar un archivo de propiedades bajo el siguiente escenario: Los archivos de log se van a ir creando de manera diaria, guardando el log de los 10 últimos días. El tamaño máximo de los archivos de log será de 10 MB y la manera en que éstos serán nombrados, será bajo el patrón [nombre_archivo].yyyy-mm-dd quedando el archivo de configuración tal como se muestra a continuación:
# Log4j configuration file.
log4j.rootCategory=DEBUG,A4,stdout

#
# stdout is ConsoleAppender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=[%d] [%C{1}.%M(%L)] - %-5p - %m%n

#
# A4 is a DailyRollingFileAppender
log4j.appender.A4=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A4.file=D:\\log\\prueba.log
log4j.appender.A4.MaxFileSize=10000KB

#
# Keep three backup files.
log4j.appender.A4.MaxBackupIndex=10
log4j.appender.A4.datePattern='.'yyyy-MM-dd
log4j.appender.A4.append=true
log4j.appender.A4.layout=org.apache.log4j.PatternLayout
log4j.appender.A4.layout.ConversionPattern=[%d] [%c.%M(%L)] - %-5p - %m%n
El código fuente para poder probar la configuración anterior es el siguiente:
import org.apache.log4j.Logger;

public class Main {

 public static void main(String[] args) {
  Logger logger = Logger.getLogger("log_file");
  logger.debug("Hola mundo");
  try {
   int a = 1/0;
   System.out.println(a);
  } catch (Exception e) {
   logger.debug(e);
  }
 }
}
Los archivos de log se deberían ir generando tal como se muestra en la siguiente imagen:


Como pueden ver, modificando el archivo de propiedades, podemos modificar el nivel de errores que se van a ir mostrando, para un pase a producción por ejemplo. El enlace de descarga de la librería es la siguiente: http://www.apache.org/dyn/closer.cgi/logging/log4j/2.0-rc1/apache-log4j-2.0-rc1-bin.tar.gz

Espero que este artículo les sea de utilidad y ya saben, cualquier consulta, no duden en comentarla. No olviden tampoco de seguirnos a través de nuestra página en Facebook.

jueves, 13 de marzo de 2014

Polimorfismo en métodos sobrescritos

El polimorfismo es un concepto importante de la programación orientada a objetos (POO) que nos dice que podemos implementar clases que compartan una lógica en común. Esto está muy asociado a la herencia, que es otro concepto de la POO, que nos permite estructurar esquemas de jerarquía en la implementación de nuestros aplicaciones en Java.

Como parte del examen de certificación OCPJP de Oracle, el polimorfismo y herencia son dos de los temas que más repeticiones tienen a lo largo de dicho examen. En este artículo vamos a tratar acerca de las clásicas preguntas de polimorfismo en métodos sobrescritos.

Supongamos que tenemos el siguiente escenario:
package com.rolandopalermo.test01;

class Vehiculo {
 
 public void imprimirSonido() {
  System.out.println("Vehiculo");
 }
 
 public void frenar() {
  System.out.println("frenar");
 }
}

class Carro extends Vehiculo {
 
 public void imprimirSonido() {
  System.out.println("Carro");
 }

 public void abrirPuerta() {
  System.out.println("Puerta abierta");
 }
}

public class Test {
 
 public static void main(String[] args) {
  Vehiculo v = new Carro();
  Carro c = new Carro();
  v.imprimirSonido();
  c.imprimirSonido();
  // --
  v.abrirPuerta();
  c.abrirPuerta();
  //--
  v.frenar();
  c.frenar();
 }
}
No hay necesidad de memorizar nada para poder entender lo que realmente pasa a nivel de la JVM pues podemos hacer un seguimiento a lo que sucede en el método main para poder determinar el resultado. Empezemos:

1.- En primer lugar creamos un objeto de la clase Vehículo en memoria.
Vehiculo v

2.- Al instanciar el objeto v, se toman en cuenta sólo los métodos que están presentes en ambas clases; en este caso void imprimirSonido(). Ahora surge la pregunta: Si ambos tienen el mismo método con diferentes implementaciones - ¿cuál es ellas es la que será tomada? La respuesta es la siguiente: En caso la clase hija haya sobrescrito el método, será éste el que se utilice para el objeto instanciado. La siguiente imagen ilustra esto.
Vehiculo v = new Carro();

Con esto, el objeto resultante v quedaría de la siguiente manera:


Lo cual nos permite rápidamente identificar que el código mostrado al inicio del artículo no se ejecutará pues el objeto v no posee el método abrirPuerta. Ahora, ejecutando este nuevo main - ¿cuál creen que sea la salida?
public static void main(String[] args) {
 Vehiculo v = new Carro();
 Carro c = new Carro();
 v.imprimirSonido();
 c.imprimirSonido();
 // --
 c.abrirPuerta();
 //--
 v.frenar();
 c.frenar();
}
Exacto, de seguro que su respuesta es igual a esta:


Esperando que este artículo les haya aclarado un poco más lo relacionado al polimorfismo y la herencia, me despido hasta una próxima oportunidad. Saludos.