domingo, 25 de diciembre de 2011

Banana Campus

Seguro que todos los usuarios de Internet somos también usuarios de al menos una de las muchas redes sociales que existen. ¿Quién no ha probado Facebook, Twitter o Tuenti? Este tipo de Webs han revolucionado la forma de utilizar la red, poniendo en contacto casi permanente a los usuarios.

Pero la realidad es que la mayoría de las redes sociales de uso masivo se limitan a proveer herramientas para "amigos": compartir fotos, jugar online, enviar mensajes... y el uso que se les da es exclusivamente "social". ¿Por qué no aprovechar las grandes posibilidades que proporcionan para algo más "útil"?

Un claro ejemplo es lo que propone otra red social que sí tiene ya un importante calado entre los usuarios de Internet: LinkedIn. No se trata de una simple red para compartir con tus amigos, sino que pretende ser un punto de encuentro de profesionales, desde el que pueden nacer oportunidades de trabajo y negocio.

Pues hoy quiero hablar de una red social que nació hace poco tiempo en España, y que tiene la intención de ser realmente útil: Banana Campus.

Banana Campus pretende poner en contacto a las personas relacionadas con el mundo universitario, con el fin de que puedan compartir sus conocimientos y experiencias. Su funcionamiento es muy simple. Cualquier persona puede publicar información sobre su vida universitaria: qué le pareció una carrera, cómo le fue en un Erasmus... y esa información queda disponible para que otras personas que estén interesadas en vivir esa experiencia puedan conocerla con mayor detalle.

Además, en su última actualización, han incluido nuevas opciones que le dan un valor añadido importante, como son la posibilidad de compartir apuntes o ejercicios, y de publicar anuncios para buscar piso, cambiar de grupo, o cualquier cosa que se os ocurra.

¡Así que todo el mundo a unirse a Banana Campus! Seguro que le encontraréis mucha utilidad, y además estaréis apoyando un proyecto nacido en nuestro país, y animando a que sigan apareciendo ideas emprendedoras como esta.

lunes, 19 de diciembre de 2011

Dividir archivos en Unix

Resulta que hace unos días necesitaba consultar el log del servidor de producción, y me encontré que pesaba nada menos que ¡400 megas!. Intentar abrir algo así con mi portátil era misión imposible, porque el pobre ya no está para esos trotes, así que necesitaba una solución alternativa.

Una buena opción para estos casos son los programas que dividen archivos. En Windows hay varias alternativas como el hacha o el hjsplit, pero, ¿qué pasa si estamos en sistemas Unix? Pues después de un buen rato buscando, resulta que averigüé que no necesitamos ninguna herramienta, sino que podemos utilizar directamente el comando split. Su sintaxis es:

split [parametros] [archivo_origen] [archivo_salida]

Si no especificamos parámetros, el archivo se divide en nuevos archivos de mil líneas, y a cada uno se le nombra como archivo_salida (o x si no se especifica ese parámetro), con el prefijo aa, ab, ac, etc. También podemos pasarle un guión como archivo_origen, y el comando dividirá lo que reciba por la entrada estándar.

Los parámetros nos permiten adecuar el funcionamiento del comando a nuestras necesidades. El más interesante para mis necesidades era el que modificaba el tamaño de los ficheros obtenidos:

-b valor indica el tamaño de los ficheros en número de bytes (también se puede usar -bytes=valor)

Y tampoco me extiendo más, porque su uso es simple, y su documentación es perfectamente clara. Lo importante es saber que está ahí si lo necesitamos.

miércoles, 9 de noviembre de 2011

Juegos de caracteres en Unix

Hace días estuve trabajando en un proceso de migración de datos. El proceso se ejecutaba en un sistema Unix, y recibía como entrada un simple fichero de texto plano. Pero, ¿cómo no?, ese fichero había sido generado bajo plataforma Windows.

El tema es que aunque el fichero se podía ver perfectamente con cualquier herramienta Windows (notepad++, ultraedit, y hasta el bloc de notas), incluyendo sus acentos y eñes, en el momento en que lo subía al equipo con Unix todo se descuajaringaba. Incluso si volvía a descargar el fichero (tanto la carga como la descarga utilizando Filezilla), pasaba a no verse tampoco en Windows.

Supongo que algún día terminaré de enterarme de los misterios que encierra la codificación de ficheros. Pero de momento me consuelo con saber que tengo una solución para conseguir que mi fiero no sufra mutaciones horrorosas.

Existe una función llamada iconv que permite cambiar la codificación de ficheros en Unix. En mi caso conseguí lo que quería con un simple

iconv --from-code=ISO-8859-1 --to-code=UTF-8 entrada.txt > salida.txt

Incluso podríamos reducirlo más

iconv -f ISO-8859-1 -t UTF-8 entrada.txt > salida.txt

También podemos utilizar la opción -l (o --list) para ver qué codificaciones hay disponibles en nuestro sistema.

domingo, 30 de octubre de 2011

Error de Jasper Server

Este error me lo encontré hace unos días ejecutando informes en Jasper Server.


 ERROR JSErrorPage_jsp,http-8080-Processor24:329 - 
java.lang.NullPointerException
at com.jaspersoft.jasperserver.war.action.ViewReportAction.checkForParams(ViewReportAction.java:143)
at sun.reflect.GeneratedMethodAccessor337.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
...

Un puntero nulo en un método que, si nos fiamos de su nombre, comprueba los parámetros del informe.

Aunque en principio supuse que el problema debería ser que el valor de alguno de los parámetros fuese nulo, lo que realmente ocurre cuando nos encontramos este error es que hemos definido un Input Control asociado al reporte en el servidor, y éste no encuentra correspondencia en el jrxml. Hay que tener en cuenta que la relación se establece entre el id del Input Control y el nombre del parámetro.

lunes, 24 de octubre de 2011

¡¡Adobe Reader no imprime!!

Me he tirado varias semanas sin poder imprimir documentos pdf desde mi portátil. Cada vez que lo intentaba me aparecía un misterioso mensaje: "Antes de realizar tareas relacionadas con la impresión, como la configuración de página o la impresión de un documento, debe instalar una impresora".


¿Que debo instalar una impresora? ¿Estamos locos? Tengo nada menos que nueve impresoras instaladas, ¿no le parece suficiente? Es más, si accedo a la opción Archivo - Configuración de impresión del Reader, se abre sin ningún problema el diálogo para definir las preferencias de impresión para cada una de ellas...

