Mostrando las entradas con la etiqueta web. Mostrar todas las entradas
Mostrando las entradas con la etiqueta web. Mostrar todas las entradas

miércoles, mayo 28, 2014

Spring REST Services y el error Required String parameter is not present

Desarrollando una API REST utilizando Spring MVC, y consumiéndola con AngularJS, me enfrenté al problema "Required String parameter is not present". Así es como lo solucioné.

Hace poco "vendí" (en rigor sólo convencía  mi jefe que es buena idea tomar este enfoque) una idea para abordar nuevos desarrollos. Consiste en desarrollar una API REST, utilizando el generador de código Telosys, y generar las interfaces con HTML5, CSS3 y JavaScript de modo de consumir los servicios con AngularJS.
Nada nuevo dirán, pero ofrece la ventaja que el mismo desarrollo web puede ser portado sin demasiado esfuerzo a una aplicación móvil usando Phonegap, o bien a una aplicación de escritorio utilizando Node-Webkit.

Este tipo de desarrollo resulta bastante rápido, y si logras una combinación entre Angular-UI-router y plantillas web con controladores propios (los controllers de AngularJS), se obtiene una modularidad bastante atractiva.

El problema

El código no tenía problemas, pero al tratar de realizar una llamada POST con Restangular a pesar de que el JSON con los datos que debía recibir la petición estaba bien construido, la llamada arrojaba el error:
Required String parameter 'usr' is not present

Soluciones propuestas

De las soluciones propuestas, después de realizar muchas búsquedas, ninguna funcionó:
  • Forzar que todas las peticiones POST indicaran en sus headers
    Content-Type = 'application/x-www-form-urlencoded' con el código:
  • $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';   
  • Agregar el atributo enctype="application/x-www-form-urlencoded" a la etiqueta form.
  • Realizar la llamada con AngularJS nativo vs usar Restangular.

Hasta pensé en cambiar el enfoque y usar HATEOAS, pero significaba realizar demasiados cambios a la aplicación (en rigor regenerar el código, Telosys se encarga del trabajo sucio).

Solución

Dí con este artículo de StackOverflow, donde explican que el servicio debe recibir un objeto que tenga todos los parámetros de la petición. Algo como:
@RequestMapping(value = "events/add", method = RequestMethod.POST)
public void addEvent(@RequestBody CommandBean commandBean){
    //some code
}

donde se debe indicar que el objeto (puede ser un POJO) CommandBean es el  @RequestBody. Y Spring se encargará de capturar los parámetros adecuadamente.
Y eso funcionó sin problemas.

miércoles, marzo 26, 2014

GulpJS amistoso con AngularJS

Hace poco después de mi lectura diaria descubrí GulpJS. Es una simpática herramienta de línea de comando que permite optimizar muchas cosas del desarrollo web, desde la minimización de imágenes, hasta la "liposucción de código" como le llamamos en la oficina al proceso de eliminar comentarios y mensajes de debug.
El resultado normalmente es un archivo .js minimizado, un archivo .css también minimizado, e imágenes y archivos .html "optimizados".

No les voy a enseñar a usarlo, eso lo pueden ver en detalle en los siguientes enlaces (todos en inglés):
Los primeros problemas a los que me enfrenté fueron básicamente que las configuraciones por defecto son muy agresivas, por lo que mis HTMLs quedaron sin algunos atributos necesarios para que mis controladores Angular funcionaran, y que derechamente mis controladores Angular dejaron de funcionar.

Después de leer algo de documentación para revisar las opciones de los plugins de Gulp que decidí usar, y trás algunas pruebas, llegué al siguiente código, que me ha arrojado los mejores resultados:

// Include gulp
var gulp = require('gulp'); 

// Include Our Plugins
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var changed = require('gulp-changed');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var stripDebug = require('gulp-strip-debug');

