Web Analytics
Mostrando entradas con la etiqueta struts. Mostrar todas las entradas
Mostrando entradas con la etiqueta struts. Mostrar todas las entradas

Una mala idea

Vamos a ir cerranding esa amalgama de ideas que vengo escribiendo. Voy a proponer una aplicación mínima cliente-servidor que cumpla parte de los requisitos que dije antes.

Voy a recortar en todo lo posible, por ejemplo no se usarán bases de datos y el cliente no persistirá ningún tipo de información. La cuestión es que todo lo que no sea imprescindible para demostrar la viabilidad de un proyecto mayor nos lo saltemos a la torera. Partir de un tablero en el que se puedan mover fichas puede dar lugar a las damas, o a cualquier otro juego de tablero por turnos, con un poco más de lío con la lógica de negocio y la sincronía por red.

Añado requisitos técnicos más específicos del desarrollo o de tecnologías a emplear como la necesidad de pruebas unitarias, incluso la programación orientada a pruebas para poder desarrollar por contratos (se podría pasar a una persona un juego de pruebas y decirle que quieres el software que las cumpla).

A estas propuestas de calidad en desarrollo también se deberán ajustar los scripts de configuración citados anteriormente.

Cito las tecnologías que se usarán y las piezas de software y problemas que resolverán:

1) Servlet/Struts/Struts2/web services.

La centralización del servidor no necesita una conexión viva. Un cliente podrá ser identificado por una sesión web. Incluso se podría descargar al servidor de mantener sesiones si se hiciera un servicio web o se identificara unívocamente al cliente mediante algún oro mecanismo.

El que un cliente haga un “polling” para ver si existen actualizaciones se ve día a día con clientes de correo, rss, etc. Liberará al servidor de hacer un push en los clientes y la posible contratación de un servidor dedicado para realizar procesos batch.

Partidas, torneos, etc se podrían almacenar en base de datos así como configuraciones y sus posibles versiones.

Finalmente, diremos que se preferiría utilizar struts2, servicios web o servlets planos a struts… Soy así de cerdo o lo que sea… Tengo mis razones, una es que estoy hasta la coronilla de struts… Otra es que quisiera programar cliente y servidor sin depender de esa capa de abstracción que me obligaría a usar Struts para poder llamar al negocio. Los demás, hasta cierto punto, implementan una fachada de entrada al modelo más o menos directa.

Inicialmente aunque sea cliente servidor, se podrá hacer que el cliente se ejecute sin comunicación por red aunque sea esta simulada. De todas maneras para funcionar en junit no hará falta matarse.

2) Beanshell

Beanshell, tras mis pruebitas en una kvm y en la jvm completa, parece ser una potentísima herramienta de scripting. Se pueden crear clases enteras o instancias de clases definidas sin tipado…

Los scripts usan la gramática de Java así que si se diera el caso de que una mecánica programada en scripts madurase lo suficiente como para convertirse en parte de una aplicación, se podría compilar y unirse a ella. Se pueden distribuir en jar y un largísimo etcétera que me hace pensar que se podría tner un cliente mínimo y programar un Terminal desde el servidor.

3) Cliente Android

Sí. Me centro en esto. Se enchufa al ordenata y depuras diréctamente sobre la máquina, eso sin instalar rollos raros ni nada de eso.

El SDK pesa poco y es fácil de usar. La API, después de un golpe inicial contra esos conceptillos que se han sacado de la manga los chavales de google, resulta hasta cómoda y hay componentes para todo o pegas una patada a una piedra y salen cinco.

Las interfaces se pueden describir en documentos XML y éstos podrían estar en el servidor.

4) Junit

Hay un tipo de misiles, supongo que basados en la mente de la mujer, que se llaman “fire’n’forget”… Bromas aparte. Esto de junit, medianamente bien usado, hace que puedas programar una parte de tu lógica, probarla unitariamente, incluso hacer pruebas más grandes uniendo más piezas, y no volver a ellas hasta que rompas algo por otra cosa.

Te olvidas, eso está programado y funciona como esperabas.

Últimamente he descubierto algunas cosillas por ahí que me facilitarán la programación de pruebas respetando los estándares de encapsulamiento y herencia. Podré organizar mejor las pruebas.