Rebuscando por Internet, sobre todo en páginas en inglés, se pueden encontrar muchas recomendaciones para solucionar este problema. Especialmente insistente es la idea de actualizar nuestra versión de Adobe Reader. Pero ni por esas...

Hasta que hace unos días, curiosamente, el mensaje desapareció y pude imprimir de nuevo. Pero, ¿por qué?, que diría Mou. Pues finalmente lo descubrí. Resulta que la impresora que tenía como predeterminada del sistema era una impresora de la red de mi oficina, a la que no tengo acceso más que cuando estoy allí trabajando. Y parece que el Reader se ofusca cuando le dices que quieres imprimir, y no es capaz de conectar a la impresora predeterminada. Bastó con marcar como predeterminada de Windows XP una impresora accesible para que todo volviese a funcionar.

martes, 11 de octubre de 2011

Uso de parámetros en Jasper


Cuando hacemos un informe con Jasper Reports, es muy normal que utilicemos parámetros. De esta forma podemos enviar datos al informe que serán utilizados a la hora de generarlo. Los casos más habituales quizá sean el mostrar directamente el valor del parámetro, o el usarlo a su vez como parámetro para la consulta SQL que ejecutamos dentro de report. En este caso sólo tenemos que definir el parámetro en la sección correspondiente de iReport, y hacer referencia a él con el formato $P{nombre_parametro}, como se muestra en la imagen.



Pero podemos ir más allá. Por ejemplo podríamos recibir como parámetro la sentencia SQL a ejecutar, o alguna de sus cláusulas. En este caso buscaríamos hacer algo como esto.



Pero si tratamos de ejecutar un informe con este formato no funcionará, y nos mostrará una excepción:

net.sf.jasperreports.engine.JRException: Error executing SQL statement for : report1


Para entender por qué pasa esto, tenemos que entrar en detalle y ver qué hace Jasper cuando procesa los parámetros.

Cuando en la definición de la consulta de un Jasper utilizamos un parámetro con el formato $P{nombre_parametro}, lo que la herramienta genera es realmente una consulta SQL con parámetros. Es decir, tendríamos una consulta tal que select * from tabla where campo = ?.

Ahora bien, si lo que vamos a recibir como parámetro es una sentencia que queremos inyectar directamente en la consulta SQL, esta forma de trabajo no funcionaría. En este caso tenemos que cambiar el formato con el que hacemos referencia al parámetro por $P!{nombre_parametro}. De esta forma le indicamos a la herramienta que no queremos pasar un parámetro a la consulta SQL, sino que queremos directamente incluir el valor textual del parámetro como parte de la consulta.

miércoles, 5 de octubre de 2011

Sin sonido en Youtube con Chrome

Hacía varios días que venía notando un problema muy molesto en mi HTPC. Cuando intentaba reproducir un vídeo de Youtube en Google Chrome la imagen se mostraba perfectamente, pero del sonido no había noticias. Parecía que mi ordenador se había quedado mudo.

Sin embargo, tras hacer las típicas comprobaciones, me encontraba que el sonido iba perfectamente al reproducir vídeos o música con VLC o Windows Media Player. ¿Qué pasaba entonces?

Pues hoy por fin he tenido un rato para dedicarle a este problema. Lo primero que descubrí es que en el mezclador del control de sonido Windows 7 existe un apartado específico para el volumen de Google Chrome; de modo que lo primero que hay que comprobar si el navegador enmudece es que no lo tengamos silenciado.

Si no es tu caso, tranquilo, puede que el problema sea la versión del plugin de Flash que tengas instalado, así que comprueba si puedes actualizarlo. Nunca está de más ponerse al día.

Por último, si todo parece correctamente configurado y sigues sin poder escuchar nada, estás como estaba yo. Accede al administrador de tareas de Chrome (dentro del menú herramientas, o utilizando el atajo shift + esc), localiza el proceso Shockwave Flash, y cárgatelo sin compasión. En las páginas de youtube que tengas abiertas verás el clásico dibujito indicando que ha habido un problema con el reproductor de flash. Refresca la página, y si todo va bien podrás volver a escuchar tus vídeos con normalidad.

jueves, 22 de septiembre de 2011

Uso avanzado del teclado Thinity

Reconozco que soy de esos hombres que no tiene la costumbre de leer instrucciones. Será que sobrevaloro mi propia capacidad para manejarme con los aparatos eléctricos. El caso es que el otro día me encontré ojeando las instrucciones de mi Thinity Wireless Entertainment Keyboard buscando una explicación a mis casi superados, pero aún no explicados, problemas de funcionamiento, cuando descubrí que las instrucciones pueden ofrecer algo más que una guía de dónde enchufar cada cable.

En este caso los descubrimientos tuvieron que ver con el ratón táctil que trae el Thinity. Un ratón que, la verdad, me parecía incómodo y poco útil debido a su pequeño tamaño, y a la ausencia de una rueda de desplazamiento. Estaba acostumbrado a que los touchpad sustituyesen la rueda por un par de botones de desplazamiento o por una zona lateral con un funcionamiento especial para desplazarse por las páginas.

El Thinity, supongo que por problemas de espacio, no ofrece ninguna de estas alternativas, pero ha pensado en una buena alternativa. Si lo que queremos es desplazarnos arriba y abajo por nuestra pantalla, podemos hacerlo deslizando dos dedos sobre la superficie táctil. El resultado será equivalente a utilizar la rueda de los ratones convencionales.

Si preferimos el efecto conseguido normalmente pulsando la rueda de desplazamiento, podemos conseguirlo dando un toque suave sobre el touchpad con dos dedos simultáneamente. Lo que habitualmente conseguiremos es que se muestre el símbolo de desplazamiento.

Incluso podemos evitar tener que utilizar los botones superiores para clic derecho e izquierdo, ya que pulsando con tres dedos obtendremos un clic derecho.

Para rematar, he descubierto que el teclado puede utilizarse tanto con la Play Station 3 como con la XBox 360. Lástima que estas funciones no sirvan de mucho en mi caso...

lunes, 12 de septiembre de 2011

Tutorial de Oracle ADF Business Components publicado en Javahispano

Hoy me han publicado un nuevo tutorial en Javahispano. En este caso el objetivo era hablar un poco de los Business Components de Oracle ADF, y explicar algunas de las cosas que se pueden hacer al trabajar con ellos en jDeveloper 11.

