jueves, 25 de octubre de 2018

How to reset a remote git repository to remove all commits

Delete the .git directory locally and recreate the git repostory:
$ cd (project-directory)
$ git init
$ (add some files)
$ git add .
$ git commit -m 'Initial commit'
Push to remote server, overwriting. Remember you're going to mess everyone else up doing this so you better be the only client.
$ git remote add origin <url>
$ git push --force --set-upstream origin master

domingo, 21 de octubre de 2018

How to Create an Executable JAR with Maven

In this quick article we will focus on packaging a Maven project into an executable Jar file. In order to create an executable jar, we don’t need any additional dependencies. We just need to create Maven Java project, and have at least one class with the main(…) method.

We also need to make sure that our pom.xml contains the the following elements:
<build>
    <finalName>anjus-invoicing-${project.version}</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <appendAssemblyId>false</appendAssemblyId>
                <archive>
                    <manifest>
                        <mainClass>com.rolandopalermo.example.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>assembly</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

viernes, 19 de octubre de 2018

Generación de número CUFE con Java

Siguiendo con la serie de artículos relacionados con Facturación Electrónica en Colombia, les comparto una función para la generación del número CUFE en Java.
public static String calculateInvoiceCUFE(String numFac, String fechaFac, String horaFac, String valFac,
   String valImp1, String valImp2, String valImp3, String valPag, String nitOFE, String tipAdq, String numAdq,
   String clTec) {
  StringBuilder sb = new StringBuilder("");
  sb.append(numFac);
  sb.append(fechaFac);
  sb.append(horaFac);
  sb.append(valFac);
  sb.append(CodImp1);
  if (StringUtils.isEmpty(valImp1)) {
   sb.append("0.00");
  } else {
   sb.append(valImp1);
  }
  sb.append(CodImp2);
  if (StringUtils.isEmpty(valImp2)) {
   sb.append("0.00");
  } else {
   sb.append(valImp2);
  }
  sb.append(CodImp3);
  if (StringUtils.isEmpty(valImp3)) {
   sb.append("0.00");
  } else {
   sb.append(valImp3);
  }
  sb.append(valPag);
  sb.append(nitOFE);
  sb.append(tipAdq);
  sb.append(numAdq);
  sb.append(clTec);
  return DigestUtils.sha1Hex(sb.toString());
 }
Es importante agregar la siguiente dependencia:
<dependency>
 <groupId>commons-codec</groupId>
 <artifactId>commons-codec</artifactId>
 <version>1.11</version>
</dependency>

jueves, 18 de octubre de 2018

Facturacion Electrónica en Colombia

Conocido es por todos que hoy en día la facturación electrónica es ya una realidad en Colombia. Se han realizado planes piloto con diversas empresas y en la actualidad ya es una necesidad acogerse a esta nueva tecnología tributaria.

En este artículo, no voy a entrar en detalle en las resoluciones y leyes emitidas por la entidad regulatoria en Colombia, la DIAN, sin embargo como desarrollador de software, me causa un profundo malestar la pésima documentación que acompaña a las normas que obligan a las empresas a facturar de manera electrónica.

Y es que no es una novedad que instituciones como el SRI en Ecuador, la SUNAT en Perú o la DIAN en Colombia pongan trabas con pésimos canales de resolución de dudas y mala documentación. A veces me planteo la interrogante de cómo es que planifican la puesta en marcha a nivel nacional de proyectos tan grandes con tan poca o nula documentación.

En mi experiencia, leyendo un manual técnico y entendido el esquema funcional del proceso, se debería estar apto para emitir comprobantes electrónicos en no más de un mes, sin embargo nos tapamos con trabas como el tener que leer un PDF que nos habla de un servicio web de tipo SOAP para consultas de facturas y terminar dándonos cuenta que en ningún momento nos indicaron cuál es el WSDL (Si bien son términos muy técnicos, los lectores que desarrollarán software entenderán la gravedad de esto).

Podría disponer de líneas y líneas en mi blog para hablar de la mala experiencia que puede resultar implementar facturación electrónica en Sudamérica pues la diversidad de manuales no versionados sumado a la poca organización de la información y la indisponibilidad de enlaces y URL's puede, a veces, hacernos arrepentir de haber emprendido este tipo de desarrollos. Sin embargo, el propósito de este artículo es clarificar de cierta manera cuales son los pasos que se debe seguir en Colombia.

El siguiente esquema funcional representa el flujo que se sigue para autorizar o en otras palabras, dar validez tributaria, a una factura electrónica en Colombia.


