jueves, 2 de febrero de 2017

Angular UI Bootstrap. Datepicker de un rango de fechas.

Para definir en nuestros formularios de angular unos datepicker muy útiles.

Primero definimos los campos en la página html.

Vamos a crear dos datepicker que definan un rango, no permitiendo que el rango final sea superior al inicial. Además el inicial solo podrá elegirse el primer día de un mes y para el final solo el último día de un mes.

Creamos una fecha para un rango inicial:

<div class="col-input">
    <div class="form-group">
        <label for="fechaInicio">Fecha de Inicio</label>
        <div class="input-group">
            <input id="fechaInicio" name="fechaInicio"
                   type="text" class="form-control"
                   uib-datepicker-popup="{{$ctrl.viewModel.format}}"
                   ng-model="$ctrl.viewModel.Dto.fechaInicio"
                   ng-model-options="{timezone: 'utc'}"
                   ng-change="$ctrl.viewModel.changeFechaInicio()"
                   is-open="$ctrl.viewModel.popup1.opened"
                   datepicker-options="$ctrl.viewModel.dateOptionsFechaInicio"
                   ng-required="true"
                   close-text="Cerrar"
                   current-text="Hoy"
                   clear-text="Limpiar"
                   alt-input-formats="$ctrl.viewModel.altInputFormats"
                   ng-disabled="$ctrl.viewModel.flags.disabledFechaInicio" />
            <span class="input-group-btn">
                <button type="button" class="btn btn-default pull-left"
                        ng-click="$ctrl.viewModel.open1($event)">
                    <i class="glyphicon glyphicon-calendar"></i>
                </button>
            </span>
        </div>
    </div>
</div>

Y otra fecha para el final del rango:

<div class="col-input">
    <div class="form-group">
        <label for="fechaFin">Fecha de Fin</label>
        <div class="input-group">
            <input id="fechaFin" name="fechaFin"
                   type="text" class="form-control"
                   uib-datepicker-popup="{{$ctrl.viewModel.format}}"
                   ng-model="$ctrl.viewModel.Dto.fechaFin"
                   ng-model-options="{timezone: 'utc'}"
                   ng-change="$ctrl.viewModel.changeFechaFin()"
                   is-open="$ctrl.viewModel.popup2.opened"
                   datepicker-options="$ctrl.viewModel.dateOptionsFechaFin"
                   ng-required="true"
                   close-text="Cerrar"
                   current-text="Hoy"
                   clear-text="Limpiar"
                   alt-input-formats="$ctrl.viewModel.altInputFormats"
                   ng-disabled="$ctrl.viewModel.flags.disabledFechaFin" />
            <span class="input-group-btn">
                <button type="button" class="btn btn-default"
                        ng-click="$ctrl.viewModel.open2($event)">
                    <i class="glyphicon glyphicon-calendar"></i>
                </button>
            </span>
        </div>
    </div>
</div>

Ahora vamos a definir en nuestro ViewModel de Angular las opciones de cada campo:


this.generalDateOptions = {
    formatYear: 'yy',
    startingDay: 1,
    showWeeks: false,
    prevText: ',
    nextText: 'Sig>',
    currentText: 'Hoy'
};
 
this.dateOptionsFechaInicio          = JSON.parse(JSON.stringify(this.generalDateOptions));
this.dateOptionsFechaInicio.minMode = 'month';
this.dateOptionsFechaInicio.minDate = new Date();
 
this.dateOptionsFechaFin             = JSON.parse(JSON.stringify(this.generalDateOptions));

La variable generalDateOptions, es la configuración común a todos los campos fecha que tengamos en nuestros formularios.

Luego personalizamos algunos de los parámetros de la configuración, como por ejemplo indicamos que para la fecha de inicio, queremos selección por meses no por días (minMode='month') y que queremos que la fecha mínima seleccionamble sea la fecha actual.

A continuación vamos a preparar las funciones de callback (open1 y open2), que serán llamadas cuando se pulse en el icono para abrir el control Datepicker. Aqui vamos a hacer depender la fecha final del rango de la fecha inicial que se haya elegido, no permitiendo elegir un dia menor.
Además vamos a desactivar todos los días del mes, menos el último (disableNotLastDayOfMonth)