Con junit se pueden probar los scripts beanshell… Depende de lo que quieras que hagan y todo eso, pero bien organizados se podrían probar. Incluso una serie de scripts pueden ser un proyecto en sí ya que al final no se distribuye una aplicación compilada sino una serie de ficheros .JAVA. Cada fichero Java se puede compilar, ejecutar con junit sus métodos, probar de mil formas y ver de mil maneras.

¿Por qué no actualizar la aplicación con las clases diréctamente? Porque es un engorro que se puede ahorra al usuario. Sin tocar más que una parte de toda esta maraña, se tendría al día el cliente y el servidor.

Quizá sea una muy mala idea. Pero puede intentarse.

Salú.

A cup of my famous java

Javascript e Internacionalización.

No se por qué lo llamamos "internacionalización"... Si viene diciéndose traducción o doblaje de toda la vida. Pero nada, nada, la cosa es poner letra por letra la misma palabra y a españolear.

Pues nada que, tonto de mí, iba a hacer un par de funciones para poder internacionalizar mi javascript y, de paso, hacer un favor a la línea en la que trabajo en Capgemini para facilitar la separación de javascript incrustado de las jotasepeses... Es una lacra que tenemos que pagar para entregar a tiempo. Símplemente se escribe el javascript, o peor, se copia de otra página.

Pocas cosas aprendí de mi empresa anterior salvo que, a veces, puede ser útil tener a alguien revisanding el código que se hace. La verdad es que para revisar el código aquí, aparte de que, como en la anterior empresa, no hay nadie con la capacidad técnica (me incluyo entre los incapaces) se necesitarían varios a tiempo completo ya que la cantidad de código generado en una línea en un día es inabarcable para un refactor bien estudiado. Pero se debería hacer para evitar tanta repetición y tantas barbaridades y patadas a las biblias (si las hay) de esto del desarrollo web.

Cada línea de javascript que se escribe es un paso a la tumba. Hay quien dice que así, en cliente va todo más rápido y casi sin frotar... Pero es que hay que depurarlo y cuando se corta y se pega en otra página hay que depurarlo dos veces... Y cuando se corta y se pega en otra página y, además, se modifica para que cuando pintaba X ahora ponga Z pues hay que depurar las dos de antes y seis más para que lo nuevo quede bien.

Yo soy más de aquel tutorial por el que parece que nadie ha pasado ya. Si se lee bien, te enseñan por qué usar JSPs, qué es un documento JSP en contra de una página JSP... Qué es un Servlet y por qué no usar más de uno. Además de proponer todos los patrones de diseño que ahora implementa Struts y que se citan en este libro que tengo por ahí de una vez que me volví loco y me dio por comprar libros.

En el tutorial, aparte de usar un controlador y el patrón command o delegate (hay que tener en cuenta que explican cómo usar Java y no una librería de terceros como es Struts, pese a que Sun se implica en el desarrollo de Struts) y de todas las pariditas que a uno se le ocurran, dicen expresamente que las páginas JSP (mejor usar documentos JSP) deberían poder ser escritas por alguien que no tenga ninguna capacidad como programador. Cualquiera con Dreamweaver o Notepad y un poco de idea sobre lo que es un tag HTML debería poder aprender a maquetar para nuestra aplicación. Así que antes de ponerse al meollo habría que pasear el documento funcional, las maquetas y las descripciones de su funcionamiento por los “expertos” en presentación o por alguien que decida qué tags hay que implementar.

El resultado de esta preparación seria una o varias librerías de etiquetas (custom tags) con sus correspondientes ficheros javascript. Todos estos se pueden incluir como librerías en Dreamweaver, Eclipse, Netbeans o a puro ojo en las maquetas con el edit de la línea de comandos.

El maquetista aprenderá a utilizar las etiquetas y a marcar tal o cual opción. Los TLD hoy dia son bastante descriptivos llegando incluso a presentar al cliente (maquetista) los posibles valores para los atributos de la etiqueta.
Visto así nunca haría falta escribir una sóla línea de javascript en las páginas. Salvo, por ejemplo, cuando sea estrictamente necesario. Un ejemplo de esto sería cuando usando Dojo queremos filtrar los parámetros que uno de los tags de Struts2 deberá enviar al servidor para actualizar un DIV pro Ajax…