Básicamente, son dos los servicios Web que nos permiten autorizar una factura, el de recepción y el de consulta. Cada uno tiene un WSDL diferente además de estar configurados para ser consumidos mediante WS-Security. Los enlaces los muestro a continuación:

https://facturaelectronica.dian.gov.co/habilitacion/B2BIntegrationEngine/FacturaElectronica/facturaElectronica.wsdl

https://facturaelectronica.dian.gov.co/habilitacion/B2BIntegrationEngine/FacturaElectronica/consultaDocumentos.wsdl

Los pasos a seguir son:

1. Generar XML
Para generar los archivos XML, a diferencia de Ecuador, debemos utilizar el esquema UBL 2.0. En este punto recomiendo no utilizar librerías externas y mejor generar los documentos XML de manera manual utilizando las clases del paquete org.w3c.dom.

2. Firmar XML
Para firmar el documento XML, una excelente librería para Java es xades4j. La dependencia de maven es la siguiente:
<dependency>
 <groupId>com.googlecode.xades4j</groupId>
 <artifactId>xades4j</artifactId>
 <version>1.5.0</version>
</dependency>
En la sección de issues en su página de github podemos encontrar diversas consultas en donde también sugieren cómo implementar la firma electrónica según los estándares de Colombia.

3. Enviar XML firmado a la DIAN
Este paso es nuestra primera interacción con la DIAN. En este servicio se valida la estructura del documento XML así como la firma digital. Es importante recordar que el SOAP request deberá tener como cabecera el objeto de WS-Security. A continuación muestro un ejemplo de request:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" S:mustUnderstand="1">
            <wsse:UsernameToken>
                <wsse:Username><!--- Proporcionado por la DIAN --></wsse:Username>
                <wsse:Password><!--- Proporcionado por la DIAN --></wsse:Password>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <!--- Hora en que se realiza la petición en formato yyyy-MM-ddTHH:mm:ssZ -->
                </wsu:Created>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis200401-wss-soap-message-security1.0#Base64Binary">
                <!--- Secuencia aleatoria codificada en base 64 -->
                </wsse:Nonce>
            </wsse:UsernameToken>
        </wsse:Security>
    </SOAP-ENV:Header>
    <S:Body>
        <EnvioFacturaElectronicaPeticion xmlns="http://www.dian.gov.co/servicios/facturaelectronica/ReportarFactura">
            <NIT><!--- NIT del facturador --></NIT>
            <InvoiceNumber><!--- Número secuencial de la factura --></InvoiceNumber>
            <IssueDate><!--- Fecha de emisión de la factura en formato yyyy-MM-ddTHH:mm:ss --></IssueDate>
            <Document><!--- Archivo ZIP codificado en base 64 --></Document>
        </EnvioFacturaElectronicaPeticion>
    </S:Body>
</S:Envelope>

4. Validar Factura
En caso el código de respuesta del servicio anterior sea 200, el siguiente paso es comprobar que la factura tenga validez tributaria. Al igual que la llamada anterior, la estructura de la petición para este servicio también considera la cabecera de tipo wS-Security.
Este paso es nuestra primera interacción con la DIAN. Es importante recordar que el SOAP request deberá tener como cabecera el objeto de WS-Security. A continuación muestro un ejemplo de request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:con="http://www.dian.gov.co/servicios/facturaelectronica/ConsultaDocumentos">
   <soapenv:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:UsernameToken>
                <wsse:Username><!--- Proporcionado por la DIAN --></wsse:Username>
                <wsse:Password><!--- Proporcionado por la DIAN --></wsse:Password>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <!--- Hora en que se realiza la petición en formato yyyy-MM-ddTHH:mm:ssZ -->
                </wsu:Created>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis200401-wss-soap-message-security1.0#Base64Binary">
                <!--- Secuencia aleatoria codificada en base 64 -->
                </wsse:Nonce>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <con:ConsultaResultadoValidacionDocumentosPeticion>
            <con:TipoDocumento>
            <!--- Parámetros enviados con error, el tipo de documento debe ser 
            1 = Factura, 
            2 = Nota Débito, 
            3 = Nota Crédito -->
            </con:TipoDocumento>
            <con:NumeroDocumento>
            <!--- Número secuencial de la factura -->
            </con:NumeroDocumento>
            <con:NitEmisor><!--- NIT del facturador --></con:NitEmisor>
            <con:FechaGeneracion>
            <!--- Fecha de emisión de la factura en formato yyyy-MM-ddTHH:mm:ss -->
            </con:FechaGeneracion>
            <con:IdentificadorSoftware>
            <!--- Proporcionado por la DIAN -->
            </con:IdentificadorSoftware>
            <con:CUFE>
            <!--- El valor del CUFE es obligatorio cuando el tipo de documento es 1 = 'INVOICE' -->
            </con:CUFE>
        </con:ConsultaResultadoValidacionDocumentosPeticion>
    </soapenv:Body>