Este tutorial viene a complementar al que ya presenté hace unos meses sobre el desarrollo de una aplicación Web con ADF, y pretende además satisfacer algunas de las solicitudes que me llegaron en sus comentarios.

Espero que sea útil.

sábado, 27 de agosto de 2011

Android - Error en R.java - Syntax Error on Tokens

De vuelta tras vacaciones y líos varios, y justo un mes después de la última entrada, retomo las publicaciones contando un pequeño problema que me he encontrado jugueteando un poco más con Android.

Resulta que estaba haciendo ligeras modificaciones en el main.xml para añadir un simple TextView a la pantalla, y cuando he terminado y me disponía a probar los cambios en el móvil, me he encontrado con que la clase R.java tenía un error.

Lo primero que hay que decir es que esta clase es generada de forma automática, y Eclipse se cuida mucho de que no la toquemos. Si lo intentamos nos avisará de que no debemos, pero no queda ahí la cosa. Si somos temerarios y le decimos que nos dan igual sus advertencias, nos encontraremos con que tras guardar los cambios el entorno volverá a generar la clase perdiendo lo que hemos hecho. Vamos, que el tratar de corregir la clase por nuestra cuenta es una batalla perdida.

Así que para hacer las cosas bien, lo que necesitamos es saber por qué se está generando la clase con un error. En este caso el que se me presentaba era:


La clase R.java, explicado sucintamente, es un índice con todos los recursos del proyecto Android. Luego si hay un error de sintaxis en ella por un token no reconocido, seguramente se deba a que hemos utilizado un carácter extraño en algún sitio.

En mi caso, por ejemplo, tras rebuscar un poco, conseguí darme cuenta de que había declarado el nuevo texto de la siguiente manera:


Lo que a simple vista parece correcto. Pero si nos fijamos otra vez, podemos observar que en el identificador pone @+ìd/enemyLifeText. Esa tilde sobre la primera i es la que está causando el problema. Si la eliminamos, la clase R.java se regenera y los problemas desaparecen.

miércoles, 27 de julio de 2011

Trabajar con varrays en Oracle

Aunque a nivel personal no los he utilizado nunca, en algunas ocasiones me he encontrado en proyectos de mantenimiento con modelos de datos que definían sus propios tipos en Oracle. Lo más habitual es la definición de una colección de elementos utilizando VARRAY.

Cada vez que uno de estos casos se presenta ante mí, me asalta la misma duda. ¿Cómo actualizo o inserto datos en una columna de un tipo definido sobre un VARRAY? La realidad es que no tiene complejidad ninguna. En este caso el valor se crea de forma similar a como se haría con un objeto, poniendo el nombre del tipo y, entre paréntesis, el contenido del array, con los valores separados por comas.

Por ejemplo, si hemos definido este tipo:

CREATE OR REPLACE TYPE MY_TYPE AS VARRAY(100)  OF VARCHAR2(32);

Insertaríamos en esa columna así:

INSERT INTO NOMBRE_TABLE (CAMPO_ARRAY) VALUES (MY_TYPE('1', '2', '3'));

La forma de actualizar sería análoga.

miércoles, 20 de julio de 2011

Tablas en JavaFX 2

En el nuevo JavaFX, existe un componente "oculto" muy interesante. Y digo oculto porque no se menciona su existencia en los tutoriales de la página principal del proyecto, aunque lógicamente sí que podemos encontrar toda la información necesaria en el api. Se trata del TableView.

Como era de esperar, lo que podemos hacer con este componente es mostrar tablas en nuestra aplicación. Su funcionamiento es muy similar al de ListView, pero tiene la ventaja de que permite trabajar con columnas. El caso de uso típico será aquél en que queramos mostrar una tabla donde cada fila contenga, separados en columnas, los atributos de un objeto. 

Si partimos del ejemplo que ya vimos en uso de CellFactory en JavaFX 2, en ese caso definimos un CellFactory para mostrar en cada fila del ListView el nombre y apellidos de una Persona. Como alternativa, con TableView podríamos mostrar cada campo en una columna distinta.


Al igual que ya hicimos trabajando con ListView, podemos definir un CellFactory, en este caso a nivel de columna, en el que indiquemos cómo deben ser presentadas. Por ejemplo, podemos definir la columna para el nombre como una columna de Persona, en lugar de como una de String.


Y ahora, podemos definir el CellFactory para mostrar en la columna el nombre de la persona, con un color dependiente de su edad.


He aquí el resultado.





lunes, 27 de junio de 2011

Excluir librerías del jar con NetBeans

Este post sirve de continuación al que escribí hace casi un año, explicando cómo incluir las librerías de nuestro proyecto en el jar generado por NetBeans. En este caso, y por petición del amigo Anómino a través de los comentarios, vamos a ver cómo excluir librerías.

La clave para hacer lo que queremos está en la etiqueta zipgroupfileset del build.xml. Con este elemento le indicamos al entorno qué queremos añadir al jar que generamos. En aquél caso indicábamos que queríamos meter todos los jar de la carpeta dist/lib.


Ahora se nos presentan dos opciones para quitar elementos. El primero es indicar explícitamente qué librerías no nos interesan en el mismo zipgroupfileset utilizando su atributo excludes.


En este caso, como puede verse, le estamos indicando que no incluya la librería beansbinding.

Si necesitamos dejar fuera más de una, podemos añadirlas separándolas por un espacio.



Como segunda alternativa, en lugar de pedir que se incluyan todas, y luego añadir excepciones, podemos meter un elemento para cada una de las librerías que queramos tener en el jar de la aplicación, de la siguiente forma.


O, igual que antes, podemos tener un único elemento con todas las librerías a incluir separadas por espacios.



En conclusión, que para determinar exactamente qué librerías queremos en el jar de nuestra aplicación no tenemos más que jugar con los atributos includes excludes, y podremos conseguir lo que nos interese.

martes, 21 de junio de 2011

Componente para reproducir vídeos en JavaFX 2

Continuando con el nuevo JavaFX, he empezado a trabajar con la reproducción de contenido multimedia.

Lo primero que hay que resaltar, es que esta nueva versión de JavaFX, al menos por el momento, viene muy limitada al permitir sólo la reproducción de vídeo en formato FLV (que contenga vídeo en formato VP6 y audio en formato MP3).

Tal como se describe en la página de JavaFX, las clases implicadas en la reproducción de vídeos son:

