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.

Servicios Web y Facturación Electrónica

Durante los últimos meses he recibido la misma consulta repetidas veces. Y es que, al parecer, se están presentando problemas al consumir los servicios web del SRI pues no estaría devolviendo los mensajes de devuelta. En base a la experiencia de haber colaborado en varios proyectos de facturación electrónica, es que he compilado una librería que definitivamente les ayudará a desarrollar sus proyectos. 

Las características de la librería son las siguientes:
Manejo de mensajes de respuesta.
  • Permite cambiar de ambiente con solo modificar un parámetro.
  • Firmado de documentos electrónicos a través de archivo y token.
  • Almacenamiento de comprobantes autorizados en archivos de texto.
  • Generación de reportes y publicación de documentos electrónicos.
  • Integración con cualquier gestor de base de datos (MySQL, SQL Server, Oracle, PostrgeSQL)
  • Integración con aplicaciones de terceros a través de SOAP, texto plano o directorios compartidos.
Cualquier consulta, no dudes en ponerse en contacto conmigo a través de mi correo electrónico: rolando.roc@gmail.com

miércoles, 12 de marzo de 2014

Crear usuarios utilizando el Entreprise Manager de Oracle

Siempre que se necesite conectarse a una base de datos de Oracle, se precisa de un usuario y contraseña. En este artículo voy a mostrarles la manera de cómo crear uno a través del Enterprise Manager de Oracle.
Para visualizar los usuario hay que hacer clic en la pestaña Servidor.


En la sección de Seguridad hacer clic en el enlace de Usuarios, tal como se muestra a continuación:


Luego hacer clic en el botón crear, tal como se indica en la siguiente imagen:


Ahí debemos ingresar el nombre de nuestro usuario así como también la contraseña, el tablespace y el tablespace temporal.


Podemos hacer clic en las linternas para poder explorar la lista de tablespaces y tablespaces temporales. Las listas se presentarán como se muestra en la Fig.5 y Fig, 6.

Fig. 5. Lista de tablespaces.
Fig. 6. Lista de tablespaces temporales.
Ahora solo restaría hacer clic en el botón Aceptar para recibir el siguiente mensaje de confirmación:


Y con eso ya podemos conectarnos desde cualquier cliente como por ejemplo Pl/Sql Developer. En un siguiente artículo les mostraré la manera de cómo crear un tablespace. Saludos.

Crear un procedimiento almacenado con MySQL

En este artículo les voy a mostrar la manera de cómo crear un procedimiento almancenado en MySQL utilizando MySQL Query Browser (Excelente herramienta que ha sido reemplazada por MySQL Workbench).

Seleccionamos la base de datos sobre la que queremos trabajar. En este caso utilizaremos la base de datos de un artículo anterior[1].


Hacemos clic en la opción Create New Procedure/Function y le damos un nombre a nuestro procedimiento almacenado.


Al hacer clic en create PROCEDURE, se generá el siguiente código sql:
DELIMITER $$

DROP PROCEDURE IF EXISTS `rolandopalermo`.`sp_obti_cant_vehi` $$
CREATE PROCEDURE `rolandopalermo`.`sp_obti_cant_vehi` ()
BEGIN

END $$

DELIMITER ;
Ahora editamos el procedimiento para que retorne como salida la cantidad de vehículos que tenemos en nuestra base de datos.
DELIMITER $$

DROP PROCEDURE IF EXISTS `rolandopalermo`.`sp_obti_cant_vehi` $$
CREATE PROCEDURE `rolandopalermo`.`sp_obti_cant_vehi` (OUT param1 INT)
BEGIN
SELECT COUNT(*) INTO param1 FROM tb_modelo;
END $$

DELIMITER ;
Y ejecutamos el script para que nuestro procedimiento sea creado haciendo clic en el botón Execute de la barra de herramientas.


Y Ahora probamos nuestro procedimiento:
CALL sp_obti_cant_vehi(@a);
Y consultamos el valor de la variable @a.
select @a;

Esperando que este artículo les sea de utilidad, me despido hasta una próxima oportunidad.

lunes, 10 de marzo de 2014

Empezando con Mybatis, Netbeans y MySQL