</soapenv:Envelope>

5. Comunicar factura
Como paso final, en caso de tener como código de transacción 200, ya podemos enviar la factura en formato ZIP junto con el PDF correspondiente al receptor.

Finalmente les comparto la información de un taller que estamos impartiendo para capacitar a desarrolladores Java en la implementación de este tipo de aplicaciones.

Espero esta información les sea de mucha utilidad y quedo presto a resolver interrogantes adicionales que podrán dejar en la caja de comentarios.

viernes, 20 de abril de 2018

Verónica: Facturación Electrónica de código abierto

En el contexto de la computación, el código fuente se define como un conjunto de líneas de texto, que son las instrucciones que debe seguir la computadora para ejecutar dicho programa; por lo que es en el código fuente, donde se encuentra escrito el funcionamiento de un determinado producto de software. Ahora bien, el código fuente de un programa está escrito en uno o más lenguajes de programación específicos, sin embargo este tipo de lenguajes no pueden ser ejecutado directamente por una computadora sino que debe ser traducidos a otro lenguaje que el ordenador pueda ejecutar más fácilmente.

Acceder al código fuente de un programa, consiste en tener acceso a los algoritmos desarrollados por sus creadores. Es la única forma de transformar de manera eficiente un programa. Al tener acceso a las fuentes, es fácil determinar las falencias de un producto sin embargo, desde un punto de vista más optimista, esto no es tan contraproducente como se pensaría puesto que el encontrar errores de programación podría ser de gran ayuda para poder subsanar de manera rápida dichos fallos o incluso, mejorar el rendimiento de un software.

Y es esto último justamente la razón por la cual, luego de haber trabajado por 6 años con más de 40 empresas en Ecuador, he decidido liberar el código fuente de la plataforma para la emisión de comprobantes electrónicos según la normativa impuesta por el Servicio de Rentas Internas (SRI) desde el año 2012. 

Veronica, que es como bauticé al proyecto, reúne todos los requerimientos para generar, firmar, autorizar y almacenar un comprobante electrónico según las leyes del SRI, la autoridad tributaria Ecuatoriana. La idea es formar una comunidad que permita hacer crecer el proyecto de tal manera que pueda ser utilizado por empresas desde la más pequeña hasta la que posea altos volúmenes de facturación. La arquitectura sobre la que está implementada Veronica justamente fue pensada para eso, la escalabilidad.

Evidentemente el fin no es lucrar con un aspecto tan importante como es la cultura tributaria y la declaración de impuestos, sino es poder apoyar a difundir el uso de la facturación electrónica dados los diversos beneficios que está traería consigo no solo para Ecuador sino también para la región.

El proyecto ha sido liberado en la plataforma de control de versiones Github y se encuentra disponible para su rápida descarga, compilación y despliegue, brindando una potente API Rest (Tendencia en el mercado actual de software) que cubre todas las especificaciones del SRI.

Involúcrate en el proyecto y hagamos que se convierta en un estándar.
https://github.com/rolandopalermo/Veronica

martes, 20 de marzo de 2018

Deserialización JSON de tipos genéricos usando Jackson

Como parte de las buenas prácticas en la reutilización de clases, es común encontrar el uso de tipos genéricos en Java. Sin embargo, cuando estas forman parte de una respuesta JSON, pueden ser un dolor de cabeza. Imaginemos que tenemos como respuestas de un API Rest los dos siguientes escenarios:

PersonaResponse
{
   "codigo":1,
   "mensaje":"ok",
   "data":{
      "nombres":"Rolando Palermo",
      "edad":29
   }
}
ProductoResponse
{
   "codigo":1,
   "mensaje":"ok",
   "data":{
      "codigo":"FX-536",
      "precio":56.98,
      "moneda":"PEN",
   }
}
Ambos Json tienen propiedades comunes, sin embargo sólo el objeto data es diferente. Para deserializar estos jsons sin tipos genéricos, tendríamos que crear 2 envoltorios con 2 clases de datos diferentes. Pero con los tipos genéricos solo necesitamos crear una clase genérica para las propiedades de la raíz y una clase específica para cada objeto en la clave de data.