this.popup1 = {
    opened: false
};
this.popup2 = {
    opened: false
};

this.open1 = function ($event) {
 
      this.popup1.opened = true;
};
this.open2 = function ($event) {
      this.dateOptionsFechaFin.minDate  = this.Dto.fechaInicio;
      this.dateOptionsFechaFin.initDate = this.dateOptionsFechaFin.minDate;
      // Desactivamos todos los días del mes menos el último
      this.dateOptionsFechaFin.dateDisabled = this.disableNotLastDayOfMonth;
      this.dateOptionsFechaFin.minMode = 'month';
      this.popup2.opened = true;
};

// Función que habilita solo las fechas que son fin de mes
this.disableNotLastDayOfMonth = function (obj) {
    var date = obj.date, mode = obj.mode;
    if (date.getDate() > 27) {
        var comprobar = new Date();
        comprobar.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
 
        if (comprobar.getDay() === date.getDay()) {
            return false;
        }
    }
    return mode === 'day' && true;
};



Podeis encontrar toda las opciones y documentación en:
https://angular-ui.github.io/bootstrap/

jueves, 2 de junio de 2016

Gestión de transacciones declarativas en Spring.

Es muy interesante poder definir de forma declarativa en el código, el ámbito de nuestras transacciones. 
Hay 7 tipos de propagación de las transacciones en Spring:

  • PROPAGATION_REQUIRED - Crea una nueva transacción si no existe. Si existe participa en ella. PROPAGATION_SUPPORTS - No crea una nueva transacción si no existe. Si existe participa en ella. 
  • PROPAGATION_MANDATORY - Si existe transacción participa en ella. Si no existe lanza una excepción. 
  • PROPAGATION_REQUIRES_NEW - Crea una nueva transacción. Si existe una transacción actual la suspende. 
  • PROPAGATION_NOT_SUPPORTED - No participa en la transacción actual y se ejecuta de forma no transaccional. 
  • PROPAGATION_NEVER - Si existe una transacción actualmente lanza una excepción. PROPAGATION_NESTED - Ejecuta una transacción anidada si existe una transacción actualmente. El caso más habitual es 
  • PROPAGATION_REQUIRED. http://www.mkyong.com/spring/spring-aop-transaction-management-in-hibernate/

martes, 31 de mayo de 2016

Conversión de fechas de cadena Java

Como formatear una fecha en una cadena tipo: "martes, 31 de mayo de 2016" A una fecha Java. java.text.SimpleDateFormat formatter=new SimpleDateFormat("EEEE, dd 'de' MMMM 'de' yyyy"); java.util.Date date=null; try { date = formatter.parse(peticionDia.getDia()); } catch (ParseException e) { e.printStackTrace(); }

lunes, 28 de septiembre de 2015

Hibernate join con condición adicional

Puede que tengamos escrito en HQL, sentencias que realizan joins de nuestras entidades. La ventaja de Hibernate es que como conoce las dependencias, no tenemos que indicar la condición del join entre cada una de nuestras tablas. Por ejemplo from Cat as cat join cat.mate as mate left join cat.kittens as kitten Pero que ocurre si no queremos que el join nos traiga el contenido de la tabla relacionada, bajo alguna circunstancia que se encuentra en dicha tabla relacionada. La solución es usar la clausula "with" que se asemeja a un and, y donde podemos especificar la condición que debe cumplirse para que el join sea efectivo y devuelva la fila de la entidad relacionada. from Cat as cat left join cat.kittens as kitten with kitten.bodyWeight > 10.0

jueves, 30 de julio de 2015

Instalación y administración Tomcat 7 en Windows

Instalación


Si quieres instalar Tomcat como ejecutable, no como servicio, en tu máquina windows.

Baja el fichero .zip correspondiente de 32 o 64 bits. Desde https://tomcat.apache.org/download-70.cgi

Descomprimelo en una carpeta. Por ejemplo: c:\tomcat7