Media - contiene información sobre el recurso, como su fuente, resolución y metadatos.
MediaPlayer - proporciona los controles para la reproducción (arranque, pausa, volumen...)
MediaView - extiende de nodo, y aporta la posibilidad de añadir animaciones, efectos...

Así que podemos reproducir un vídeo FLV con el siguiente código.

media = new Media(mediaPath);
   player = new MediaPlayer(media);
   view = new MediaView(player);
  getChildren().add(vbox);
   player.play();
Partiendo de esta base, he creado un pequeño componente que implementa un reproductor de vídeo sencillo, con posibilidad de pausar, avanzar, retroceder, ir a una posición concreta, y de cambiar el volumen. La clase extiende de javafx.scene.layout.Region, de forma que puede añadirse directamente al layout de una aplicación. Por ejemplo:

public void start(Stage primaryStage) {
     Group root = new Group();
        
     border = new BorderPane();
     border.setCenter(new VideoPlayer(videoPath);
        
     root.getChildren().add(border);
     Scene scene = new Scene(root, 800, 600);
           
     primaryStage.setScene(scene);
     primaryStage.setVisible(true);
  }
A la hora de indicar la ruta del vídeo que se quiere reproducir es importante tener en cuenta que no se admiten espacios; en su lugar tenemos que poner %20. Por ejemplo: 

C:/Documents%20and%20Settings/user/Mis%20documentos/1.flv

Aquí se puede descargar el VideoPlayer.

lunes, 6 de junio de 2011

InstantiationException

En cuanto uno empieza a hacer cositas con reflexión en Java, es normal que se encuentre tarde o temprano con la excepción InstantiationException. Hasta la versión 1.5, el api de Java indicaba respecto a esta excepción algo así como:

Lanzada cuando una aplicación intenta crear una instancia de una clase utilizando el método newInstance de la clase Class, pero el objeto no puede ser instanciado porque es una interfaz o una clase abstracta.

Este mensaje tenía la habilidad de hacernos pensar que los especificados eran los únicos motivos que podían hacer que se lanzase esta excepción. Pero entonces, si estamos absolutamente seguros de que estamos intentando instanciar una clase no abstracta, ¿por qué me puede aparecer el error?

Pues por ejemplo, porque estés ejecutando algo así:

Object o = Class.forName("Clase").newInstance();

Y en la clase Clase no tengas explícitamente definido el constructor sin parámetros. Simplemente añadiéndolo a la definición de la clase solucionaremos entonces el problema.

Es por esto que a partir de la versión 6, el api de la clase InstantiationException ha cambiado su descripción a:

Lanzada cuando una aplicación intenta crear una instancia de una clase utilizando el método newInstance de la clase Class, pero el objeto no puede ser instanciado. La creación de la instancia puede fallar por varios motivos, incluyendo, pero no limitándolos a:

  • El objeto representa a una clase abstracta, una interfaz, un array, un tipo primitivo o void.
  • La clase no tiene constructor sin argumentos.
Mucho mejor.

domingo, 5 de junio de 2011

Uso de CellFactory en Java FX 2

Tras las primeras horas bicheando JavaFX 2, aquí un post en el que explico cómo definir la forma en que se presentan los elementos de un lista.

Lo que tenemos es un objeto de tipo ListView, que se muestra por pantalla como una lista de elementos. Lo primero que debemos tener en cuenta, es que la forma más correcta de manejar su contenido es tener una ObservableList, que será sobre la que hagamos los cambios (adición, eliminación y actualización de elementos). Si fijamos esta lista observable como contenido de la ListView, ésta será notificada cada vez que se produzca un cambio en la colección, y tendremos la vista de nuestra aplicación siempre actualizada.



Pero lo que necesitamos en este caso es manejar una lista de elementos más complejos. Por ejemplo, supongamos que tenemos la clase Persona:


Sin problema podríamos crear una lista para presentar una serie de personas con el siguiente código.


Pero al ejecutar este código, lo que veríamos en la lista sería el valor obtenido al llamar al método toString de la clase Persona. Si no lo hemos sobrescrito, se mostraría la referencia al objeto. Un primer paso para refinar este comportamiento se reduciría a crear un método toString que devolviese el nombre y apellidos de la persona, y así podríamos ver esos valores en la lista.

Pero supongamos que queremos ir más allá, y no sólo presentar el nombre completo de la persona, sino también utilizar un color distinto en función de su edad, mostrando en rojo a los adultos, y en azul a los que todavía no lo son. Pues para eso podemos utilizar el método setCellFactory de la clase ListView.


Como podemos ver, la entrada al método es un objeto que implemente la interfaz Callback, con el que básicamente le decimos a la lista cómo debe crear sus celdas. La interfaz define un único método, call, que devolverá, en nuestro caso, una celda que contiene una persona (ListCell). 



Como podemos ver en el código anterior, el método call define en primer lugar un elemento Text, y después una ListCell, que es la celda que vamos a devolver. En este caso creamos una celda de Persona, y construimos el objeto sobrescribiendo el método updateItem, en el que configuramos el elemento Text como queremos, y lo asignamos como nodo de la celda. De esta forma, cuando veamos la lista por pantalla, lo que se presentará para cada elemento será el Text, con la configuración dada en función de los datos del objeto Persona correspondiente.

No sé si la explicación ha quedado clara, pero al ejecutarlo se verá que la idea es muy sencilla. Además, a partir de aquí surgen muchas posibilidades, ya que podemos representar elementos complejos dentro de una lista contando con todas las posibilidades de JavaFX.

martes, 31 de mayo de 2011

Java FX 2 - Error de instalación del plugin para Net Beans 7.0

El pasado 24 de mayo salió la versión beta del nuevo Java FX 2. Tras mucho tiempo esperando este último intento de convertir Java FX en una tecnología con repercusión, andaba ansioso por empezar a cacharrear, y plantearme algún proyectito para ver qué nos podía ofrecer.

Pero nada más empezar, ya me estaba dando cabezazos. Resulta que tenemos disponible un plugin para la versión 7.0 de Net Beans. Me lo descargo, lo instalo, reinicio el IDE como me piden, y... casquiporre.

Warning - could not install some modules

Y una larga retahíla de librerías o similares.

Como en las instrucciones de instalación no se especifica nada sobre errores, y en principio las había seeguido tal cuál, incluyendo la instalación previa del runtime, empecé a probar siguiendo mi instinto. Reinstalación de Net Beans, rebajada del plugin, reinicio del pc, tonterías varias... nada de nada.

Hasta que en el foro de Oracle encontré la solución gracias a la ayuda de 862201. La historia es que antes de instalar el plugin en sí, hay que instalar todas las actualizaciones disponibles. Esto lo hacemos accediendo a Tools - Plugins, y seleccionando todos los elementos de la pestaña Updates.

Ahora sí, ¡a juguetear!

martes, 24 de mayo de 2011

Review - Teclado Thinity Wireless de Trust

Uno de los periféricos más importantes que adquirí con mi nuevo HTPC, es el teclado Thinity Wireless de Trust. Con este post hago mi estreno en la tarea de analizar y ofrecer mis impresiones de los aparatejos que tengo la suerte de probar. Lo que viene conociéndose en la jerga de la red como hacer una review.

En general el Thinity cumple con los requisitos deseados para este tipo de periféricos. En mi opinión, su punto fuerte es sin duda el apartado estético. Presenta un diseño elegante y moderno, y por su tamaño no destacará más de lo necesario si lo tienes en un lugar visible de tu salón. Los acabados son buenos, y suficientemente resistentes para el trote al que normalmete estará sometido. En cuanto a funciones, presenta todas las teclas habituales, más algunas adicionales como las que permiten manejar directamente el sonido, que son imprescindibles para un teclado orientado al uso con un centro multimedia. Además tenemos también un touchpad, por lo que no necesitamos un ratón adicional. Un importante punto a favor es la utilización de batería. La carga se realiza simplemente colocándolo sobre la base, resultando muy cómoda.



Pero como en esta vida no hay nada perfecto, hay bastantes pegas que ponerle.

Lo primero es tener muy presente de qué estamos hablando. Se trata de un teclado para tu ordenador de salón, así que no esperes poder trabajar eficientemente con él. Tendrás lo justo para poder escribir direcciones Web, nombres de carpetas, y algún que otro correo, pero el tamaño y posición de las teclas no permite hacer alardes mecanográficos. Exactamente lo mismo pasa con el touchpad, con el agravante de que en general al ratón se le da más uso. Personalmente, acabé optando por comprar un ratón inalámbrico. Si simplemente vas a navegar o ver unas fotos, el Thinity puede bastar. Pero a partir de ahí se me hacía demasiado limitado.

Respecto al funcionamiento, en general es correcto, pero en algunas ocasiones me he encontrado con problemas por pulsaciones no detectadas (o detectadas demasiadas veces). Por las pruebas que he hecho, me da la impresión de que los fallos tienen que ver con la posición del teclado (no con su distancia al receptor, que nunca supera los 3 - 4 metros). En cualquier caso resulta frustrante, y le hace perder muchos puntos.

Por último queda hablar del precio. A mí me costó 72,65 €, incluído el iva. Carísimo. Pero no deja de ser un caprichito, y así es como está el mercado de este tipo de periféricos. De hecho, no es de los más caros que podemos encontrar. 

Resumiendo, que es prescindible y mejorable, pero queda muy bonito.

Definición gráfica de ininteligible



lunes, 23 de mayo de 2011

Problemas de memoria

Aunque también podría, no me refiero en este caso a mi escasa capacidad para almacenar recuerdos, sino a la gestión de memoria al trabajar con JPA.

En estos días estoy liado con el desarrollo de un proceso de migración que obtiene información de una base de datos Oracle, la procesa, y la escribe en ficheros de texto. El procesamiento principal se reducía a ir obteniendo todos los registros de una tabla, y tratarlos uno a uno. El volumen de datos estaba en torno a los 200.000 registros.

En sí, el código necesario para este trabajo no tiene mayor complejidad, puesto que no hay más que a ir sacando la información de la base de datos, y manejarla. El problema que se nos va a presentar tiene que ver con los límites de memoria de nuestro pc. Tal como funciona JPA, cada uno de los registros de la base de datos se convertirá en una instancia de la entidad con la que estemos trabajando que, lógicamente, se alojará en memoria. Y lo normal, con estos volúmenes de información, es que no tengamos capacidad para almacenarlos todos.

Al tratarse de un procesamiento iterativo, en el que cada objeto lo utilizamos independientemente del resto, y una vez que terminamos con él no lo necesitamos más, podemos pensar que no hay problema en que en cada momento haya un único objeto en memoria, que sea justamente el que estemos usando. El problema es que JPA no tiene conocimiento de esta situación, y cada uno de los objetos que se van cargando se quedan ahí a perpetuidad. Lógicamente en poco tiempo te encontrarás el temido mensaje:

java.lang.OutOfMemory - Java heap space

Java se ha quedado sin memoria. La solución directa no puede ser otra, por tanto, que aumentarla. Si no cabes en tu casa, búscate una más grande (o mayor, que diría mi hermana). Esto se puede hacer simplemente incluyendo el parámetro -xmx al lanzar tu aplicación. En jDeveloper, por ejemplo, esta opción la puedes incluir en la sección Java Application de las propiedades de tu proyecto.

Esta opción está muy bien, pero tiene pegas. Una importante es que si al final consigues solucionar el problema, estarás en cualquier caso utilizando mucha más memoria de la que realmente necesitas, malgastándola. Una todavía más determinante es que realmente la limitación sigue estando ahí: ¿qué haces si no tienes suficiente ni asignándole a Java toda la memoria de tu equipo? (Aparte de la opción de pasar por caja y ampliar la memoria, que sería una opción un tanto drástica).

Vamos, que mi opinión es que esta no es una buena solución para nuestro problema concreto. El aumento de memoria se debería hacer sólo si realmente necesitas tener toda esa información cargada. Si no, mejor buscar alternativas.

Y nuestra alternativa en este caso es clara. Sabemos que no necesitamos más que un objeto en memoria en cada iteración, así que digámosle a JPA que no los acumule tontamente.

Conforme vamos cargando entidades, estas pasan a ser gestionadas por JPA, componiendo lo que se conoce como Contexto de persistencia. Y mientras una entidad sea gestionada, seguirá estando ahí y no liberará memoria. Por eso existe la posibilidad de decirle a JPA que deje de gestionar entidades, utilizando el método clear. Al invocarlo, todas las entidades del contexto de persistencia dejarán de ser manejadas, y el recolector de basura de Java podrá por fin hacerse cargo de ellas. También existe la posibilidad de aplicar este tratamiento a una única instancia mediante el método detach.

Eso sí, tampoco hay necesidad de invocar al método clear cada vez que terminemos con una entidad. Lo ideal sería hacer el procesamiento por lotes, y liberar cada vez que se termine con uno.

Bajo rendimiento de consulta Oracle con upper

Hace poco estaba trabajando, y tenía una consulta sobre mi base de datos Oracle, que obtenía una sería de datos haciendo un filtrado por un campo de tipo varchar2. La consulta parecía funcionar bien, y tenía un rendimiento perfectamente aceptable. Algo como:

select * from tabla where campo=:parametro

Pero al poco tiempo me di cuenta de que para que la consulta funcionase correctamente en todos los casos, necesitaba que no se distinguiese entre mayúsculas y minúsculas al hacer la comparación. Por tanto, añadí una llamada a upper para el campo (el parámetro siempre llega en mayúsculas).

select * from tabla where upper(campo)=:parametro

De esta forma la consulta funcionaba como yo necesitaba. El problema es que, para mi sorpresa, el rendimiento cayó en picado.

En principio busqué la explicación en la llamada a upper en sí, pero lógicamente este tratamiento no es tan pesado como para producir tanto retraso. El problema está en que el buen tiempo de respuesta de la consulta original se producía gracias a la existencia de un índice sobre la columna campo. Al pasar a hacer la comparación por upper(campo), Oracle no puede utilizar el índice, y el tiempo de respuesta crece exponencialmente.

Ante esta situación, una solución es crear un índice directamente sobre la expresión upper(campo), en lugar (o además) de directamente sobre campo.

create index campo_index on tabla (upper(campo))

Eso sí, hay que tener en cuenta que para que el índice sea utilizado en este caso, es necesario modificar ligeramente la consulta, y asegurarse de que no se obtienen valores nulos.

martes, 17 de mayo de 2011

HTPC

Desde que me convertí en uno más del grupo de mileuristas hipotecados de España, tenía en mente la idea de adquirir un Media Center para mi nueva vivienda. De esta forma podría escuchar música, ver películas, navegar por Internet, y un puñado de cosas más, desde mi sofá con un único aparatito.

Así que llevaba ya bastante tiempo dándole vueltas para decidir qué comprarme. Lo primero que tuve en mente fue el Dell Zino, que en mi opinión es el mejor estéticamente, pero que se quedaba atrás si teníamos en cuenta prestaciones y precio. Así que tras ver algunas otras alternativas premontadas, me animé a pedir presupuesto para un equipo por componentes, y acabé eligiendo esta opción. Cuando tenga tiempo intentaré hacer un pequeño review con la solución que he adquirido, y el resultado que me ha dado. Pero de momento valga esta entrada para agradecer su ayuda a dos Webs. En primer lugar, todohtpc.com, una página en la que puedes encontrar noticias relacionadas con el mundo de los HTPC, y que sobre todo tiene un foro con bastante vida (sin llegar a estar saturado), con mucha información interesante, y gente con una magnífica predisposición a ayudar. Y en segundo lugar, changlonet.es. Esa es la Web de la tienda en la que me he comprado el ordenador, y la recomiendo por el excelente trato que me han prestado. A través de su página ofrecen un servicio que te permite indicar tus necesidades, y ellos utilizarán esa información para proponerte distintas configuraciones que te puedan venir bien. Todo con buen trato, velocidad de respuesta, y muy buena presentación final. De lo que no puedo hablar mucho es del precio, ya que no me paré demasiado a comparar, pero por lo que ví están dentro de mercado.

miércoles, 27 de abril de 2011

Retrospectiva

Pues sí. Así como el que no quiere la cosa, resulta que el blog cumple un año. Y como siempre me han gustado mucho los números y las estadísticas, he decidido hacer un post a modo de resumen de estos primeros 356 días de vida.

Los primeros datos tienen que ver con el número de posts. En total han sido 63 las entradas que he publicado, lo que hace una media de 5,25 por mes. Mi época más prolífica llegó en septiembre de 2010, con diez entradas, justo después del mes de menor actividad, que fue agosto, con una. Algo normal por aquello de que en agosto uno está para casi cualquier cosa, menos para producir, y porque precisamente eso hace que a la vuelta de vacaciones las pilas estén cargadas y la mente repleta de ideas y proyectos.

Evaluando estas cifras, me sorprende gratamente ver que he alcanzado con creces el objetivo que me he planteado todo este tiempo, que era mantener una cadencia de un post semanal. Así que en este sentido espero mantenerme, si bien el objetivo pasa a ser ahora conseguir un ritmo más regular (la diferencia de uno a diez posts en un solo mes es demasiada).

En cuanto a los temas tratados, este es el top-nine de etiquetas utilizadas:

utilidades (11)
Oracle (8)
tutorial (6)
Java (5)
jDeveloper (5)
SQL (5)
ADF (4)
Android (4)
Chrome (4)

Resulta que de lo que más he hablado es de mi experiencia con utilidades software. Algo que no estaba en un principio entre mis ideas para el blog, pero que considero que se ajusta a su temática, por lo que lo doy por bueno. Al fin y al cabo son entradas que también tratan problemas informáticos, aunque a nivel de usuario, lo que democratiza el blog. Por detrás están Oracle, lógico dado que trabajo mucho con sus productos, y tutorial. Esta etiqueta marca uno de los grandes obejtivos que me gustaría cumplir de aquí en adelante: orientarme a la creación de documentación técnica. Algo que veo complicado, ya que requiere mucho tiempo, pero quizá sea cuestión de perseguir objetivos menos ambiciosos, y hacer tutoriales menos exhaustivos. Trabajaremos en ello.

El resto, son las tecnologías con las que más he trabajado en los últimos tiempos, luego ocupan la posición que les corresponde.

¿Y qué hay de los usuarios? En este sentido no me había planteado objetivos, más que nada porque no tenía idea de por dónde podrían andar los tiros, pero lógicamente es algo muy importante; ya que uno dedica su tiempo a escribir algo, agrada que alguien lo lea. Tras un año, el blog ha recibido un total de 5400 visitas, estabilizándose en los últimos seis meses en torno a las 650 visitas mensuales, y a las 25 diarias (con grandes bajadas en fines de semana). El máximo mensual lo alcancé justamente el último mes, marzo de 2011, con 907 visitas. Lógicamente el público hispano es el que se impone por la barrera del lenguaje. Estas son las visitas por países.

España (2.045)
México (810)
Colombia (455)
Argentina (366)
Perú (311)
Chile (246)
Estados Unidos (214)
Ecuador (137)
Venezuela (93)
Bolivia (5)

Si pasamos ahora al top-ten de páginas vistas, el resultado es el siguiente:


El líder destacado es el post en el que explicaba cómo generar ficheros jar en NetBeans que incluyesen las librerías del proyecto. Hay que destacar que se cuelan en las primeras posiciones dos posts orientados a usuarios no técnicos, y un único tutorial. Claro que hay que tener en cuenta la antigüedad de las entradas. La única de 2011 que aparece entre las más visitadas es la que cuenta cómo configurar barras de progreso en Android.

Una conclusión clara (que era predecible) de esta información, es que los post más visitados tienen un marcado carácter técnico, y en su mayoría se reducen a explicar cómo hacer algo. Esto me alegra, puesto que la razón de ser del blog era precisamente la de dar solución a problemas informáticos (de ahí su nombre), y está visto que es ahí donde más interés consigue atraer. Entre otras cosas, y con esto enlazo con el siguiente tema, porque el punto de acceso es, casi únicamente, Google.

Y es que un blog como este tiene difícil la fidelización del lector. Dejando de lado amigos y familiares, pocas personas pueden tener interés en el blog de forma global. La mayoría (un 86% en el último mes), accede a través de motores de búsqueda, y pocas veces alguien que ha entrado buscando información sobre Android se parará a leer también un post que habla sobre Pentaho, y menos aún mis opiniones sobre nuestra maravillosa profesión.

¿Y qué busca una persona para llegar hasta aquí? Pues habiendo visto los posts más visitados, estos datos aportan poca información, pero ahí van algunos ejemplos.

java.lang.noclassdeffounderror: org/codehaus/groovy/control/CompilationFailedException
incluir librerías en jar
no puedo borrar en word
decompilar jasper
km software
4f530e43505002ef
barra de progreso android

El último aspecto que me parece interesante analizar son los comentarios. Si para el autor de un blog es gratificante tener visitas, lo es aún más que éstas participen y den feedback. En todo un año, sólo hay registrados 21 comentarios, y 9 de ellos son respuestas mías. Puede que uno de los motivos de tan poca participación sea la necesidad de logarse para comentar, así que me plantearé probar a eliminar esta restricción temporalmente, y mantenerla si el spam no fastidia mucho. En cualquier caso, aprovecho este post (que atendiendo a los datos, será un grito al viento porque poca gente lo leerá), para pedir a los lectores que comenten. Se aceptan críticas y sugerencias, por supuesto; y si es manteniendo el buen rollo, mejor.

viernes, 22 de abril de 2011

Concatenar una fecha en Excel

El Excel es una herramienta muy práctica y que la mayoría cree controlar bastante bien. Sin embargo, es muy habitual que alguien quiera hacer algo, y no sepa cómo.

Hace pocos días viví un nuevo caso en el trabajo. Un compañero tenía una hoja con una serie de datos, entre los que había fechas. Su objetivo era componer en una celda una sentencia SQL en la que utilizaba los valores de otras celdas.



Seguro que todos diríais que no tendríais problemas para crear esa hoja, pero igual no os resulta tan fácil como pensáis. Eso es lo que nos pasó a nosotros. Lo primero que se os puede ocurrir es utilizar la fórmula:

=CONCATENAR("update tabla set valor=0 where codigo='";A2;"' and fecha='";B2;"'")

Pero el resultado obtenido entonces no sería el deseado:



Lo que muestra Excel al concatenar la fecha con otros textos es el valor interno que éste almacena, que se corresponde con el número de días que han transcurrido desde el 1 de enero de 1900. Entonces, ¿cómo conseguimos que utilice la fecha en formato textual? Pues tenemos que usar la función de conversión TEXTO, de la siguiente forma:

=CONCATENAR("update tabla set valor=0 where codigo='";A2;"' and fecha='";TEXTO(B2; "dd/mm/aaaa");"'")

Así, antes de mostrar la fecha la estamos convirtiendo en una cadena de texto con el formato especificado, y conseguimos el resultado buscado.

domingo, 10 de abril de 2011

Portapapeles múltiple

Más de una vez al trabajar he echado en falta alguna funcionalidad en mi ordenador que podría haberme hecho la vida más fácil. Normalmente cuando me pasa esto me apunto en una lista la idea por si algún día me aburro, y me pongo manos a la obra para tratar de fabricarme una solución a medida. Sin embargo ya aprendí a echar antes un vistazo en Internet, porque normalmente ya existe algo que es más o menos lo que a mí se me había ocurrido.

El último ejemplo lo he encontrado con Multi Clipboard. Hacía tiempo que tenía en mi lista hacer una aplicación que mantuviese a nivel de sistema un protapapeles gestionable, que pudiese tener varios elementos, y que permitiese pegar el que interesase en cada caso. Algo como lo que traen las últimas versiones de Ms Word, por ejemplo.

Pues lo dicho, al buscar en la red he encontrado varias aplicaciones que cubren de una u otra forma esta funcionalidad. He estado probando varias de ellas, y la conclusión es que ninguna llega al nivel esperado. Al final me he quedado con Multi Clipboard. Lo que hace esta herramienta es mostrar una pequeña barra, que puedes ubicar en cualquier posición de la pantalla, con un desplegable en el que puedes elegir entre los últimos textos copiados el que quieres pegar a continuación. Además ofrece las opciones básicas de gestión: añadir textos, editarlos y eliminarlos. Eso sí, parece que no se renueva desde el año 2002, y tiene un aspecto bastante arcaico.

Lo que me hubiese gustado es conseguir una utilidad que además de esta gestión diese la posibilidad de pegar directamente los distintos textos con una combinación de teclas, o de arrastrarlos de manera gráfica.

Seguiré buscando a ver si encuentro algo más completo y, si no, ya tengo con qué entretenerme en tiempos de relajación.

martes, 22 de marzo de 2011

Speed dial

Creo que ya he comentado alguna vez que una de las aportaciones que más me gustó de Chrome fue su página inicial en la que se muestran una serie de accesos directos a las páginas que visitas con más frecuencia.

Sin embargo, también me ha parecido siempre que esta funcionalidad tenía muchas posibilidades de mejora. De hecho hace poco tiempo estuve probando durante un tiempo la alternativa de Opera, siendo su página de inicio similar a la de Chrome, pero mejorada, una de las cosas que más me atrajo.

Lo que presento hoy es un plugin para el navegador de Google que ofrece una nueva página de inicio con el mismo estilo, pero configurable: Speed Dial 2. Existe también un plugin Speed Dial (que en principio no tiene relación, porque parece que tienen desarrolladores distintos), con una funcionalidad similar, e incluso más atractivo estéticamente, pero que, por lo que he podido probar, no funciona bien del todo.

Con Speed Dial 2 podremos decidir cuáles son las páginas que queremos tener indexadas, y definir qué imagen queremos que se muestre para cada una de ellas. Además, tiene una gran variedad de opciones de configuración, incluyendo un analizador de nuestros hábitos de navegación que destaca las páginas que sueles visitar en el momento del día en que estés. Todavía no lo he probado, ya que tampoco lo veo muy práctico, aunque sí experimentalmente interesante.

En cuanto a la apariencia, se pueden configurar la imagen de fondo, el tamaño de las letras y sus colores, pudiendo así tener una página adecuada a las preferencias de cada uno.

Si usáis Chrome, os animo a probarlo.

¿Cómo obtener el valor de una campo de una secuencia Oracle trabajando con ADF BC?

Un título largo y descriptivo que plantea perfectamente el problema a tratar. Resulta que cuando queremos que el valor de una campo se obtenga directamente de una secuencia Oracle y estamos utilizando ADF Business Components, es fácil que cometamos un error.

Cuando configuramos los atributos de un Entity Object, podemos seleccionar varios tipos de dato, entre los que se encuentra DBSequence. Cuando elegimos esta opción, el diálogo de jDeveloper muestra un par de campos nuevos en los que nos pide que indiquemos un nombre de secuencia, y un valor de comienzo. Es lógico pensar que si ponemos en ese campo, por ejemplo, SEQ_PERSONA, el framework se encargará de coger el valor correspondiente de la secuencia, e inyectarlo en el campo que estamos editando. Nada más lejos de la realidad...

El utilizar el tipo DBSequence para un campo indica a ADF que el valor para el mismo va a ser proporcionado por la base de datos, pero ADF no se va a encargar de obtenerlo. Lo que va a hacer es asignar un valor temporal al campo, y esperar a que la base de datos le proporcione el real a la hora de persistir la información. El valor temporal será un número negativo.

Esto implica que nos toca a nosotros obtener el valor de la secuencia y utilizarlo para informar el campo. Una forma sencilla de hacerlo es crear un trigger en la base de datos que se ejecute antes de cada inserción en la tabla correspondiente. De forma general el código tendría el siguiente aspecto.

CREATE OR REPLACE TRIGGER %NOMBRE_TRIGGER%
BEFORE INSERT ON %TABLA% FOR EACH ROW
BEGIN
IF :NEW.%CAMPO% IS NULL OR :NEW.%CAMPO% < 0 THEN
SELECT %NOMBRE_SECUENCIA%.NEXTVAL
INTO :NEW.%CAMPO%
FROM DUAL;
END IF;
END;

Y, entonces, ¿para qué nos pide el IDE el nombre de la secuencia? Pues este dato sólo tendrá utilidad si estamos utilizando un enfoque en el que creemos en primer lugar nuestros objetos de negocio, y a partir de ellos queramos generar el esquema de datos. En este caso, jDeveloper creará, además de la tabla, la secuencia indicada en la base de datos.

jueves, 10 de marzo de 2011

Tutorial de Oracle ADF

Hoy me han publicado un nuevo tutorial en Javahispano. En este caso sobre el desarrollo de una aplicación Web con Oracle ADF, utilizando jDeveloper 11.

En el documento se hace una breve introducción teórica al framework de Oracle, comentando su arquitectura y, posteriormente, se detallan los pasos a seguir para crear una aplicación Web simple basada en ADF utilizando el entorno de desarrollo jDeveloper, en su versión 11. En el proceso se cubre desde la definición de la base de datos hasta el despliegue en el servidor WebLogic integrado en el IDE.

ADF es un framework basado en la arquitectura MVC, y ofrece un solución para cada una de las capas, aunque permite igualmente el uso de casi cualquier combinación de las tecnologías J2EE más extendidas. En el ejemplo del tutorial se ha optado por trabajar con JSF para la vista y el controlador (con la implementación ADFFaces, concretamente), y con EJB para la capa de servicios de negocio.

El tutorial se puede descargar en esta dirección.

Muchas gracias de nuevo a todo el equipo de Javahispano.

martes, 8 de marzo de 2011

Android - Gestión de aplicaciones

Después de un tiempo bicheando con Android, desarrollando y probando aplicaciones, te puedes encontrar que el emulador esté hasta arriba de iconos, y quieras eliminar algunos. Si no estás familiarizado con el funcionamiento de estos móviles, como me pasa a mí, puede que no atines a encontrar la forma de hacerlo, aunque es bastante simple.

Lo primero es pulsar el botón Menú, con lo que aparecerán una serie de opciones. Seleccionamos Manage Apps. Esto nos lleva a una pantalla en la que se muestran todas las aplicaciones del emulador (con los iconos de la sección superior se puede restringir la vista para mostrar las que se encuentran en la tarjeta SD, por ejemplo). Si buscamos en esa lista (ordenada alfabéticamente) la aplicación que queremos eliminar, y la seleccionamos, accederemos a una pantalla donde se mostrará información sobre ella, y en la que podemos ver un botón Uninstall.


Si pulsamos este botón y confirmamos, la aplicación desaparecerá de nuestro emulador.

Sin llegar al extremo de eliminarla, nos puede pasar que ejecutemos una aplicación y al salir de ella se quede ejecutándose. Me ha pasado, por ejemplo, con algunos juegos con sonidos; si sales con el botón de vuelta atrás, el juego sigue ejecutándose, y por tanto sonando.

Para parar la aplicación podemos volver a la pantalla de gestión de aplicaciones, y encontramos una opción en la botonera superior para mostrar las aplicaciones que se están ejecutando. Sin embargo, es muy posible que no encontremos la aplicación que queremos parar. Para verla tendremos que volver a pulsar el botón Menú desde esa pantalla, y seleccionar la opción Show Cached Processes. En la nueva lista sí que podremos ver todas las aplicaciones que se están ejecutando y, al seleccionarlas, tendremos un botón Stop, que detendrá su ejecución.