// Lint Task
gulp.task('lint', function() {
    return gulp.src('js/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});

// Concatenate & Minify JS
gulp.task('scripts', function() {
    return gulp.src(['js/angular.min.js', 'js/Directive/bindonce.min.js', 'js/jquery-2.0.3.min.js', 'js/bootstrap.min.js',  'js/app.js', 'js/*.js', 'js/Service/*.js', 'js/Filter/*.js', 'js/Directive/*.js', 'js/Controller/*.js'])
        .pipe(concat('appjs.js'))
        .pipe(stripDebug())
        .pipe(gulp.dest('dist'))
        .pipe(rename('app.min.js'))
        .pipe(uglify({ mangle: false }))
        .pipe(gulp.dest('dist'));
});

// include plug-ins
var minifyHTML = require('gulp-minify-html');
 
// minify new or changed HTML pages
gulp.task('htmlpage', function() {
  var htmlSrc = '*.html',
      htmlDst = 'dist';
 
  gulp.src(htmlSrc)
    .pipe(changed(htmlDst))
    .pipe(minifyHTML({ empty: true, spare:true, quotes: true }))
    .pipe(gulp.dest(htmlDst));
});

// include plug-ins
var autoprefix = require('gulp-autoprefixer');
var minifyCSS = require('gulp-minify-css');
 
// CSS concat, auto-prefix and minify
gulp.task('styles', function() {
  gulp.src(['css/bootstrap.min.css', 'css/*.css'])
    .pipe(concat('styles.min.css'))
    .pipe(autoprefix('last 2 versions'))
    .pipe(minifyCSS())
    .pipe(gulp.dest('dist'));
});

// default gulp task
gulp.task('default', ['htmlpage', 'scripts', 'styles'], function() {
});

Lo único que no pude resolver a través de parámetros (y si alguien lo sabe se agradece si comparten el dato) fue el hecho que el plugin minify-html se "come" mis espacios en blanco intencionales (a veces necesarios) y los atributos que no tienen valor (como el bindonce). Tan grave no es si sabes donde ponerlos de vuelta, pero eso ya es parte del trabajo manual.

domingo, diciembre 15, 2013

¿Es el fin de las aplicaciones de escritorio?

Hace poco me encomendaron  el desarrollo de un sistema de software. Inicialmente pensé en usar Java, pero terminé con algo "más web".



Cuando nos enfrentamos al desarrollo de software, aparte del diseño acorde a la captura de requerimientos que se haya realizado, y las interfaces de usuario; entre muchas otras cosas; se debe escoger la tecnología adecuada.

La elección de que tecnología utilizar normalmente va ligada a la instalación, vale decir en las características de la máquina del cliente donde se instalará la aplicación. En la propuesta inicial pensé en realizar el desarrollo usando Java y una base de datos H2. Logré un avance para la generación medianamente rápida de la GUI, sin embargo me di cuenta que para conseguir interfaces de usuario sencillas, y por sobretodo intuitivas, Java me limitaba demasiado, aún considerando Swing, JavaFX y muchas otras librerías de terceros que entregan infinitas alternativas.



La alternativa:

Hacer un desarrollo "más web", vale decir desarrollar el FrontEnd en HTML y el backend en modo "servidor". Entre las elecciones "lógicas" estaba utilizar un servidor Apache Tomcat, un Jetty, o algo para contener JSP y Servlets, o usar Apache (o similar) con PHP.
El problema de esas opciones es que el computador huésped, la máquina del cliente y usuario final, de una u otra manera termina convirtiéndose en un servidor, eso sin considerar la cantidad de dependencias que se deben considerar:
  • JDK de Java
  • Servidor web
  • Motor de base de datos
  • Plugins varios
  • etc.

Pensé ¿.NET será una alternativa? y el problema es similar al de Java, necesitas previamente instalar muchas dependencias. Si el PC del cliente no tiene todo lo necesario, una aplicación que pesa un par de megas significa finalmente descargar sobre 40 MB de instaladores anexos. ¿Cómo evitamos eso?

De vuelta al enfoque inicial

¿Una WebApp local quizás? Con eso se soluciona el peso de la aplicación, aunque hay 2 problemas:
  1. El almacenamiento de datos usando WebDB está limitado a las restricciones del navegador que se utilice. Eso y los riesgos que el usuario utilice distintos navegadores, generando inconsistencias en la información, o que haga una limpieza agresiva del caché del navegador (lo que eliminaría la BD).
  2. La versión del navegador es un elemento que no se puede ignorar, y créanlo, aún hay usuarios de Internet Explorer 6...

Busqué alternativas disponibles, y ahorrándoles el proceso de análisis y selección de la a mi parecer mejor, finalmente llegué a node-webkit.
Aprovechando mi reciente incursión con Node.js decidí hacer algunas pruebas, que luego de resolver un par de problemas han resultado en una aplicación que cumple todas mis expectativas. Lo que utilicé:


Y una vez llegado a esto empiezo a cuestionar que tanto vale la pena desgastarse tratando de hacer una aplicación de escritorio, con miles de dependencias y limitaciones. Más considerando que hoy en día todo avanza hacia convertirse en Web:
  • La comunicación entre las personas se vuelve más y más Web, sólo piensen en las redes sociales.
  • La experiencia de juego cada vez se enlaza más a la Web.
  • Aplicaciones móviles desarrolladas de manera híbrida, vale decir HTML5+CSS3+JavaScript+API nativas. Phonegap lleva mucho avanzado en esta línea.
  • Las aplicaciones de Windows 8, que muchas veces están desarrolladas 100% usando tecnologías web.
  • Los temas de escritorio de GnomeShell utilizan CSS para muchas de sus definiciones.
  • Muchos widgets de escritorio de cada uno de los distintos sistemas operativos
  • El mismo Node.js que es JavaScript en el servidor.
  • Me arriesgaría a decir que más del 90% de los desarrollos de Google.

Incluso escalar este el modelo de aplicación de escritorio web no es tan difícil, pensando en un escenario en el que se decida masificar el uso de la aplicación en la organización.

Estoy claro que esta línea puede no ser la respuesta a todos los problemas que podemos enfrentar en desarrollo de software, pero al menos a mi me hace dar una segunda mirada cada vez que me hablan de desarrollar una aplicación de escritorio.

Si tienen dudas sobretodo respecto a como resolver la persistencia de datos con node-webkit, Sequelize y SQLite no duden en hacerlas.


martes, agosto 20, 2013

Diseño orientado al pixel vs Diseño web

Hace algún tiempo que me vengo relacionando con varios amigos diseñadores. Debo decirlo, sus trabajos gráficos son increíbles, pero lamentablemente tienen poca o nula idea de diseño web.

En cuanto a mi apreciación, ¿porqué tan radical? se preguntará el honorable lector. Muy simple, la mayoría de ellos dibuja muy bonito, sabe usar Photoshop (cosa que yo no sé), pero son todos obstinados en cuanto a su diseño. Cuando se ponen a diseñar sitios web, insisten en usar anchos fijos, ubicaciones estáticas, todo orientado al pixel.

Y esto es herencia de su escuela, muchos aprendieron diseño en papel, o diseño digital. Saben a la perfección de paletas de colores, colores complementarios, balance en la imagen, y muchos otros conceptos que claramente yo NO manejo ni conozco. Pero no saben de diseño web, y de como focalizar un trabajo gráfico increíble en la atención de los visitantes del sitio.

Con el tiempo he desarrollado la capacidad de poder pasar un diseño en PSD, o una simple imagen, a una versión web con HTML y CSS, sin demasiado esfuerzo. Pero ello implica saber, y sobretodo entender que el diseño orientado al pixel aplicado a web es contraproducente. Hay un desgaste no menor tratando de alinear todo a la perfección, y si el diseñador no está consciente de esto, y el cliente tampoco, entonces puede ser un factor bastante negativo para el proyecto.

Para web el diseño que sirve es netamente conceptual:

  • Paleta de colores adecuada
  • Ubicación referencial de los elementos importantes de cada página
  • Imágenes de fondo
  • Tipografías
Incluso muchos de esos elementos ya son la sintonía fina del diseño. 

No es tan necesario esforzarse tanto en que el diseño esté pensado para pantallas de 1024x768 con un contenedor de 980px y un espacio útil de 960px, y que todo encuadre perfectamente en esas dimensiones. Tarde o temprano alguien con otra resolución verá el sitio y este se verá mal, y lamentablemente, siempre pensando en diseño web,  no se puede satisfacer todas las necesidades de diseño. Pensemos solamente en los distintos dispositivos móviles en los cuales se podría ver el sitio, y la orientación del dispositivo (vertical u horizontal).

No digo que para el diseño web no sirva ajustarse a una resolución, pero no pensar en el pixel. Es hora de que, ustedes amigos diseñadores, empiecen a distinguir cada elemento y cuál es su importancia en el diseño web, más que solamente ver si debe estar 10px a la derecha de la imagen principal y cuadrar dentro de un espacio de 960px.

lunes, mayo 21, 2012

Instalación de Phreeze: Framework MVC para PHP

Desde hace poco estoy desempolvando mis destrezas programando PHP. Estaba entre arreglar mi generador de código (algún día hablaré del mítico DbCommand y su generador de código) y crear unas plantillas Velocity para generar código  PHP o encontrar un Framework FRB (Fácil, Rápido y Bonito)  que me cree los CRUDs que necesito y me permita seguir usándolo sin demasiada dificultad (por eso lo fácil).

No puedo decir que evalué, sino más bien miré, varios Frameworks. CodeIgniter, Zend, CakePHP, y varios otros algo más desconocidos, todos son muy muy completos, pero son tan completos como complejos. Yo buscaba algo fácil. Y llegué a Phreeze.

Phreeze me convención en un video de 3 minutos. La aplicación genera un CRUD completo para bases de datos MySQL con sólo algunos clicks. Me dejé seducir por el video ya que Phreeze es bastante complejo y hay mucho de magia detrás.
A punta de prueba y error logré decifrar como instalarlo en un entorno "no preparado". Hay que decirlo la documentación es completa, pero hasta hace poco carecía de tutoriales, y no es precisamente un Framework para enfrentarse sin un buen ejemplo, o un buen tutorial (personalmente prefiero los 2dos).

Requerimientos previos:

  •  Apache
  •  MySQL, sino no tiene sentido haberlo bajado...
  •  PHP, sino no va a funcionar
  •  PEAR  para PHP
  •  Habilitar mod_rewrite en la configuración del Apache

En mi caso yo uso Ubuntu, así que la instalación la hice usando apt-get y Synaptic (ya se que el nuevo Software Center supuestamente es más simple, pero yo soy de la vieja escuela).

La habilitación de mod_rewrite tiene sus "ques":

  • Se debe editar el archivo de configuración de sitios de Apache reemplazando donde dice
    AllowOverride None
    por
    AllowOverride All
    para que  los directorios que deban ser afectados por este módulo.
    En Ubuntu el archivo se encuentra en:
    /etc/apache2/sites-enabled/000-default
  • Habilitar el módulo mod_rewrite copiando el archivo a la carpeta de módulos habilitados (comando en una sola línea):
    cp /etc/apache2/mods-available/rewrite.load/etc/apache2/mods-enabled/rewrite.load
  • Reiniciar Apache:
    service apache2 restart


Supongo que está de sobra decir que los comandos se ejecutan en modo root ( sudo su - , o derechamente con sudo) .


Instalación:

  • Bajar el archivo comprimido desde la página oficial y descomprimir en alguna carpeta que sea visible desde su servidor web, por ejemplo /var/www/phreeze (de hecho llamarla phreeze es lo recomendado).
  • Ajustar los permisos para la carpeta temporal de Phreeze, en 
    /var/www/phreeze/builder/temp
    ejecutando
    chmod -R 777 /var/www/phreeze/builder/temp
    Los permisos 777 suelen ser  "complicados", pero claramente no van a asignar todos los permisos en un servidor de producción.
    ¡HÁGANLO SOLAMENTE EN MÁQUINAS DE DESARROLLO NO EXPUESTAS!
    (Sí, les grité, pero fue sólo para asegurarme que entienden esto.)
  • Verificar que funcione visitando http://localhost/phreeze/builder
  • Generar sus CRUDs.

Instalación de los CRUDs:

  • Descompriman el archivo que les generó Phreeze en alguna carpeta. Procuren  respetar los parámetros de configuración que dieron en el builder.
  • Ajusten los permisos de la aplicación a 755
    chmod -R 755 *
  • Cambien los permisos de la carpeta template_c a 777
    chmod -R 777 templatec
    Esto es para permitir que las plantillas puedan ser compiladas a la carpeta local.
    OJO
    : Yo uso Smarty, Phreeze permite usar Smarty o Savant como motores de plantillas (templates), la carpeta template_c es de Smarty, si usan Savant es otra carpeta.

Los comandos los ejecutan en la carpeta donde descomprimieron su aplicación.

Creo que con eso tienen para entretenerse. Les recomiendo que vean los tutoriales en video de Phreeze, son muy ilustrativos de como se usa la aplicación.

martes, marzo 13, 2012

jQuery Mobile borrar item en listview usando swipe

En este momento estoy usando jQuery Mobile para desarrollar algunas interfaces para unas aplicaciones móviles. Gracias a PhoneGap puedo compilarlas para Android y pasan de ser un desarrollo 100% a una desarrollo que sigue siendo web, pero tiene olor a aplicación.

Dentro de la interfaz me enfrenté al problema que lo limitado del espacio en pantalla no me permite incluir demasiados botones, y requería de una manera para eliminar ítemes de una lista en modo inset. Quise copiar un poco la interfaz de webOS (de la difunta Palm)  para esto, una interfaz muy similar a la que provee iOS en el iPhone.


La idea:

  • Deslizar el dedo desde izquierda a derecha para eliminar un ítem.
  • Deben aparecer botones que permitan borrar el ítem o cancelar la operación de borrado.
  • Al seleccionar borrar se debe confirmar la eliminación antes de hacerla efectiva.


El código y el ejemplo:

Observaciones:
La variable onswipe marca como activa la acción de eliminación. Si se está eliminando un item, no se podrán eliminar otro.
Una vez que se hacen aparecer los botones para la eliminación es necesario desactivar los eventos tap y click sobre el ítem de la lista, sino va a tomar la acción por defecto y los botones no van a poder capturar el evento de click sobre ellos.
Se ha utilizado la etiqueta "button" en vez de "a" (para enlaces) para evitar que el framework aplique los estilos de lista (en este caso lista tipo inset).

Está probado en Android y en iOS y funciona. Seguramente alguien lo va a poder mejorar.
El código toma bastantes referencias de lo discutido en https://forum.jquery.com/topic/adding-an-iphone-style-swipe-to-delete-button-to-a-listview . Lamentablemente el código original no me funcionó.

lunes, octubre 11, 2010

Solicitud de Feedback para aplicación CuantoQueda

Dado que me censuraron, lo pongo por aquí.
Hola a todos.
Como algunos sabrán la aplicación CuantoFalta desarrollada por Onda Labs dejó de funcionar. Esta era una aplicación para celulares iPhone o con Android que permitía saber cuanto faltaba para que llegara la micro al paradero.
Dado esto, y a modo de experimento hice algo parecido que originalmente denominé CuantoQueda. Tiene algunas diferencias gráficas y conceptuales respecto a CuantoFalta, pero la idea es la misma.

Necesito voluntarios que me puedan decir si funciona en distintos celulares con acceso a internet, que se le puede mejorar a la interfaz y comentarios varios.

La URL desde la que pueden acceder es:

Hay una versión Lo-fi (enlazada al final de la página) para celulares más viejitos (funciona con una Palm Treo 680, y con Opera Mini).
Con navegadores normales también funciona, pero me interesa saber que tal andan las versiones (hi y lo-fi) en distintos celulares. Ojala me puedan indicar marca, modelo y si se puede que navegador usan.

Bueno eso. Gracias.
Si aún andan en micro (usando el Transantiago, échenle un vistazo) y corran la voz. De repente les sirve a más personas y recibo más feedback del regular.