lunes, marzo 22, 2010

MVC en Python

Últimamente he utilizado herramientas como SQLAlchemy y Turbogears en Python. La verdad me ha gustado mucho la flexibilidad y facilidad con la que puedo escribir scripts para procesar información con SQLAlchemy y me ha gustado mucho el modelo MVC de Turbogears 2, parecido al de Spring en Java, por lo que voy a comenzar a implementar más cosas en python.
Comenzaré con un blog/cms en Turbogears, yo sé que existen muchísimas opciones ya desarrolladas que seguramente son mejores a cualquiera que yo pueda hacer, sin embargo, me sirve para familiarizarme en ambiente de trabajo con TG2.

Instalando Turbogears.
La mejor opción es con Virtualenv, que crea un "ambiente virtual" de python para cargar dependencias, librerías y versiones, etc. Sin embargo en producción a mi me ha funcionado instalarlo junto con el resto de python del servidor. Las instrucciones para instalarlo son sencillas y están aquí.
Creando un proyecto
Es muy simple iniciar un proyecto en Turbogears.

$ paster quickstart
Enter project name: Altadefinicion
Enter package name [altadefinicion]:
Do you need authentication and authorization in this project? [yes]
Selected and implied templates:
tg.devtools#turbogears2 TurboGears 2.0 Standard Quickstart Template

Variables:
auth: sqlalchemy
egg: Altadefinicion
geo: None
package: altadefinicion
project: Altadefinicion
sqlalchemy: True
sqlobject: False
tgversion: 2.0.3
Creating template turbogears2
Creating directory ./Altadefinicion
...
...
...
reading manifest template 'MANIFEST.in'
writing manifest file 'Altadefinicion.egg-info/SOURCES.txt'

Si no recibimos ningún mensaje de error, podemos iniciar la aplicación con:

$ paster serve --reload development.ini

Y apuntando nuestro explorador a http://localhost:8080 podremos ver una página de bienvenida.



Entrando al directorio del proyecto podemos observar una simple estructura:

$ tree -d
.
|-- Altadefinicion.egg-info
|-- altadefinicion
| |-- config
| |-- controllers
| |-- i18n
| | `-- ru
| | `-- LC_MESSAGES
| |-- lib
| |-- model
| |-- public
| | |-- css
| | `-- images
| |-- templates
| `-- tests
| |-- functional
| `-- models
|-- data
| `-- sessions
`-- ez_setup

25 directories

Por default TG2 usa SQLite como motor de base de datos y almacena todo en un archivo llamado devdata.db para crear la base de datos por default con datos de prueba hay que correr otro comando de paster:

$ paster setup-app development.ini

Con esto ya tenemos lista la cimentación para construir una aplicación con python, usando Turbogears 2 y SQLalchemy

martes, febrero 02, 2010

Neither BindingResult nor plain target object for bean name "command"...

Este error me sale frecuentemente y sobre todo después de muchas correcciones o adecuaciones a nuevos controllers en spring-mvc.

Siempre pierdo mucho tiempo tratando de encontrar el error, por que cuando veo el código tanto del jsp como del controllores todo parace perfecto, sin embargo el error persiste.

Cuando encuentro la solución siempre recuerdo que ya lo había hecho así antes y ahora quiero ponerlo aquí para que no se me olvide.

El error sale cuando inserto un nuevo objeto para persistir, no cuando edito uno ya existente y la respuesta está en la salida con succesView
return new ModelAndView(success);

Si successView no está definido me arroja el error, cuando se modifica el objeto successView es editado para mostrar nuevamente la forma de edición, sin embargo cuando el objeto es nuevo, pasa el parámetro de successView que está definido en el dispatcher. Entonces, si no hay successView definido en el dispatcher, me encuentro con ese error.

    <bean id="catalogoEstrategiasFormController" class="com.deuxbits.ssaspps.webapp.controller.CatalogoEstrategiasFormController">
        <!-- property name="validator" ref="beanValidator"/ -->
        <property name="successView" value="redirect:catalogoestrategias.html"/>
        <property name="catalogoEstrategiasManager" ref="catalogoEstrategiasManager"/>
        <property name="userManager" ref="userManager" />
        <property name="catalogoProgramasManager" ref="catalogoProgramasManager" />    
    </bean>





viernes, marzo 20, 2009

Arreglando locale en Ubuntu 8.10 Intrepid

En una nueva instalación del Ubuntu Intrepid, en su versión a 64 bits, batallé dos días para arreglar el problema con el locale, principalmente con perl.

El mensaje era el siguiente:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = "en_US:en",
LC_ALL = (unset),
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

Intenté de varias formas arreglar el locale con:

# locale-gen en_US.UTF-8
# update-locale en_US.UTF-8
# update-locale-config en_US.UTF-8

Ajustando la configuración de "/etc/environment":
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
LANGUAGE="en_US:en"
LANG="en_US.UTF-8"


y la configuración de "/etc/default/locale":
LANG=en_US.UTF-8

Pero el error seguía, en mi estación también tengo el Intrepid instalado pero en su versión de 32 bits, y llegué a pensar que el problema venía en los paquetes de 64 bits.

Buscando en google nunca dí con una solución clara al problema y entonces decidí buscar sin especificar la distribución de linuz, para obtener resultados más genéricos y encontré la línea que me ayudó a resolver el problema.

# localedef --no-archive -i en_US -c -f UTF-8 en_US.UTF-8

y después las subsecuentes...

# locale-gen en_US.UTF-8
# update-locale en_US.UTF-8
# update-locale-config en_US.UTF-8

y problema resuelto.

Lo copio aquí para próximas instalaciones.

martes, febrero 24, 2009

MyEclipse 7.0 y Visual HTML Designer

Es necesario de vez en cuando editar HTML y en Linux a la fecha no hay un editor decente, para mi. Sé que existen y he usado el Quanta+ y el difunto NVU, pero ninguno de los dos se compara con el Dreamweaver.

Entonces escribo código en Linux y luego hago los arreglos cosméticos en la Mac.

MyEclipse, es la herramienta de desarrollo que más utilizo ahora, tiene un editor decente de html con preview, pero desde hace años sigue en modo "experimental" que es una forma de cubrirse por si tiene algún error.

Lo puedo activar agregando al laucher -Dlinux.experimental=true

En MyEclipse 7.0, se agrega al final de
~/Genuitec/MyEclipse 7.0/myeclipse.ini

Quedando mi configuración así:
-startup
../Common/plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
--launcher.library
../Common/plugins/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805
-clean
-configuration
/home/pablito/Genuitec/MyEclipse 7.0/configuration
-vm
/home/pablito/Genuitec/Common/binary/com.sun.java.jre.linux.x86_1.5.0.011/bin/java
-vmargs
-Xms256M
-Xmx512M
-XX:PermSize=128M
-XX:MaxPermSize=256M
-Dlinux.experimental=true

No olvidar instalar la librería libstdc++5 de lo contrario MyEclipse no arrancará arrojando un error poco claro.

viernes, enero 09, 2009

Hibernate Annotations y DELETE_ORPHAN

DELETE_ORPHAN aún no es soportado por JPA, pero es una opción muy útil cuando manejamos colecciones.

Afortunadamente Hibernate 3+ tiene esta opción.

Agregamos "@OneToMany(cascade=CascadeType.ALL)" pero esta cascada no incluirá el borrado de registros huérfanos que después de algún tiempo se pueden aglutinar en la base de datos.

        @OneToMany(cascade=CascadeType.ALL)
        @Cascade({org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
        public List<BillDetails> getBillDetails() {
                return billDetails;
        }

sábado, agosto 09, 2008

Extendiendo la memoria virtual en el Nokia N800

La máxima memoria virtual del N800 es de 128KB, quiero agregar por lo menos 1GB que tomaré de la tarjeta interna.

La SD interna es de 8GB y la tengo ocupada sólo con respaldos de contactos, correos etc.

Entro como root desde mi desktop.
hopper800:~# sfdisk -l /dev/mmcblk0

Disk /dev/mmcblk0: 250112 cylinders, 4 heads, 16 sectors/track
Warning: The partition table looks like it was made
for C/H/S=*/103/2 (instead of 250112/4/16).
For this listing I'll assume that geometry.
Units = cylinders of 105472 bytes, blocks of 1024 bytes, counting from 0

Device Boot Start End #cyls #blocks Id System
/dev/mmcblk0p1 39+ 77704- 77665- 7999488 b W95 FAT32
start: (c,h,s) expected (39,79,1) found (0,130,3)
end: (c,h,s) expected (1023,102,2) found (996,102,2)
/dev/mmcblk0p2 0 - 0 0 0 Empty
/dev/mmcblk0p3 0 - 0 0 0 Empty
/dev/mmcblk0p4 0 - 0 0 0 Empty


El formato original de la tarjeta ocupa los 8GB en una partición FAT32.
hopper800:~# sfdisk /dev/mmcblk0 -uM
Checking that no-one is using this disk right now ...
OK

Disk /dev/mmcblk0: 250112 cylinders, 4 heads, 16 sectors/track
Old situation:
Units = mebibytes of 1048576 bytes, blocks of 1024 bytes, counting from 0

Device Boot Start End MiB #blocks Id System
/dev/mmcblk0p1 0+ 6799 6800- 6963199+ b W95 FAT32
/dev/mmcblk0p2 6800 7815 1016 1040384 82 Linux swap / Solaris
/dev/mmcblk0p3 0 - 0 0 0 Empty
/dev/mmcblk0p4 0 - 0 0 0 Empty
Input in the following format; absent fields get a default value.

Usually you only need to specify and (and perhaps ).

/dev/mmcblk0p1 :0,6800,82
/dev/mmcblk0p1 0+ 6799 6800- 6963199+ 82 Linux swap / Solaris
/dev/mmcblk0p2 :,,83
/dev/mmcblk0p2 6800 7815 1016 1040384 83 Linux
/dev/mmcblk0p3 :
/dev/mmcblk0p3 0 - 0 0 0 Empty
/dev/mmcblk0p4 :
/dev/mmcblk0p4 0 - 0 0 0 Empty
New situation:
Units = mebibytes of 1048576 bytes, blocks of 1024 bytes, counting from 0

Device Boot Start End MiB #blocks Id System
/dev/mmcblk0p1 0+ 6799 6800- 6963199+ 82 Linux swap / Solaris
/dev/mmcblk0p2 6800 7815 1016 1040384 83 Linux
/dev/mmcblk0p3 0 - 0 0 0 Empty
/dev/mmcblk0p4 0 - 0 0 0 Empty
Warning: no primary partition is marked bootable (active)
This does not matter for LILO, but the DOS MBR will not boot this disk.
Do you want to write this to disk? [ynq] y
Successfully wrote the new partition table

Re-reading the partition table ...

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)


El tamaño de la tarjeta no es exactamente 8GB asi que ajusto el tamaño como sigue:

/dev/mmcblk0p1 :0,6800,82

Partición tipo 82 (linux), el resto lo dejo como swap, tipo 83

/dev/mmcblk0p2 :,,83

Ahora doy formato a la partición swap:

hopper800:~# mkswap /dev/mmcblk0

Checo con free si lo tengo lo hice bien.
hopper800:~# free
total used free shared buffers
Mem: 126796 113880 12916 0 7712
Swap: 1040376 0 1040376
Total: 1167172 113880 1053292

Aparentemete el sistema me reconoce el swap de 1GB. weeeeee! y además es de tipo swap cosa que le ahorrará mucho proceso por no pasar por el sistema de archivos FAT32.

Ahora cada vez que se reinicie el tablet se perderá este swap, lo mejor es configurarlo para que se monte automáticamente.

Lo podemos agregar en /etc/fstab para que lo carge cada vez que se reinicie.

hopper800:~# cat /etc/fstab 
rootfs / rootfs defaults,errors=remount-ro,noatime 0 0
/dev/mmcblk0p1 /media/mmc1 vfat rw,noauto,nodev,noexec,nosuid,utf8,uid=29999 0 0
/dev/mmcblk0p2 none swap sw 0 0


Luego agregar la siguiente línea antes del exit 0 en /etc/init.d/rcS :
swapon -a

OK swap listo, ahora el resto de la tarjeta la formateamos como ext2, más eficiente que FAT32.

Tenemos que instalar las librerías necesarias por que no están incluídas por default en el OS2008.Diablo.

hopper800:~# apt-get install e2fsprogs

Ahora podemos formatear nuestra partición
hopper800:~# mkfs.ext2 /dev/mmcblk0p1 
mke2fs 1.37 (21-Mar-2005)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
870912 inodes, 1740799 blocks
87039 blocks (5.00%) reserved for the super user
First data block=0
54 block groups
32768 blocks per group, 32768 fragments per group
16128 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 32 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.


Esta partición se monta automáticamente.

Espero que el desempeño de mi tablet mejore con esta configuración.

lunes, julio 21, 2008

Agregando librerías al proyecto en Maven 2

Desarrollando una aplicación para facturación digital, requiero de aplicar un sello de seguridad y la librería de la cual depende ese método no está en los repositorios de Maven2, si quiero mantener el control con Maven2 debo de incluir esta librería al repositorio local.

La librería es Not-Yet-Commons-SSL, que maneja varios protocolos de seguridad y llaves.

Paso 1:
Bajar el jar a un direcotorio temporal.

curl -C - -O http://juliusdavies.ca/commons-ssl/not-yet-commons-ssl-0.3.10.jar

*No tengo el wget a la mano en Leopard, así que lo bajé con curl

Paso 2:
Lo agregamos en el repositorio local de Maven2

mvn install:install-file -Dfile=not-yet-commons-ssl-0.3.10.jar -DgroupId=org.apache.commons -DartifactId=not-yet-commons-ssl -Dversion=0.3.10 -Dpackaging=jar

Paso 3:
Lo ponemos como dependiencia en nuestro proyecto

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>not-yet-commons-ssl</artifactId>
<version>0.3.10</version>
<scope>compile</scope>
</dependency>


Como uso Eclipse, tengo que volver a ejecutar mvn install eclipse:eclipse para que la librería sea instalada.
Listo!