Abre una consola de windows.

Establece las variables de entorno donde tengas instalado el jdk

set PATH=%PATH%;C:\Program Files\Java\jdk1.7.0_71\bin
set JAVA_HOME=C:\Archivos de programa\Java\jdk1.7.0_71

Dirigete a c:\tomcat7\bin y ejecuta startup.bat

Y ahora abre un navegador con la dirección: http:\\localhost:8080

Voila!

Si quieres parar Tomcat, en la misma consola de windows donde ejecutaste startup.bat, solo tienes que ejecutar shutdown.bat

Consola de administración

Edita el fichero c:\tomcat7\conf\tomcat-users.xml para que tenga la forma:


Accede a la siguiente dirección y cuando pida contraseña utiliza la definida en el anterior fichero:

http://localhost:8080/manager


Ampliación de memoria

Si tienes problemas de memoria al arrancar las aplicaciones, tienes que crear un fichero con nombre setenv.bat en el directorio c:\tomcat7\conf

set "CATALINA_OPTS=%CATALINA_OPTS% -Dfile.encoding=UTF8 -Xmx2048m -XX:MaxPermSize=512m"

Cambio de Puerto

Editar el fichero c:\tomcat\conf\server.xml cambiar el puerto 8080 por ejemplo por el 7001:


               < Connector port="7001" protocol="HTTP/1.1" connectionTimeout="20000"
               redirectPort="8443" />

Si además queremos tener dos tomcat arrancados en la misma máquina habremos de cambiar el puerto 8005 y el puerto 8009:

               < Server port="8015" shutdown="SHUTDOWN" />

               ....
               < Connector port="8019" protocol="AJP/1.3" redirectPort="8443" />




martes, 21 de abril de 2015

Java. Guardar una cadena en un fichero

En un proyecto Java, componía un xml a traves de una serie de consultas las cuales necesitaban un tiempo de proceso muy largo.

Para mejorar el rendimiento y devolver el xml si no había habido cambios en las tablas relacionadas, puede servir una caché primitiva como esta. Un método guarda el string del xml en un fichero y otro método lo lee y lo devuelve.


private void GuardarXmlCache ( String nombreFichero, String xml) {
try(FileOutputStream fos=new FileOutputStream(nombreFichero)){
fos.write(xml.getBytes());
fos.close();
}catch(IOException e){

}

}


private String LeerXmlCache ( String nombreFichero) {
FileInputStream fos = null;
String message  = new String();
try {
fos=new FileInputStream(nombreFichero);
BufferedReader rd = new BufferedReader (new InputStreamReader(fos,"UTF-8"));
String line=null;
//final StringBuffer buffer = new StringBuffer(2048);
while ((line = rd.readLine()) != null) {

message += line;
}        
rd.close();
 
}catch(IOException e){
e.printStackTrace();
}
return message;
}

jueves, 19 de febrero de 2015

analizando consultas en Postgresql. Parte I

Tenemos una potente herramienta para analizar las consultas en PostgreSQL: explain analyze

explain analyze select * from usuario;

Seq Scan on usuario  (cost=0.00..4743.71 rows=44471 width=243) (actual time=0.026..59.431 rows=44474 loops=1)

 Total runtime: 63.645 ms

(2 filas)

Seq Scan, significa que la consulta se hará fila a fila secuencialmente sin acceso por índice.

El valor numérico cost=0,00, es el tiempo que tiene que esperar la consulta en ser ejecutada. En este caso el tiempo es 0.00 porque puede ejecutarse inmediatamente.

El segundo valor 4743,71, es el numero de fetches necesarios para recuperar todas las filas de la consulta, el número de fetches lo podemos minimizar por ejemplo aplicando LIMIT.

Rows=44.471 es el número de filas que devolverá la consulta y width el tamaño medio en bytes de cada fila.

Truco: si vas a realizar análisis de operaciones de escritura, encierralas en un bloque de transacción, para poder ejecutarlas las veces que necesites y que no se produzcan cambios en la base de datos:

begin;
explain analyze insert ...;
rollback;