¿Los servidores DNS que uso son decentes?

Hace casi 6 meses iniciamos la comunidad java Guatemala

Hace casi 3 meses alguien de la comunidad amablemente adquirio el dominio guate-jug.org.

Hace casi 2 meses este dominio se apunto hacia un nuevo servidor el cual es un procedimiento de rutina y regularmente no requiere más de 72 horas para que todos los dns tengan la nueva ip lista y fresca.

Hace un mes despues de detectar un problema con la actualizacion de DNS en un ISP con servidores DNS mediocres (telgua) hicimos de todo hasta cambiar de registrador de dominio.

Y el dia de hoy las cosas estan asi:

Google:

$ nslookup guate-jug.org 8.8.8.8
Server:        8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
Name:    guate-jug.org
Address: 173.236.29.66

$ nslookup guate-jug.org 8.8.4.4
Server:        8.8.4.4
Address:    8.8.4.4#53

Non-authoritative answer:
Name:    guate-jug.org
Address: 173.236.29.66

Opendns:

$ nslookup guate-jug.org 208.67.222.222
Server:        208.67.222.222
Address:    208.67.222.222#53

Non-authoritative answer:
Name:    guate-jug.org
Address: 173.236.29.66

$ nslookup guate-jug.org 208.67.220.220
Server:        208.67.220.220
Address:    208.67.220.220#53

Non-authoritative answer:
Name:    guate-jug.org
Address: 173.236.29.66

Pero si vamos por los locales:

Tigo:

$ nslookup guate-jug.org 200.49.161.131
Server:        200.49.161.131
Address:    200.49.161.131#53

Non-authoritative answer:
Name:    guate-jug.org
Address: 67.23.226.35

Telgua:

$ nslookup guate-jug.org ns.telgua.com.gt
Server:        ns.telgua.com.gt
Address:    216.230.128.33#53

** server can’t find guate-jug.org: REFUSED

$ nslookup guate-jug.org ns.comtech.net.gt
Server:        ns.comtech.net.gt
Address:    216.230.128.32#53

** server can’t find guate-jug.org: REFUSED

Y si puede parecer engreido que me queje tanto, pero despues de que todos dicen que es porque configure mal wordpress ¬¬, mientras yo con el uso de google dns he podido ver la pagina siempre. Tengo el derecho de quejarme que los tecnicos certificados CCNA/CCNP/CCNAlgo se dignen a optimizar el funcionamiento de sus servidores DNS o se rindan y preconfiguren en sus routers servidores DNS de verdad. Si hacen pruebas en los ISP locales a veces si resuelve la direccion . . . solo que a la IP equivocada.

Se aceptan donaciones para un guate-jug.net :/

Validando propiedades nulas de un objeto en Java

Todo programador java sabe que los tipos primitivos tienen un valor por defecto y los objetos por defecto tienen valor nulo (si no lo sabias ponte a estudiar).

A veces es necesario validar estos objetos para realizar operaciones sobre ellos y asegurarnos que nuestro usuario no reciba un magico nullPointerException. El metodo más rapido seria validar una a una las propiedades o la opción que me gusta, preguntarle a nuestro objeto que propiedades tiene y luego utilizar los metodos propios del objeto con Java Reflection.

Java Reflection es un API poco conocida por programadores principiantes, sin embargo es la unica salida en programas que requieren la habilidad de examinar un objeto en tiempo de ejecución. Si no han leido acerca de esto no se preocupen el Java Tutorial lo califica como avanzado.

Todos los detalles acerca de reflection se encuentra en el Java Tutorial sin embargo la clase que utilizo para validar nulos es la siguiente:

public class NullValidator {
 