GenericResponse.java
public class GenericResponse<T> {

    private String codigo;
    private String mensaje;
    T data;

    public String getCodigo() {
        return codigo;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public String getMensaje() {
        return mensaje;
    }

    public void setMensaje(String mensaje) {
        this.mensaje = mensaje;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
    
}
PersonaResponse
public class PersonaResponse {

    private String nombres;
    private int edad;

    public String getNombres() {
        return nombres;
    }

    public void setNombres(String nombres) {
        this.nombres = nombres;
    }

    public int getEdad() {
        return edad;
    }

    public void setEdad(int edad) {
        this.edad = edad;
    }
}
ProductoResponse
public class ProductoResponse {

    private String codigo;
    private double precio;
    private String moneda;

    public String getCodigo() {
        return codigo;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public double getPrecio() {
        return precio;
    }

    public void setPrecio(double precio) {
        this.precio = precio;
    }

    public String getMoneda() {
        return moneda;
    }

    public void setMoneda(String moneda) {
        this.moneda = moneda;
    }

}
Ahora, la deserialización JSON nos quedaría de la siguiente manera:
ObjectMapper mapper = new ObjectMapper();
//Para persona
GenericResponse<PersonaResponse> response1 = mapper.readValue(jsonString, new TypeReference<GenericResponse<PersonaResponse>>() {});
//Para producto
GenericResponse<ProductoResponse> response2 = mapper.readValue(jsonString, new TypeReference<GenericResponse<ProductoResponse>>() {});

sábado, 24 de febrero de 2018

Bloqueo de recursos en SQL Server

En los últimos años hemos sido testigos de un crecimiento exponencial de aplicaciones distribuidas, con infinidad de componentes concurrentes de propósito específico interactuando unos con otros en tiempo real y a grandes velocidades. Estos nuevos enfoques de arquitecturas asíncronas han traído consigo antiguos problemas que nosotros, los desarrolladores, debemos resolver en nuestro día a día; uno de ellos, el mítico bloqueo mutuo.

Escenarios tales como accesos a interfaces de hardware, aplicaciones IOT o hasta la simple generación de números de secuencia de tickets son casos donde el interbloqueo o bloqueo mutuo es un problema que de no ser resuelto, podría comprometer el éxito de un proyecto de software. Si bien es cierto, existen soluciones que van desde complejas arquitecturas distribuidas hasta increíbles artimañanas inventadas por algún programador adicto al café, en este artículo nos centraremos en una propuesta que manejará el interbloqueo desde base de datos haciendo uso de un procedimiento almacenado de sistema, el sp-getapplock.

El problema se planteará de la siguiente manera: "Debemos desarrollar un procedimiento almacenado que garantice la inserción de registros en una tabla determinada, cada uno de los cuales estará identificado por un id que deberá generarse de manera secuencial sin dejar ningún vacío, esto quiere decir que de presentarse algún error, se deberá ejecutar una instrucción de rollback y la siguiente inserción deberá hacer uso de esta secuencia".

El primer paso será crear nuestra tabla, para lo cual haremos ejecutaremos la siguiente consulta en SQL Server.
CREATE TABLE dbo.Registros  
   (Registro_Seq_ID int PRIMARY KEY NOT NULL,  
    Registro_Descripcion varchar(25) NOT NULL)  
GO 
El siguiente paso será crear un procedimiento almacenado que se encargue de la inserción, esto con el fin de tener un punto de entrada dónde poder aplicar nuestro control contra los interbloqueos.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE spInsertarRegistro
 @Descripcion VARCHAR(25),
 @RegistroSeq INT OUT
AS
BEGIN
 SET NOCOUNT ON;
 SELECT @RegistroSeq = ISNULL(MAX(Registro_Seq_ID), 0) + 1  from Registros;
 INSERT INTO Registros(Registro_Seq_ID, Registro_Descripcion) VALUES (@RegistroSeq, @Descripcion);
END
GO
Y ahora utilizaremos Java para probar nuestro procedimiento almacenado.
package com.rolandopalermo.sql;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class App {
    
 public String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
 public void insertRegistro(String descripcion) throws SQLException,
 ClassNotFoundException {
  String connectionUrl = "jdbc:sqlserver://localhost:55418;databaseName=BD_TEST;user=user_test_app;password=12345678";
  try (
  Connection connection = DriverManager.getConnection(connectionUrl);
  CallableStatement cstmt = connection.prepareCall("{call spInsertarRegistro(?,?)}")) {
   Class.forName(driver);
   cstmt.setString(1, descripcion);
   cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
   cstmt.execute();
   System.out.println("Se creó el registro [" + cstmt.getInt(2) + "]");
  }
 }
 
 public static void main(String[] args) throws Exception {
  App app = new App();
  app.insertRegistro("Registro sin interbloqueo");
 }
 
}
Al ejecutar dicha clase, veremos que nuestro registro se insertó correctamente, sin embargo ahora realizaremos una pequeña mofidicación al método main para que inserte registros de manera continua, estableciendo una pausa de 200 milisegundos entre cada inserción. Al ejecutar un sólo proceso, el resultado será el siguiente:



Sin embargo, al ejecutar tres procesos, la historia cambia:



Es aquí donde sp-getapplock viene a salvarnos el día. Nuestro procedimiento sufrirá una ligera modifación, la cual evitará que más de una petición intente ejecutarlo de manera concurrente. El recurso de bloqueo creado por sp_getapplock se crea en la base de datos actual para la sesión.
SET ANSI_NULLS ON  
 GO  
 SET QUOTED_IDENTIFIER ON  
 GO  
 ALTER PROCEDURE spInsertarRegistro2  
      @Descripcion VARCHAR(25),  
      @RegistroSeq INT OUT  
 AS  
 DECLARE  
      @rc int = 0,  
      @msg varchar(2000)  
 SET @msg = CONVERT(varchar, GETDATE(), 114) + ' Se incia el segmento a sincronizar'  
 RAISERROR (@msg, 0, 1) WITH NOWAIT  
 BEGIN TRY  
      BEGIN TRAN  
           SET @msg = CONVERT(varchar, GETDATE(), 114) + ' Tratando de obtener el candado'  
           RAISERROR (@msg, 0, 1) WITH NOWAIT  
           -- Se solicita el candado  
           EXEC @rc = sp_getapplock   
                @Resource = 'spInsertarRegistro2', -- Nombre del recurso a bloquear  
                @LockMode = 'Exclusive', -- Tipo de candado  
                @LockOwner = 'Transaction', -- Transaction or Session  
                @LockTimeout = 15000 -- Tiempo de espera máximo, 15 seconds  
           -- Se verifica si se pudo obtener el candado  
           SET @msg =   
                CONVERT(varchar, GETDATE(), 114) +   
                ' sp_getapplock retornó ' +   
                CONVERT(varchar(30), @rc) +   
                ' -- ' +   
                CASE  
                     WHEN @rc < 0 THEN 'No se pudo obtener el candado'  
                     ELSE 'Candado obtenido'  
                END  
           RAISERROR (@msg, 0, 1) WITH NOWAIT  
           IF @rc >= 0  
                BEGIN  
                     SET @msg = CONVERT(varchar, GETDATE(), 114) + ' Se iniciará con la sección crítica '  
                     RAISERROR (@msg, 0, 1) WITH NOWAIT  
                     -- Inserciones protegias por código  
                     SET NOCOUNT ON;  
                     SELECT @RegistroSeq = ISNULL(MAX(Registro_Seq_ID), 0) + 1 from Registros;  
                     INSERT INTO Registros(Registro_Seq_ID, Registro_Descripcion) VALUES (@RegistroSeq, @Descripcion);  
                     --   
                     COMMIT TRAN -- Se libera el candado  
                     SET @msg = CONVERT(varchar, GETDATE(), 114) + ' Trabajo completado, se libera el candado'  
                     RAISERROR (@msg, 0, 1) WITH NOWAIT  
                END  
           ELSE  
                BEGIN  
                ROLLBACK TRAN  
                SET @rc = 50000  
           END  
 END TRY  
 BEGIN CATCH  
      set @msg = 'ERROR: ' + ERROR_MESSAGE() + ' en '   
       + coalesce(ERROR_PROCEDURE(), '')  
       + coalesce (' la línea:' + convert(varchar(30), ERROR_LINE()), '')  
      IF @@Trancount > 1  
           ROLLBACK TRAN;  
      RAISERROR (@msg, 0, 1)  
 END CATCH  
Ahora realizaremos una modificación a la clase Java para que inserte de manera concurrente registros sin ninguna pausa. Al ser la columna Registro_Seq_ID una clave primaria, si en algún momento llegase a duplicarse, se deberá lanzar un error. El siguiente video evidencia que, a pesar de la concurrencia, todos los registros se están insertando de manera correcta.


Espero que este post les sea de utilidad y cualquier consulta adicional, no duden en comentarla.