Bueno… Dada la turria esta que acabamos de tener… Que me he salido totalmente del tiesto, etc… Volvemos al tema.

En mi trabajo ahora mismo utilizo, incluso, Struts1.1. Raro, me decían, que no trabajéis con una beta, ya que las empresas son tan estúpidas de utilizar herramientas tan anticuadas aun siendo gratuitas y no habiendo cambiado su funcionalidad ni las interfaces sino mejorado con el tiempo. Ahora mismo podríamos tener la versión posterior con más bugs corregidos y más facilidades de uso como DownloadAction, cosa necesaria para mis planes y para unas pariditas que he estado haciendo esta semana exportanding cartas en formato PDF…

La cosa estaría en poder internacionalizar el javascript. Actualmente uno de los mayores problemas que tenemos es que en el javascript incrustamos valores que vienen de la petición. Aún hay doctorandos (tócate los cojones) que quieren acceder a la request desde código ejecutado en el cliente (eso es javascript). Tontos aparte, todos sabemos que javascript es texto y, una vez escrito, salvo con algún eval() no se puede cambiar. Así tenemos parámetros a funciones o valores de variables sacados con escrituras de EL (Expresión Language) en mi caso y en el de la gente que trabaja conmigo a los que invito a aprender un poco más, que siempre es bueno. También hay quien escribe scriplets y le cortamos las manos o le dejamos por imposible y le reescribimos lo que haga para no enfadarle porque, encima, se enfadan. Tambien se escriben con bean:write.

La cuestión es que si queremos extraer el javascript de las páginas tendremos que declarar funciones con muchos parámetros para poder pasarles estos valores en su llamada. Los valores se pintarán en la JSP en la sentencia que llama al javascript que estará incluido en un fichero .js.

¿Y los mensajes al usuario? Pues lo mismo. Siempre se pintan con bean:message, ${el} (o con scriplets, no puedo vigilar todo lo que se hace). Y tenemos el mismo batiburrillo. Así que una función para validar un formulario una vez pasada a un fichero externo va a tener una interfaz enorme de la forma:
validate( document.forms[‘miform’], msg1, msg2, msg3, msg4 …);

Porque puede haber muchísimos mensajes de error.

Bueno, pues la solución que se me ocurrió es hacer una función javascript que se descargue los recursos de la aplicación ya internacionalizados (que pasen por la parte online) y que pinte el String que corresponda con la clave que se le de.

Surgen problemas, cada petición de un string a la función generará una petición de los recursos… Esto se puede saltar porque se puede hacer la petición con http GET para que no se cachee en el cliente. Si es que se ha configurado el controlador con parámetros para saltarse la caché del cliente, se podría configurar otra instancia del consolador o un servlet aparte que haga sólo de servidor de recursos.

Así que con una sóla función podríamos internacionalizar la aplicación completa. Pero aun así me estan comiendo los problemas… Tenemos problemas porque el cliente no va a permitir estas chorraditas. Son pariditas molonas pero me se salen del framework, muchacho y como pa hacerme entender el argumento a estas alturas de la película. A mi ponme un solo servlet y no se te ocurra escribir los recursos al cliente que te caneo… Y ya podrás argumentar y regatear que te van a cortar las alas.

Además esto va un pelín en contra de aquello que escribí arriba muy arriba de no ser intrusivo con la página. Cuanto menos código escribamos en la jsp mucho mejor. Una línea menos de javascript, un peldañito más al cielo… Y jQuery se hizo.

Ni por el forro de los jueves podríamos usar jquery en un proyecto. Los clientes se nos iban a chiflar y no veas de qué manera… Bueno, eso también pasa por preguntar y no meterlo sin decir nada a ver si ni lo miran… Pero bueno… Tenemos el problema.

Pero qué cojones. Voy a dejar de ayudar a la empresa y hacer como aquel fulano griego: Ayúdate a ti mismo. Para mis propósitos, si alguna vez tengo que pintar javascript internacionalizado, voy a utilizar jquery, cosa que intento aprender y este plugin para poder incluir mensajes. Además mi acción para descargarme recursos desde el cliente sigue siendo útil: Incluso el plugin jquery me envía el locale del cliente por si no le gusta el que su navegador envía en la petición.