MyBatis es un framework de persistencia de Java que permite el acceso a base de datos mediante la ejecución de comandos DML evitando que el programador escriba todo el código manualmente, tal como se hacía con JDBC.
En este artículo les mostraré la manera de cómo utilizar Mybatis en nuestros proyectos de Netbeans (la configuración en Eclipse o JDeveloper es la misma) utilizando una base de datos MySQL. La imagen que se muestra a continuación representa el árbol de paquetes que va a estructurar a nuestro proyecto.

Fig 1. Estructura de paquetes del proyecto de ejemplo
Esencialmente, para poder utilizar Mybatis debemos agregar la librería del framework que podemos descargar de su página y además debemos agregar un archivo de configuración llamado mybatis-config.xml. En este archivo se encuentran los parámetros de conexión a la base de datos así como también los mappers, que son elementos que se encargan de indicarle a Mybatis dónde encontrar las sentencias SQL mapeadas.
<?xml version="1.0" encoding="UTF-8"?>

<!--
    Document   : mybatis-config.xml
    Created on : 9 de marzo de 2014, 20:51
    Author     : Rolando
    Description:
        Purpose of the document follows.
-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="configuracion.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/rolandopalermo/example/data/TbVehiculos.xml"/>
    </mappers>
</configuration>
Como podemos notar, los parámetros de conexión no están establecidos explícitamente en la sección correspondiente sino que son leídos de un archivo de propiedades. Para esto, debemos indicarle a Mybatis la ruta de este archivo properties agregando una propiedad en nuestra configuración: <properties resource="configuracion.properties"/>. El archivo properties es el que se muestra a continuación:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/rolandopalermo
username=root
password=admin
Hecho esto, ahora procedemos a crear el POJO que se encargará de mapear un objeto Java con la tabla sobre la que queremos hacer un mantenimiento. Obviamente, antes de eso, debemos crear la base de datos utilizando el script siguiente:
-- MySQL Administrator dump 1.4
--
-- ------------------------------------------------------
-- Server version 5.5.16


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;


--
-- Create schema rolandopalermo
--

CREATE DATABASE IF NOT EXISTS rolandopalermo;
USE rolandopalermo;

--
-- Definition of table `tb_mantenimiento`
--

DROP TABLE IF EXISTS `tb_mantenimiento`;
CREATE TABLE `tb_mantenimiento` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `id_vehiculo` int(10) unsigned NOT NULL,
  `fecha_mantenimiento` date NOT NULL,
  `id_piloto` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_tb_mantenimiento_vehiculo` (`id_vehiculo`),
  KEY `FK_tb_mantenimiento_piloto` (`id_piloto`),
  CONSTRAINT `FK_tb_mantenimiento_piloto` FOREIGN KEY (`id_piloto`) REFERENCES `tb_piloto` (`id`),
  CONSTRAINT `FK_tb_mantenimiento_vehiculo` FOREIGN KEY (`id_vehiculo`) REFERENCES `tb_vehiculos` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_mantenimiento`
--

/*!40000 ALTER TABLE `tb_mantenimiento` DISABLE KEYS */;
INSERT INTO `tb_mantenimiento` (`id`,`id_vehiculo`,`fecha_mantenimiento`,`id_piloto`) VALUES 
 (1,1,'2013-11-17',1),
 (2,2,'2013-11-14',2),
 (3,3,'2013-11-17',3),
 (4,4,'2013-09-12',3),
 (5,5,'2013-11-17',2),
 (6,5,'2013-11-17',2),
 (7,6,'2013-11-17',1),
 (8,6,'2013-09-29',1),
 (9,2,'2013-11-17',2);
/*!40000 ALTER TABLE `tb_mantenimiento` ENABLE KEYS */;


--
-- Definition of table `tb_modelo`
--