    public static Object validarCampos(Object pObjeto) {
        Object objeto = pObjeto;
        Method metodos[] = pObjeto.getClass().getMethods();
        for (int i = 0; i < metodos.length; i++) {
            Method metodo = metodos[i];
            //Si es un metodo get o is lo utilizo con su equivalente set
            if ((metodo.getName().substring(0, 3).equalsIgnoreCase("get") || metodo.getName().substring(0, 2).equalsIgnoreCase("is")) && !metodo.getName().equals("getClass")) {
                String methodNameSet = "";
                if(metodo.getName().substring(0, 3).equalsIgnoreCase("get")){
                    methodNameSet = metodo.getName().replaceFirst("get", "set");
                }else{
                    methodNameSet = methodNameSet.replaceFirst("is", "set");
                }
                try {
                    Method metodoSet = pObjeto.getClass().getMethod(methodNameSet, metodo.getReturnType());
                    if (metodoSet != null) {
                        //Datos numericos
                        //Si es byte
                        if (metodo.getReturnType().equals(java.lang.Byte.class)) {
                            Byte valor = (Byte)metodo.invoke(pObjeto, new Object[0]);
                            if(valor==null){
                                metodoSet.invoke(pObjeto, 0);
                            }
                        }
                        //Si es bigDecimal
                        if (metodo.getReturnType().equals(java.math.BigDecimal.class)) {
                            BigDecimal valor = (BigDecimal)metodo.invoke(pObjeto, new Object[0]);
                            if(valor==null){
                                metodoSet.invoke(pObjeto, new BigDecimal(0));
                            }
                        }
                        // Si es Double
                        if (metodo.getReturnType().equals(java.lang.Double.class)) {
                            Double valor = (Double)metodo.invoke(pObjeto, new Object[0]);
                            if(valor==null){
                                metodoSet.invoke(pObjeto, new Double(0));
                            }
                        }
                        //Si es un string
                        if (metodo.getReturnType().equals(java.lang.String.class)) {
                            String valor = (String)metodo.invoke(pObjeto, new Object[0]);
                            if(valor==null){
                                metodoSet.invoke(pObjeto, "");
                            }
                        }
                        //Si es una lista
                        if (metodo.getReturnType().equals(java.util.List.class)) {
                            List objetosList = (List)metodo.invoke(pObjeto, new Object[0]);
                            for(Object objetoFromList:objetosList){
                                NullValidator.validarCampos(objetoFromList);
                            }
                        }
                        //Si es date
                        if (metodo.getReturnType().equals(java.util.Date.class)) {
                            Date valor = (Date)metodo.invoke(pObjeto, new Object[0]);
                            if(valor==null){
                                metodoSet.invoke(pObjeto, new Date());
                            }
                        }
                        //Si es primitivo
                        if (metodo.getReturnType().isPrimitive()) {
                            //los primitivos no permiten null
                        }
                    }
                } catch (Exception e) {
                }
            }
        }
        return objeto;
    }
 
}

¿Como funciona?

  1. Primero capturo los metodos que tiene el objeto
  2. Luego si es un metodo get procedo a utilizar su equivalente is o set
  3. Por ultimo compruebo el tipo de dato y si es nulo, si es nulo procedo a darle un valor inicial

Luego basta con invocar el metodo validarCampos (porque además es estatico) y listo nuestro objeto sera validado contra valores nulos.

 

Cyanogenmod 7 y Google Apps para paises con market restringido

El día de hoy se publicaron los primeros release candidate de mi ROM preferido para smartphones Android, esta vez con un cambio de versión mayor acorde al cambio de ROM base. Los nuevos ROMS del proyecto cyanogenmod de ahora en adelante estarán basados en Android Gingerbread.

Dejando a un lado los bombos y platillos, siguiendo mi tradición gentoosera bleeding edge procedi a instalar un release candidate :P.

Los pasos detallados para una instalación nueva se encuentran en la wiki del proyecto. Y para los usuarios actuales de cyanogenmod ya esta disponible la actualizacion desde el ROM manager.

En mi caso ya era usuario de cyanogenmod la instalación fue transparente, solo actualice ClockworkMod, luego el correspondiente backup y despues de descargar la imagen del ROM todo fue bien a excepcion de un inconveniente: Instalación aplicaciones de google

El problema es que aunque las aplicaciones de Google sean descargadas mediante el instalador del Rom Manager, necesitan ser instaladas via Android Market pero solo son visibles para usuarios de tiendas de aplicaciónes «premium» (con aplicaciones de pago)

Solucion 1 (Sin ejecutar el Android Market):

Si despues de instalar aun no han ejecutado el android market deben cargar por medio de sideload la aplicacion Market Enabler y obtener un perfil de cualquier pais con un Android Market «premium».

Por ejemplo si busco gmail con el Market normal de Guatemala obtengo:

Y despues de la ejecucion del Market Enabler:

Solucion 2 (Ya habiendo ejecutado el Android Market):

Si ya han ejecutado el Android Market y el instalador no pudo encontrar las Google Apps el procedimiento es descargarlas, instalarlas nuevamente via ROM Manager en la opcion «Install ROM From SD Card» y podemos buscar de nuevo las google apps en el Market e instalarlas sin problema

¿Que pasa si unicamente las busco en el Android Market?

En mi caso todas las aplicaciones descargadas (Gmail por ejemplo) no funcionaron hasta instalar el ROM descrito anteriormente.

Y con esto soy un usuario feliz de Cyanogenmod en mi nexus one :).

Querys con multiples columnas en JPA (JPA Projection)

Un error bastante común al desarrollar aplicaciones con JPA es volvernos perezosos y acostumbrarnos a siempre traer de vuelta los objetos enteros aun cuando solo necesitemos un par de propiedades.

Otro error común cuando somos principiantes en JPA (más que todo por ignorancia) es hacer varias consultas para obtener varios atributos desde la base de datos sin obtener el objeto completo.