Así quedará una página del tipo holamundo con jquery, el plugin y mi action de descarga de recursos:


Las peticiones hechas por el cliente vistas con firebug:



Y la página en pantalla:


Quod erat demostrandum ^g^

A cup of my famous java

Quizá sea que lo estoy usanding mal, pero struts-menu hace que se cacheen las peticiones entre una y la siguiente de forma que la aplicación no responde igual las dos veces... Bueno, al revés, hace que responda igual pero sin pasar por todas las verticales que antes sí utilizaba.

A ver si me explico. Struts-menu se inventó para usar con struts. En esto, era común configurar el ActionServlet para que no permitiese al navegador cachear las peticiones. La cosa funcionaba.

Llegados a Struts2 me dio, qué se yo, me aburría, por seguir con el plugin en lugar de pintar el menú con una JSP, cosa que puede que acabe haciendo. En struts2 para evitar la caché de los navegadores utilizan Dojo. Dojo evita la caché añadiendo parámetros distintos a los enlaces de forma que cada vez que pinchas en uno, aunque se haga la petición con el método HTTP GET (la que en realidad se cachea), será distinta y no pasará por la caché a preguntar. Es común ver en los enlaces un "[...]&nocache=22142353454578", supongo que el número saldrá de la hora de la CPU o algo de eso.

Pues struts-menu no se lo esperaba así que hubo que actualizarlo para que haga algo de esto. Ocurría que para depurar cualquier cosa tenía que pinchar una y otra vez sobre la opción de menú hasta que al navegador le daba por saltarse la caché o poner la dirección del enlace y pulsar ctrl-F5 para forzar este comportamiento.

El arreglo pasa por añadir un parámetro "nocache" a los enlaces que sea siempre distinto de forma que nunca se almacene en caché la petición provovada por una opción del menú. Por si alguien tiene el mismo problema, debería crear una clase que sobreescriba net.sf.navigator.taglib.DisplayMenuTag y añada el parámetro nocache.


@Override
protected String getPage(String page) {
String ret = super.getPage(page);
if (ret.indexOf('?') < 0 ) {
ret = ret + "?nocache=" + System.currentTimeMillis();
} else {
ret = ret + "&nocache=" + System.currentTimeMillis();
}
return ret;
}

Hay que acordarse de cambiar el tld para que apunte a la clase modificada ^^.

A cup of my famous Java

¡Ahhhhh! Las manos ociosas son la semilla del diablo. Con tiempo en las manos otra vez puedo retomar las tonterías de siempre. Este fin de semana de medio descanso medio oficina no he tocado el compilador, antes me he puesto con 3dmax otra vez y a hacer "papercrafts", figuritas de papel en broma para unos compañeros de la ofi, espero que les molen. Me reí mucho haciendolas y me han quedado aceptables.

Pero Java, java, esto era de Java y algo quería contar... Ah, sí, la cosa iba de struts 2 y struts. Bueno, en realidad debería decir struts1.3 y struts2 ya que en esto no va la cosa como con el cine y eso que uno dice Regreso al Futuro y Regreso al Futuro II... Pero no Regreso al Futuro I, ya que nunca existió...

Bien, pues por qué con un proyecto funcionando y al que sólo faltaba la maquetación, validaciones de entrada y un par más de diálogos le hay que repasar toda la interfaz de usuario y mudarse a struts2... Pues por cuestiones de productividad en cuanto a la interfaz. El mantener los componentes que yo mismo estaba haciendo me hacía perder muchiiisimo tiempo en escribir estúpido, estúpido, estúpido y sucio javascript que, aunque mantenía separado de mis jotasepeses, seguía siendo javascript que yo mismo tenía que mantener...

Uno que es dado a esto de pelearse con librerías, se metió con DOJO dándose cuenta de que todo venía ya hecho, más que probado y hasta en explotación. Es más, se entera uno de que la librería de componentes visuales de Struts2 se basa en DOJO y hasta se separa de DOJO si falta hiciera... Así que, qué carajo, a por Struts 2.

Una del par de pantallas que me quedan por hacer es un editor. Tenía otro pero era un cacota de textarea... Ahora gracias a las librerías tengo un editor con el que obtener html completo donde mis usuarios pueden editar entradas, poner imágenes, cambiar tipos de letra... Sólo por esa tontería había que incluir DOJO y sólo por incluir DOJO y no tener que escribir ni una sola línea más de la cuenta en cuanto a javascript se refiere... Struts2