DROP TABLE IF EXISTS `tb_modelo`;
CREATE TABLE `tb_modelo` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `descripcion` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_modelo`
--

/*!40000 ALTER TABLE `tb_modelo` DISABLE KEYS */;
INSERT INTO `tb_modelo` (`id`,`descripcion`) VALUES 
 (1,'SCANIA 3 EJES'),
 (2,'CABEZAL VOLVO'),
 (3,'CARRETA 4 EJES');
/*!40000 ALTER TABLE `tb_modelo` ENABLE KEYS */;


--
-- Definition of table `tb_piloto`
--

DROP TABLE IF EXISTS `tb_piloto`;
CREATE TABLE `tb_piloto` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nombre` varchar(60) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_piloto`
--

/*!40000 ALTER TABLE `tb_piloto` DISABLE KEYS */;
INSERT INTO `tb_piloto` (`id`,`nombre`) VALUES 
 (1,'Juan Pérez'),
 (2,'José Guzmán'),
 (3,'Luis Díaz'),
 (4,'Pedro Suarez'),
 (5,'Arturo Pomar');
/*!40000 ALTER TABLE `tb_piloto` ENABLE KEYS */;


--
-- Definition of table `tb_vehiculos`
--

DROP TABLE IF EXISTS `tb_vehiculos`;
CREATE TABLE `tb_vehiculos` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `numero_placa` varchar(45) NOT NULL,
  `fecha_registro` date NOT NULL,
  `id_modelo` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_tb_vehiculos_modelos` (`id_modelo`),
  CONSTRAINT `FK_tb_vehiculos_modelos` FOREIGN KEY (`id_modelo`) REFERENCES `tb_modelo` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_vehiculos`
--

/*!40000 ALTER TABLE `tb_vehiculos` DISABLE KEYS */;
INSERT INTO `tb_vehiculos` (`id`,`numero_placa`,`fecha_registro`,`id_modelo`) VALUES 
 (1,'SD-3456','2013-11-17',1),
 (2,'XS-9843','2013-11-17',2),
 (3,'LM-5621','2013-11-17',3),
 (4,'GB-0045','2013-11-17',2),
 (5,'KN-2354','2013-11-17',1),
 (6,'YL-5625','2013-11-17',2),
 (8,'XD-1237','2014-09-03',3),
 (9,'XD-1237','2014-09-03',3),
 (10,'XD-1237','2014-09-03',3),
 (11,'XD-1237','2014-09-03',3);
/*!40000 ALTER TABLE `tb_vehiculos` ENABLE KEYS */;




/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
Ahora vamos a crear un mantenimiento a la tabla rolandopalermo.tb_vehiculos, por lo que debemos crear un POJO que haga un mapeo de cada columna de dicha tabla.
Fig 2. Tabla sobre la que se hará el mantenimiento
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.model;

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

    private String id;
    private String numeroPlaca;
    private String fechaRegistro;
    private String idModelo;

    public String getFechaRegistro() {
        return fechaRegistro;
    }

    public void setFechaRegistro(String fechaRegistro) {
        this.fechaRegistro = fechaRegistro;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getIdModelo() {
        return idModelo;
    }

    public void setIdModelo(String idModelo) {
        this.idModelo = idModelo;
    }

    public String getNumeroPlaca() {
        return numeroPlaca;
    }

    public void setNumeroPlaca(String numeroPlaca) {
        this.numeroPlaca = numeroPlaca;
    }
}
Ahora hay que crear el archivo de mapeo TbVehiculos.xml para que Mybatis puede interpretar que la clase TbVehiculos hace referencia a la tabla tb_vehiculos y también la manera en que los atributos se relacionan con las columnas.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="TbVehiculos">
 
    <resultMap id="result" type="com.rolandopalermo.example.model.TbVehiculos">
        <result property="id" column="ID"/>
        <result property="numeroPlaca" column="NUMERO_PLACA"/>
        <result property="fechaRegistro" column="FECHA_REGISTRO"/>
        <result property="idModelo" column="ID_MODELO"/>
    </resultMap>
 
    <select id="getAll" resultMap="result">
        SELECT * FROM TB_VEHICULOS
    </select>
 
    <select id="getById" parameterType="int" resultMap="result">
        SELECT * FROM TB_VEHICULOS WHERE ID = #{id}
    </select>
 
    <delete id="deleteById" parameterType="int">
        DELETE from TB_VEHICULOS WHERE ID = #{id};
    </delete>
 
    <insert id="insert" parameterType="com.rolandopalermo.example.model.TbVehiculos">
    INSERT INTO TB_VEHICULOS (NUMERO_PLACA, FECHA_REGISTRO, ID_MODELO)
        VALUES (#{numeroPlaca}, #{fechaRegistro}, #{idModelo});
    </insert>
 
    <update id="update" parameterType="com.rolandopalermo.example.model.TbVehiculos">
        UPDATE TB_VEHICULOS
        SET
            NUMERO_PLACA = #{numeroPlaca},
            FECHA_REGISTRO = #{fechaRegistro},
            ID_MODELO = #{idModelo}
        WHERE ID = #{id};
    </update>
 
</mapper>
Ahora hay que indicarle a Mybatis de dónde debe leer los parámetros de conexión para poder crear las sesiones. Para esto creamos la clase MyBatisConnectionFactory.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.dao;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {

            String resource = "mybatis-config.xml";
            Reader reader = Resources.getResourceAsReader(resource);

            if (sqlSessionFactory == null) {
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            }
        } catch (FileNotFoundException fileNotFoundException) {
            fileNotFoundException.printStackTrace();
        } catch (IOException iOException) {
            iOException.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {

        return sqlSessionFactory;
    }
}
Y ahora creamos la clase DAO, quien a través de sus métodos encapsulará las operaciones que vamos a realizar sobre la tabla tb_vehiculos.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.dao;

import com.rolandopalermo.example.model.TbVehiculos;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

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

    private SqlSessionFactory sqlSessionFactory;

    public TbVehiculosDAO() {
        sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory();
    }

    @SuppressWarnings("unchecked")
    public List<TbVehiculos> selectAll() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            List<TbVehiculos> list = session.selectList("TbVehiculos.getAll");
            return list;
        } finally {
            session.close();
        }
    }

    public TbVehiculos selectById(int id) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            TbVehiculos contact = (TbVehiculos) session.selectOne("TbVehiculos.getById", id);
            return contact;
        } finally {
            session.close();
        }
    }

    public void update(TbVehiculos contact) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.update("TbVehiculos.update", contact);
            session.commit();
        } finally {
            session.close();
        }
    }

    public void insert(TbVehiculos contact) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.insert("TbVehiculos.insert", contact);
            session.commit();
        } finally {
            session.close();
        }
    }

    public void delete(int id) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.delete("TbVehiculos.deleteById", id);
            session.commit();
        } finally {
            session.close();
        }
    }
}
Y por último la clase de prueba que nos permitirá saber si toda nuestra configuración fue hecha correctamente.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.test;

import com.rolandopalermo.example.dao.TbVehiculosDAO;
import com.rolandopalermo.example.model.TbVehiculos;
import java.util.List;

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

    public static void main(String[] args) {
        TbVehiculosDAO dao = new TbVehiculosDAO();
        List<TbVehiculos> lstVehiculos = dao.selectAll();
        for (TbVehiculos tbVehiculos : lstVehiculos) {
            System.out.println(tbVehiculos.getId() + "t" + tbVehiculos.getNumeroPlaca());
        }
        TbVehiculos nuevoVehiculo = new TbVehiculos();
        nuevoVehiculo.setFechaRegistro("2014-03-10");
        nuevoVehiculo.setIdModelo("1");
        nuevoVehiculo.setNumeroPlaca("Test");
        dao.insert(nuevoVehiculo);
        System.out.println("--------------------");
        lstVehiculos = dao.selectAll();
        for (TbVehiculos tbVehiculos : lstVehiculos) {
            System.out.println(tbVehiculos.getId() + "t" + tbVehiculos.getNumeroPlaca());
        }
    }
}
Y el resultado:

Aquí les adjunto el enlace para poder descargar el proyecto:
Y en un siguiente artículo les mostraré cómo invocar a un procedimiento almacenado desde Mybatis. Saludos y hasta una próxima oportunidad.

lunes, 3 de marzo de 2014

Activar telnet en Windows 7

En este post les muestro cómo activar el servicio de Telnet a través de 4 simples pasos.





Con esto, abrimos la consola y ya deberíamos tener nuestro protocolo Telnet operativo. Un saludo y hasta una próxima oportunidad.