Sin embargo podemos jugar un poco con JPA utilizando JPA projection para obtener solo los atributos que queremos

Imaginemos el siguiente escenario, donde tenemos una clase Foo equivalente a la tabla foo con 5 atributos-columnas.

Asi pues tendriamos

public class Foo{
private int id;
private String codigoUniversalProducto;
private String nombreUniversalProducto;
private BigDecimal existenciaActual;
private BigDecimal pedidosPendientes;
/*Getters y setters*/
}

Ahora bien imaginemos que nuestro servidor es de bajo rendimiento y por cada atributo nuestra implementacion de JPA tarda alrededor de 0.02 segundos en hacer el mapeo, por cada fila que obtengamos de la base de datos tardaremos 0.1 segundos.

Si esto lo traducimos a un resultset de 5000 filas tendriamos automaticamente 500 segundos solo para efectuar el mapeo. Obviamente estos tiempos son sobredimensionados pero imaginemos que este resultset es parte de una logica más grande y que es necesario hacer varias consultas a la misma tabla para algun procedimiento dentro de un EJB donde SOLO necesitamos los atributos de nombre y de existencia actual.

Si hacemos cuentas al solo obtener de regreso dos columnas de la base de datos en lugar del objeto completo, la operacion de mapeo tardaria 0.04 segundos en lugar de 0.1 segundos, con el resultset de 5000 filas tendriamos 200 segundos de operaciones de mapeo, interesante reducción no?.

¿Solución?

Solo obtener las columnas que necesitamos y eso lo hacemos con JPA projection, JPA projection es una funcionalidad de JPA para realizar mapeos de varias columnas dentro de una tabla y obtenerlas de tal forma que sean manipulables como objetos (el objetivo de los ORM), en JPA tenemos dos modos de funcionamiento SELECT con expresiones multiples, y utilizando constructores.

SELECT con expresiones multiples

Analogo a lo que realizamos con sql plano con JPA podemos hacer una consulta sobre las columnas que necesitamos. Por ejemplo

SELECT f.codigoUniversalProducto, f.nombreUniversalProducto FROM Foo AS f

Si ejecutamos esta query lo que obtendremos sera un listado de objetos de tipo generico Object. Dependiendo si fueron una o más  columnas este Object representara otro objeto de tipo Object[] o un tipo de dato en particular si nuestra query fue sobre una sola columna.

Por ejemplo:

List Object[] results =  em.createQuery("SELECT f.codigoUniversalProducto, f.nombreUniversalProducto FROM Foo AS f").getResultList();
for (Object[] result : results) {
System.out.println("Codigo: " + result[0] + ", Nombre: " + result[1]);
}

SELECT utilizando constructor
Sin embargo si queremos ir un poco más alla tambien podemos utilizar los constructores de nuestros objetos (mi metodo preferido). Con esta alternativa estariamos utilizando de nuevo los POJO’s que utilizabamos sin rediseñar nuestra arquitectura, por ejemplo con la query anterior deberiamos agregar el siguiente constructor a nuestro POJO:

public foo(String codigoUniversalProducto, String nombreUniversalProducto)
{
this.codigoUniversalProducto=codigoUniversalProducto;
this.nombreUniversalProducto=nombreUniversalProducto;
}

Y utilizamos este constructor desde nuestra expresión JPA

SELECT NEW org.shekalug.tuxtor.Foo(f.codigoUniversalProducto, c.nombreUniversalProducto)FROM Foo AS f;

La query anterior es totalmente equivalente y un ejemplo de uso seria:

String queryStr = "SELECT NEW org.shekalug.tuxtor.Foo(f.codigoUniversalProducto, c.nombreUniversalProducto)FROM Foo AS f;"
List Foo resultado = em.createQuery(queryStr).getResultList();
for(Foo fooObjeto:resultado)
{
System.out.println("Codigo: "+foo.getCodigo()+" Nombre: "+foo.getNombre());
}

Vale la pena resaltar que se puete utilizar cualquier POJO independientemente si represente una tabla o no.

Misma cara nuevo peinado

Después de casi un año regreso \o/, aun no se ingles pero si he mejorado y seguiré con el experimento y al fin veo la luz al final del tunel en la Univerisidad. Creo que ya es tiempo de retomar la escritura aca.

Luego de que toda Guatemala dejara la onda blog y se metiera en la onda social media (porque aceptemoslo es más difícil encadenar 3 párrafos coherentes que 250 caracteres con estupidez permitida), he visto que un par de bloggers de vieja escuela regresan y creo que eso me motiva(no pseudobloggers que copiaban noticias esos ahora ya solo ponen links en twitter).

Un par de cosas que han pasado en estos dias:

¿Sigo usando FLOSS?

Si

¿Trabajas con FLOSS?

Tambien

¿En serio trabajas con FLOSS?

