Actualmente, la creación de aplicaciones web resulta un proceso pesado y propenso a errores. Los desarrolladores pueden pasar el 90% de su tiempo estudiando las peculiaridades de los navegadores. Por otra parte, la creación, la reutilización y el mantenimiento de una gran cantidad de componentes AJAX y bases de código JavaScript pueden ser tareas complejas y delicadas. Google Web Toolkit (GWT), especialmente en combinación con el complemento de Google para Eclipse, facilita estas arduas tareas al ofrecer a los desarrolladores la posibilidad de crear y mantener rápidamente aplicaciones JavaScript con interfaces complejas, pero de gran rendimiento, en el lenguaje de programación Java.Aunque a mi me parece que el 90% del tiempo en entender las particularidades de cada navegador me parece una super exageración, si es verdad que los componentes en cada navegador funcionan de una forma distinta, permitiendo GWT abstraernos de estos detalles.Además facilita el desarrollo de la progración con AJAX.
domingo, 11 de julio de 2010
GWT o como facilitar la vida al programador de Javascript
miércoles, 9 de junio de 2010
ManyToMany en Hibernate con anotaciones
Supongamos que por una extraña razón a Geno se le juntan muchos marrones encima (cosa que no pasa casi nunca ;)) y por otro lado están (estabamos) todos los precarios, entonces le encarga a Rafa que los reparta de una forma sencilla. Rafa como está apuntito de casarse piensa que lo mejor es hacer una aplicación sencilla para que Geno la pueda utilizar y le deje escribir su tesis, que aunque él cree que la lleva bien aún le queda por escribir unas 100 páginas.La aplicación será llamada Brown Dispatching y su modelo de datos generaría unas 3 tablas:
- Una tabla para cada miembro del labo, donde podríamos incluir el nombre del precario, el nombre de la máquina, las horas que está o cualquier otra información que pudiese resultar útil para esta situación. En el caso del ejemplo, creo que con el nombre bastaría, además que somos pocos y nos conocemos perfectamente.
- Otra tabla para cada marrón, indicando el nombre, una descripción y una fecha límite por poner unos campos de ejemplo.
- La tercera tabla sería la que finalmente enlazaría a los marrones con los precarios. Por lo que tendría unicamente el identificador único de marrón y el identificador único de usuario.
imports ...
@Entity
@Table(name = "T_PRECARIOS")
public class Precario implements IGwtSerializableParameter {
private Long id;
private String name;
private Set browns;
// ID SETTER AND GETTER
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// NAME SETTER AND GETTER
@Column(name = "NAME", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// BROWNS SETTER AND GETTER
@ManyToMany(
cascade = { CascadeType.MERGE,
CascadeType.PERSIST },
fetch = FetchType.EAGER
)
@JoinTable(
name = "T_PRECARIOS_BROWNS",
joinColumns = { @JoinColumn(name = "PRECARIO_ID") },
inverseJoinColumns = { @JoinColumn(name = "BROWN_ID") }
)
public Set getBrowns() {
return browns;
}
public void setBrowns(Set browns) {
this.browns = browns;
}
...
}
import ...
@Entity
@Table(name = "T_BROWNS")
public class Brown implements IGwtSerializableParameter {
private Long id; // Unique identifier for brown
private String name; // Brown's name
private String description; // Brown's description
private Date finalDate; // Brown's final date
private Set precarios; // Set with the "precarios" associated
// SETTER AND GETTER FOR ID
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// SETTER AND GETTER FOR NAME
@Column(name = "NAME", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// SETTER AND GETTER FOR DESCRIPTION
@Column(name = "DESCRIPTION", nullable = false)
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
// SETTER AND GETTER FOR FINAL DATE
@Column(name = "FINAL_DATE", nullable = false)
@Temporal(TemporalType.DATE)
public Date getFinalDate() {
return finalDate;
}
public void setFinalDate(Date finalDate) {
this.finalDate = finalDate;
}
// SETTER AND GETTER FOR "PRECARIOS"
@ManyToMany(
mappedBy = "browns",
cascade = { CascadeType.MERGE,
CascadeType.PERSIST },
fetch = FetchType.EAGER
)
public Set getPrecarios() {
return precarios;
}
public void setPrecarios(Set precarios) {
this.precarios = precarios;
}
...
}
En modo de anotaciones de Hibernate, las notaciones se pueden poner en la definición del atributo o en el Getter del mismo, como se puede ver yo he elegido ponerlas en el getter.
miércoles, 2 de junio de 2010
Abajo esas etiquetas
Algunas herramientas que podemos usar son el propio paquete markdown (debian | script en perl), pandoc (diversas conversiones), htmldoc (para pasar a pdf un html) y muchas otras utilidades. A la hora de editar markdown desde vim, podemos utilizar un poco de magia de vim.org: http://www.vim.org/scripts/script.php?script_id=2882
viernes, 21 de mayo de 2010
Git en tu prompt
Ultimamente, GIT está causando furor entre los miembros del labo. Aunque el cambio desde Subversion puede ser algo traumático si no se digieren bien los nuevos conceptos, el cambio de paradigma hacia el control de versiones distribuidos merece mucho la pena. Una buena introducción es el libro online Pro Git (recomendación vía Álvaro).
Hoy quiero compartir un snippet que permite personalizar el PROMTP de bash para que muestre en que rama de un repositorio GIT estamos trabajando y un asterisco si tenemos cambios pendientes. Para usarlo, basta con que lo copiéis a vuestro home y lo llaméis desde el .bashrc.
Como característica extra, el prompt cambia de color si abrís una shell de root para que no se os olvide cerrarla.
Actualización: si utilizáis el git desde los ports de mac, echadle un vistazo a este hilo para habilitar el comando __git_ps1
martes, 11 de mayo de 2010
Remontadas
Los sistemas de ficheros compartidos por red son muy útiles a mi me simplifican mucho la tarea de almacenar copias de seguridad en una máquina diferente. Basta con tener montada la partición y usarla como si fuese local.
Sin embargo, cuando hay problemas de red o cortes de luz puede ser necesario montar o remontar esas particiones y se puede tardar bastante tiempo en detectar si no se tiene cuidado. Una forma de atacar el problema es tener a mano un script en el cron. A continuación pego el que acabamos de poner en funcionamiento en el labo:>
Podéis probarlo con la opción --verbose para ver qué hace paso a paso y que puede resumirse en comprobar si el montaje esta ido o desmontado y actuar en consecuencia. No olvidéis sustituir los puntos de montaje al principio del script!
lunes, 26 de abril de 2010
Limpiar ficheros en Python
Este es un problema que surge cuando un equipo trabajan sobre los mismos ficheros de texto, cada uno con su editor, en su sistema operativo... y entre Álvaro, Sebas y yo nos hemos propuesto solucionarlo.
Para ello, hemos creado un script en Python que toma como argumentos una lista indeterminada de ficheros y los "limpia". En concreto:
- Elimina espacios y tabuladores al final de todas las líneas.
- Elimina los retornos de carro estilo MS-DOS, para homogeneizarlos y que se vean "bonitos" en todos los entornos.
- Opcionalmente, por medio del paso de un parámetro extra, se sustituyen los tabuladores de principio de línea por 4 espacios.
python sanitize_nl.py [--retab] <fichero1> [<fichero2> ...]...y listo. Ficheros limpitos y sin problemas.
Podeis descargarlo de aqui
jueves, 8 de abril de 2010
JSON con comentarios
JSON es un formato que permite representar estructuras de datos de una manera muy sencilla y compacta para su uso en aplicaciones web. El formato es deliberadamente simple y austero para evitar problemas, por ejemplo, sólo se utilizan comillas dobles y no se permiten comentarios.
Pero, ¿qué sucede si queremos utilizar JSON para representar configuraciones? Los comentarios son importantísimos y los parsers existentes no lo contemplan. Podríamos meternos en un infierno de expresiones regulares con los problemas que eso puede traer (las regex se quedan cortas para este tipo de trabajos) pero es mejor disponer de un parser adaptado a esta tarea.
Partiendo de la última versión del parser escrito en JavaScript de JSON.org hemos añadido los comentarios de línea (//) y bloque (/* */). Esta opción es más lenta que los parsers integrados en el navegador pero, a fin de cuentas, los ficheros de configuración no deberían ser enormes con lo que es un buen compromiso.
El resultado lo podéis descargar aquí: commented json parser. Para usarlo basta con incluir la biblioteca e invocarlo así:
var object = cjson_parse('{ "hola": /* adios */ "3", \n\
"cumpleaños": "2009-12-12" // fecha temporal\n\
}');