Refactor time

David me ha dado muuucha envidia, carajo.

Las pérdidas de memoria ya que struts2 no reutiliza los action me habían echado atrás en su uso. Ayer me pasé un ratillo leyending y releyending documentación sobre Struts1.x y Struts2.x y comparativas entre uno y el otro.

Me encontré aquel strutscx que ayudé a mejorar y que, por lo que tengo visto, aun no se han incorporado mis cambios en la forma de validación. Aun contesto a los mensajes de la lista aunque, visto struts2 o el más viejo STX que creo, como strutscx no siguió en desarrollo.

El uso de strutscx o stxx era puntual en cualquier aplicación ya que usaban demasiada memoria. Con mi sistema de validación ahorrabamos muchísima ^g^. De hecho, que lo sepa el mundo, uno de los que preguntaban en la lista trabajaba en thawte con lo que puedo decir que hasta Google ha utilizado mi código ya que los PDF que se generan dinámicamente en su portal cuyas firmas digitales utiliza Google pasan por mi validador y por mi serializador XML de peticiones web ^^.

Fue mi primera aplicación en explotación, carajo.

Bueno pues eso es una mierda ahora al lado de struts 2. Me vuelvo a struts2. Hay versión nueva, que no es del todo... del todo... Y que se ve cada vez más madura (¡qué raro poder decir esto en femenino!). Así que me vuelvo a struts2, carajo. Ayer tocó crear unos scripts para hacer backup del svn que tengo montado. Voy a partir de uno limpio y partir mi aplicación en cuatro proyectos. Ahora mismo son tres.

Tengo tres proyectos, uno web donde va struts y todas las capas salvo la lógica de filtrado de documentos que está en otro proyecto. El tercero sería la generadora middlegen. Al principio la usaba para regenerar todos los VO y mapeos extrayending lo que hay en la BDD... peeeero... Llegaron las vistas que tienen su punto de utilidad. No me gustan nada, pero hay que reconocerles su mérito.

La aplicación, no lo he probado pero es fácilmente medible, irá más rápido si uso consultas directas sobre las tablas que sobre vistas, pero tienen su utilidad para extraer "metadatos". No se si existe la palabra metadatos en castellano, pero así se puede llamar a estadísticos y a todas esas cosillas que hay que explotar en una base de datos como envíos pendientes, errores en tareas batch, etc... Ahora que lo digo, quizá serán cinco los proyectos ya que, este, también tiene su parte por lotes.

La decisión de entrar con Struts y no con Struts2 fue muy sopesada por mi parte, pero visto lo que me va a ofrecer la segunda de no tener que programar mis propios tags para el uso de ajax, incluso facilidades de sincronía y adaptación a nuevos estándares... Pues, ¡qué demonios!. El cambio es prácticamente trivial por lo que anuncian y, a partir de ahi, ir adaptanding los componentes y añadiending los nuevos.

Quizá me pese un poco al principio porque esto lo tenía mirado como afición y pasar a desarrollar con ello seguro que es un cambio más que radical, pero lo de aprender estas cosas es muy entretenido y aunque traiga quebrantos, seguro que el fin pasa por los medios.