Si

¿Promoves FLOSS?

Si pero de diferente manera

¿Otros blogs, cual es cual?

-Este blog (donde el TODO #1 es poner más cosas sobre java para aportar a Guatejug)

En ingles (que seguira enfocado en Gentoo y en reflexiones persionales)

Mi fotolog

¿Nuevo peinado?

-Si, ahora el blog es compatible con social media para estar cool, pero no le cambie el template porque me gusta

¿Que esperar de ahora en adelante?

Más java, más codigo, mismas reflexiones, menos eventos y . . .

las mismas locuras que hicieron que 70 personas en algun momento de su existencia me agregaran a su rss y/o entrega via mail.

Y por ultimo gracias a todos por no aprovechar ninguna vulnerabilidad en mi wordpress porque lo tenia desatendido.

Si aun no se han dado cuenta todas las lineas a excepción del saludo tienen menos de 240 caracteres (sarcasm mode off).

Saludos 🙂

Cerrando . . .

. . . . por unas semanas.

Hace tiempo les comente que tenia otro blog experimento para practicar mi gramática en ingles. Sin embargo por mi falta de tiempo siempre termino escribiendo todo en español. La idea original era mantener ambos blogs con contenido paralelo pero no tengo el suficiente tiempo. Asi que mientras no tenga TOEFL para seguir estudiando este blog permanecerá en la inactividad.

Pueden seguirme (y corregirme) en este blog y ver un par de fotos en mi fotolog.

Espero que no sea mucho tiempo 🙂

Terminando el dia . . .

Paralelismo de realidades

Querido Esposito,

Ha manera de redactar nuestra historia, aquella que es y no es. Y no es, porque nunca existió. Y es, porque tiene un contexto imaginario, mágico y paralelo a esta realidad. Ha ésta de átomos y moléculas, de electrones moviendose en la red. De fotones y neutrinos. De tu familia y la mía. Pasa el tiempo, y cada vez que respiro soy menos ella: tu esposa imaginaria. De eso que paso hace diecisiete años. Yo ocho y tu cuatro. Tuvimos a nuestro unico y amado hijo por alquimia, con un antepasado de la tarjeta NVIDIA, mucho helado de vainilla, migajas de galleta oreo y como olvidar al pequeño pinguino. Imagina ambos tan pequeños que ibamos a saber de familia, de amor de padres, de responsabilidades, solo eramos eso, niños. Nuestros padres sabiendolo, tomaron a nuestro amado hijo y dandoselo a una buena y linda famlia, borraron nuestros recuerdos. Paso el tiempo. Imaginó tu rostro al verlo por primera vez, en una actividad de usuarios de computadoras. Al intersectar su mirada, lo has sabido. Tanta emoción, que te invade, que solo pudiste decir.. patojo 073!. Empezaste a conocerlo, instruirlo y enseñarle sistemas operativos no propietarios. Ah! que tardes! hablando por horas de videojuegos.

A mi, me ha costado más. Llegue tarde. Pero cuando hable por primera vez con él por medio del protocolo IRC.. lo supe. Era mi pequeño! Mientras escribo, salen las lágrimas de mis ojos. Mi gordo bello. Pero la familia de nuevo reunida, no duró mucho. Acaso seguiremos siendo niños imaginarios?. Es hora de escribir, de nuevo de átomos y moléculas. De neutrones y fotones. Donde somos, sólo tres fanáticos de Linux. Pero en el fondo, tu y yo sabemos, que el sigue siendo nuestro amado hijo,

(ducuchu)

—–

Un cuento de mi gran amiga y gran escritora Andrea Rodas :D. Bastante bueno y creativo, el borrador lo hizo en una conversación de chat literalmente de la nada. Si eso no es talento no se que lo sea.

PD. Creo que solo los de slgt entienden todo el cuento.

FLOSS Barcamp Xela

Un Barcamp es basicamente una reunion de conferencias basadas en anarquia donde todos participan con el fin de compartir conocimiento. Aca en .gt han habido un par y solo puedo decir que he ido a uno y terminaron en un pleito web que simplemente me parecio gracioso ^_^.

Pero bueno la gente de xelalug va a organizar uno para este fin de semana, centrado en FLOSS y creo que voy a asistir. Lo mejor de todo es que no se si dare charlas o no. Solo se que voy a participar :P.

Si se deciden echar el viaje o son de Xela, nos vemos el sabado.

Mi nueva Scrum vida – reglas vrs. guias

Como algunos ya saben estoy tratando de independizarme y fortalecer un proyecto personal de desarrollo y soporte, que espero que termine en algo más grande. Y ya que aun no estoy dedicado al 100% al ambito laboral la verdad prefiero que sea en algo mio y no codeando como desquiciado (si necesitan algo pregunten jajaja) por mala paga.

Continue reading →