A cup of my famous java: otra vez a por Struts 2... ¡Y me dejé los libros en la ofi! :(

A cup of my famous Java

Me lo han vuelto a decir, que por qué no escribo sobre informática... Será algo que quiero olvidar.

La cosa es que me han preguntado y además es algo que tenemos que solucionar en el proyecto en el que trabajo y en futuros proyectos basados en Struts1.x.

Struts es útil para lo que es y es que con tanto framework surgir de tanto framework limitado a un solo ámbito del desarrollo de software (¿sólo se hacen frameworks web en el mundo?) pues uno se encuentra con muros que saltar a cada paso.

A pesar de que, tengo que reconocer, en la empresa vamos a lomos de gigantes, he tirado para solucionar esto de archivo. Me he ido a una vieja aplicación que hice para otra empresa.

El problema es tener una selección múltiple en un formulario web, manejarla y guardarla en request siempre que haga falta… El número de elementos seleccionados varía dinámicamente entre petición y petición por javascript. Se puede cambiar de página y se debe conservar la selección de la anterior.

En aquel tiempo, aunque sí sabía que eran buenas prácticas, no hacía tags para esto. Hoy se que no hay nada mejor que MVC para el mantenimiento y separación de responsabilidades, quita muchísimos dolores de cabeza. Entonces usábamos Struts y ahora también. Pero ahora voy a hacer esto con tags, qué carajo. A ver si hay gente libre y aprendemos todos algo.

Pregunté a gentes (con experiencia) y me dijeron que pasando un array de objetos javascript iba muy bien porque “ya lo habían hecho” en su día. Yo también, pero no lo recordaba… Vale, me mintieron como bellacos. Lo he comprobado, un array de objetos al controlador se la suda. Hay que utilizar propiedades indexadas (o mapeadas) y no hay más remedio.

En mi aplicación utilizaba propiedades mapeadas para acceder a objetos anidados de un FormBean, era la O de la palabra ola: liberaba session de árboles completos, guardándolos en request. Teníamos una interfaz de edición de cursos, dejábamos al usuario elegir los temas y cambiar nombres a las unidades… Se editaban los libros del curso que después pasaban a un maestro y se podían enviar a impresión, etc. Todo el árbol del curso viene en un bean.

En los formularios hay que acceder a las propiedades que son arrays (propiedades indexadas) con una nomenclatura especial que Commons Beanutils comprende ya per se y, por tanto, Struts también.

Así para enviar al servidor un array de dos elementos, hay que crear dos hidden y no uno sólo:

<input value=”uno” name=”lista[0]” type=”hidden”>

<input value=”otro” name=”lista[1]” type=”hidden”>

En el formbean tiene que haber un método que reciba como entrada un array del tipo que sea el valor, en este caso de String:

public void setList (String [] in) {…

Esto no es una propiedad indexada del todo. Del todo sería esta:

public void setElement (int i, String value) {…

public String getElement (int i) { …

Sin que haya un set para la lista.

Ambos tienen problemas, al primero no se le pueden pasar elementos salteados porque el controlador va a crear un array con el número de elementos que tiene la lista en el documento cliente, si tenemos algo del tipo:

<input value=”uno” name=list type=”hidden”>

<input value=”otro” name=”list" type=”hidden”>

Provocará un ArrayIndexOutOfBoundsException. Porque se crea un array de dos posiciones y se intenta acceder a la sexta…

El otro tiene el problema de que no puede ser “desatendido”, quiero decir, que se tienen que controlar los índices que llegan y hacer crecer el array que recibirá los elementos en consecuencia.

Mi vieja solución pasaba por usar mapas. Cuando llegaba un índice lo almacenaba en un TreeMap que es ordenado y devolverá siempre los elementos como si fuesen de un array al iterar. La clave era un Integer con lo que me pasasen.

Cojonudo… Ahora sólo queda programar en javascript la creación y borrado de elementos de un formulario o algo parecido para poder hacer el post con ese formato de corchetes para propiedades que son múltiples.

¿Qué son propiedades mapeadas? Pues son exactamente igual pero la clave para mapear es un String. En el FormBean los métodos quedan como:

public void setMap (Map in) {…

public void setElement (String key, String in) {…

public String getElement (Strin key) {…

En este no importa que los elementos sean salteados ni nada por el estilo. El formato del documento html cambia en que ahora las claves se dan entrecomilladas para denotar que son String:

<input value=”uno” name=”list" type=”hidden”>

<input value=”otro” name=”list" type=”hidden”>

Al final tenía un setElement parecido a esto:

public void setElement(String key, String in) {

Integer intKey = null;

Try{

Int n = Integer.parseInt(key);

intKey = new Integer(n);

} catch (Exception e) {

//nothing to do

}

If (intKey == null) {

map.put(key, in);

} else {

Map.put(intKey, in);

}

}

Así podia mapear con Strings numéricos y ordenar. Además, donde hacía falta, pasaba una clave del tipo “padre.hijo.nieto” y parseaba hasta el punto para llamar a setters de propiedades anidadas con Beanutils.

Vamos a hacer esto, carajo, y separar a los programadores de toda la chapa de iterar sobre un array para salvarlo en request.