Java

Resulta curioso lo de la memoria en java, nunca había tenido problema con ella, y sigo sin tenerlos. Lo único que he tenido ha sido un problema que parecia que era de memoria con una aplicación para un cliente. Al final ha resultado ser una tontería que no ha implicado ningún problema.
Pero la situación me ha hecho investigar un poco sobre el asunto de la memoria y como optimizar Tomcat para producción. Hasta ahora si tenia un problema de memoria, solo la incrementaba y se solucionaba el problema. No se si por que mis requerimientos siempre han sido de andar por casa (nunca he tenido una aplicación con tantos usuarios como Facebook, ya quisiera), o por que siempre he desarrollado las aplicaciones siguiendo una arquitectura estandar y aplicando patrones y tecnologías actualizadas. Pero nunca he tenido problemas.
He descubierto un par de paginas interesantes para aprender las bases de la gestión de la memoria en java. Una es de David Bonilla, una persona a la que sigo desde hace tiempo, artículo.
Esta otra página trata de que hacer cuando tienes un problema y como tratar de solucionarlo. Yo lo he hecho y resulta un poco complicado, supongo que sera práctica.

Y por último una página con pasos claros de como mejorar el rendimiento de nuestro Tomcat. Algunas muy elementales, como gestionar los log con alguna librería y nunca con System.out. Y otras que desconocía completamente como la opción -server.
Un post corto pero cargado de información. Cualquier sugerencia siempre sera bien recibida.
![]()
Llevo tiempo queriendo hacer una integración un poco mas limpia entre spring y gwt, y de paso empezar a usar maven de forma completa. Navegando por internet no he encontrado mucha información sobre esta complicada unión. Incluso en Google hay una pequeña pagina donde explica a grandes rasgos una posible integración. Pero no ha sido hasta hace poco que no he dado con alguien que explicara de forma clara como hacerlo.
La dirección de los tutoriales es esta http://krams915.blogspot.com/search/label/GWT, una web que interesante . Si estáis interesados, seguir los tutoriales.
Yo solo añadiré algunas aclaraciones, porque aunque esta bastante claro hay cosas que no me han funcionado.
M2eclipse
Este plugin me ha dado muchos problemas, hasta que me he dado cuenta de que era el y lo he erradicado por completo. Vamos a ver, no es que sea malo o no funcione, es que en mi caso particular me ha hecho muchos extraños. Para empezar, en un proyecto maven las librerías no están en el proyecto, si no que están en el repositorio local, con lo que el eclipse en algunas ocasiones se puede hacer un lío. Solucionable copiando dichos archivos a la carpeta de la web. Aunque claro, ya empezamos con piados a mano de librerías. Y no importa que las tengas en el classpath, algunas no las coge, no me preguntéis por que.
Y lo mas raro de todo, los controller de spring-mvc no los cargaba, aunque si me cargaba los beans de spring security. Curiosamente las dos clases controlador que hace mención en el tutorial de arriba, no las cargaba, y claro, no encontraba las paginas. Después de muchas comprobaciones, y de ver que utilizando el maven a pelo para ponerlo en marcha si que funcionaba, llegue a esta conclusión.
Y el autor ha debido tener los mismos problemas porque utiliza la declaración de los beans de gwt por el xml, y comenta que hay algún tipo de conflicto con las anotaciones y gwt. Pero puedo confirmar que los servicios de gwt se pueden configurar por anotaciones sin ningún problema.
Así que para evitar problemas, recomiendo utilizar maven como siempre, pero a la hora de ponerlo en eclipse, utilizar mvn eclipse:eclipse, que eso no falla y podréis manejar el proyecto sin problemas, depurar y ejecutar con el plugin de google.
Plugin de google
En este caso solo una aclaración, que ademas la tenéis en la página del mojo, la web donde esta el archetype de gwt, y es que tenéis que mover el archivo de configuración de gwt, modulo.gwt.xml, desde la carpeta de fuentes resources, /src/main/resources, a la carpeta de fuentes java, /src/main/java. Para que el plugin lo reconozca y no tenga problema en ejecutarlo.
gwt-widget
Esta librería te la una implementación sencilla de la solución que propuso google. No tiene ningún problema y funciona muy bien. El inconveniente, que lleva tiempo parada y no se si continuara, aunque por el momento a mi me sirve.
También hay que tener en cuenta que no esta en repositorios maven, con lo que hay que bajárselo e instalarlo en el repositorio local para que funcione bien con maven. Un ejemplo:
mvn install:install-file -DgroupId=org.gwtwidget -DartifactId=gwtwidget -Dversion=1.0 -Dpackaging=jar -Dfile=/path/to/file
Luego la incluis en vuestro pom tal que así:
<dependency> <groupId>gwt.widget</groupId> <artifactId>gwtwidget</artifactId> <version>1.0</version> </dependency>
Poco mas puede aportar, me ha llevado algún tiempo sacar estas conclusiones pero en el fondo es sencillo.
Queda pendiente un post de como utilizar spring security para aplicar seguridad a una aplicación gwt. Ahora que tengo esto montado y funcionando no me llevara mucho tiempo.
![]()
Hacia tiempo que no escribía un post técnico y ya ha llegado el momento. Recientemente, desarrollando una aplicación a medida para un cliente, me he visto en la necesidad de conectar una aplicación de escritorio con una aplicación web. En los años que llevo programando no he tenido necesidad de realizar esta operativa, muchas veces ha sido conectar una aplicación web con otras aplicaciones, tanto web, servidores de diferentes tipos como de escritorio, pero han sido siempre desde la perspectiva de la lógica de negocio en el servidor, consumiendo servicios web, accediendo a base de datos o incluso leyendo archivos. Esto es distinto, tengo que ofrecer acceso a mi aplicación web para aplicaciones de escritorio. Nada complicado si se utilizan webservices. Pero he aprovechado la coyuntura para probar unas nuevas herramientas, spring roo, que genera de forma espectacular una aplicación web y al que ya dedicare un post con mas tranquilidad. Por el momento decir que genera aplicaciones con JPA en Hiberanate (mas bien en cualquier cosa) y spring para el negocio. Ademas de hacer un scaffold de las web con GWT. Para la seguridad puedes incluir spring security, que es lo que yo he introducido. Hasta aquí todo bien, funciona perfectamente y sin ningún problema, puedes controlar el acceso por métodos de negocio con simples tag, muy fácil. Ahora viene la parte en que conectamos la aplicación de escritorio, en mi caso con una aplicación swing (por cierto con netbeans y matisse, muy sencillo también). Spring te ofrece un montón de opciones de interconexión, RMI directamente y de forma sencilla, HTTP-Invoke o webservices, entre muchos. He probado RMI y muy contento, pero al final me he decantado por HTTP-invoke por varios motivos:
-
RMI necesita configurarse ademas un puerto concreto, complicando la instalación en según que sitios. Si el servidor y la red son tuyos no hay muchos problemas, pero si utilizas algo como la PAAS de google puedes tener algunos problemas. En cambio HTTP-Invoke usa el mismo puerto 80.
-
Rendimiento: Tanto RMI como HTTP-Invoke tienen muy buenos rendimientos, ambos usan serialización de objetos.
-
Configuración, al ir por el puerto 80 no requiere configuración extra de seguridad.
El problema lo tuve en la seguridad, como configurar la seguridad y realizar un login remoto, que es lo que voy a explicar aquí.
Servidor
Para configurar el lado del servidor hay que realizar los siguientes pasos:
- Crear una capa de servicios: para ello creamos unas clases en nuestro código que ofrecerá los servicios que nos interesen.
public interface ServicioSaludo {
@Secured(“ROLE_ADMIN”)
public String getSaludo();
}
@Service(“saludador”)
public class ServicioSaludoImpl implements ServicioSaludo {
@Override
public String getSaludo() {
return “Hola”;
}
}
Es en la interfaz donde declaramos la seguridad con los tags @Secured. Luego pondré la configuración básica de seguridad.
El tag @Service le indica a spring que es un bean y que debe nombrarlo como saludador, de esta manera no hará falta ponerlo expresamente en el xml de configuración. Claro que para que funcione debéis configurar vuestro spring con el siguiente código.
<context:component-scan base-package=”paquete”>
Si no, simplemente lo declaráis expresamente como un bean
<bean name=”saludador” class=”paquete.ServicioSaludoImpl”/>
Ya tenemos el servicio declarado, ahora lo exponemos con HTTP-Invoker.
<bean name=”/saludadorHTTP” class=”org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter”>
<property name=”service” ref=”saludador”/>
<property name=”serviceInterface” value=”paquete.ServicioSaludo”/>
</bean>
/saludadorHTTP indica donde estará accesible, después ponemos con que lo exponemos, e indicamos las clases que queremos exponer.
Aquí tenéis el archivo de configuración de seguridad.
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans:beans xmlns=”http://www.springframework.org/schema/security”xmlns:beans=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd”>
<http auto-config=”true” use-expressions=”true”>
<intercept-url pattern=”/login.*” access=”permitAll”/>
<intercept-url pattern=”/**” access=”isAuthenticated()” />
<form-login/>
<anonymous />
<http-basic />
</http>
<global-method-security secured-annotations=”enabled”/>
<!– Configure Authentication mechanism –>
<authentication-manager alias=”authenticationManager”>
<authentication-provider>
<user-service>
<user name=”admin” password=”admin” authorities=”ROLE_ADMIN”/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
use-expressions sirve para utilizar las nuevas forma de definir las seguridad, bastante mas completas.
Global-method-security sirve para poder utilizar las anotaciones de seguridad en las interfaces que hemos usado antes.
En cuanto a lo demás, es básico en seguridad de spring, así que no haré mas comentarios.
Ahora cargamos otro dispacher de spring en el web.xml, se pueden tener todos los que se quieran, y es recomendable separarlo, si tenéis uno para el MVC de spring, podéis dejarlo intacto y añadir este otro solo para las conexiones remotas.
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/remoting-servlet.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
Varias cosas, para los que no lo sepan, el contextConfigLocation no es necesario, siempre y cuando llaméis al archivo con la nomenclatura servletName-servlet.xml y ubicado en WEB-INF/classes. Si lo queréis en otro sitio y con otro nombre pues se pone.
Aquí nos quedamos con la URI /remoting, que se usara en el cliente. Con esto ya tendremos configurado el servidor.
Cliente
Le toca al cliente, en este caso utilizare una simple aplicación de consola. Necesitaremos varias cosas:
- Las interfaces del servidor: podemos empaquetar solo las interfaces del servidor y añadirlas nuestro proyecto cliente.
- Las librerias de spring: tanto el core como security.
Ahora configuramos nuestra aplicación creando un archivo de configuración cliente para spring, por ejemplo cliente.xml, e introducimos lo siguiente:
<bean id=”servicio”>
<property name=”serviceUrl” value=”http://localhost/remoting/saludadorHTTP”/>
<property name=”serviceInterface” value=”paquete.ServicioSaludo”/>
<property name=”httpInvokerRequestExecutor”>
<ref bean=”httpInvokerRequestExecutor”/>
</property>
</bean>
<bean id=”httpInvokerRequestExecutor” class=”org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor”/>
La dirección del servicio donde lo tengáis, en mi caso en localhost, seguido de remoting que es donde mapeamos el servlet para servicios remotos y por último la dirección del servicio concreto que configuramos en el archivo xml de spring del servidor. Ademas cargamos el bean para que lo use de autenticado.
Y nos vamos al main de la clase cliente.
//Creamos una autenticación con el usuario y contraseña
Authentication request = new UsernamePasswordAuthenticationToken(“admin”, “admin”);
//Este es el contexto que extiende del servidor, es aqui donde nos logeamos
SecurityContextHolder.getContext().setAuthentication(request);
//Cargamos el archivo de configuración
ClassPathXmlApplicationContext contexto = new ClassPathXmlApplicationContext(“cliente.xml”);
ServicioSaludador servicio = (ServicioSaludador) contexto.getBean(“servicio”);
String cadena = servicio.getSaludo();
Y ya esta, facilísimo.
Bueno, quien dice un main dice una aplicación swing, es la mar de sencillo, yo por el momento uso netbeans que funciona muy bien.
El sistema de layouts de GWT cambio en la versión 2.0. Desde entonces se usan las interfaces RequiereResize y ProvidesResize. El mecanismo se usa en cascada y debemos tener en cuanta varias cosas:
- Partir desde el RootLayoutPanel, que ya implementa RequiereResize y ProvidesResize.
- Modo estándar: hay que poner en el html la siguiente instrucción <!DOCTYPE html>
- No romper la cadena, si tenemos una estructura un poco compleja y el cambio de tamaño afecta a toda la cadena, todas las clases intervinientes deben implementarlo, si nos dejamos una ya no funcionara.
Tenemos dos tipos de clases o paneles, los que son layout e implementan la interfaz RequiereResize y los que no.
Entre los que los tienes son las clases nuevas como RootLayoutPanel, y todos los paneles que contengan la palabra layout. Aunque el problema viene con los paneles que utilizan las tablas como estructura interna. Algunos elementos de html como los divs, dependiendo de los navegadores, interpretan el 100% de forma diferente, por ejemplo, si pones un div en una celda que mide 100px de ancho y tiene un borde de 1px y padding de 5px, el div cogerá y pondrá que mide 112px de ancho más su propio bode, padding y magen, con lo que se sale el div de la celda. Y resulta difícil arreglarlo salvo implementando el onResize y teniendo en cuenta todos estos margenes. Aunque poco se puede hacer por el momento para sustituir el HorizontalPanel y el VerticalPanel.
Si se quiere implementar esta interfaz solo hay que implementar onRiseze() modificando los tamaños que queramos
En el caso de los Composites podemos hacerlo de dos maneras
- ResizeComposite: Si extendemos de esta clase, ya viene implementada onResize() y lo único que hace es comprobar que el objeto que tiene como hijo sea RequiereResize y llama a su onResize(), pero el hijo debe ser un objeto RequiereResize, si no dará una excepción nada mas ponerlo en marcha.
- Implementar RequiereResize: esta es lo mismo que lo anterior pero seremos nosotros quienes implementemos el método onResize() y no tendremos la restricción de que el hijo sea RequiereResize, pudiendo poner cualquier widget.
Después tenemos la interfaz ProvidesResize que solo indica que la clase que la implementa propaga sobre sus hijos el onResize(), es decir, que si alguna de vuestras clases o componentes en su método onResize() lo propaga por todos sus hijos, entonces debería implementar esta interfaz. Aunque a efectos prácticos funciona igual, es más aclaratoria en la documentación.
Esto es lo que he aprendido de su uso en este último año, que ha sido muy intenso, pero como siempre acepto y agradezco cualquier corrección o aportación.
NOTA: En ocasiones el calculo del tamaño de un widget lleva su tiempo, y pueden haber discrepancias con respecto a lo pintado. La solución que he encontrado por internet es la de poner un Timer en el onResize de pocos milisegundos para darle tiempo al recalculo.
new Timer() {
@Override
public void run() {
int width = ResizeContainer.this.getOffsetWidth();
}
}.schedule(100);
Aunque no resulte muy elegante.

Aunque ya hace semanas que esta disponible las versión más reciente de GWT, no he podido mirar las nuevas características. Que os voy a contar que no sepáis ya del tan deseado tiempo libre. Pero estaba con una nueva funcionalidad que requería una tabla rápida y sencilla, así que me he puesto a mirar las tabla o Cell variadas que traen las últimas versiones de GWT.
Simplemente impresionante, sencillo y algo que se demandaba desde hace tiempo. Yo he estado utilizando las tablas paginadas de incubator, a las cuales les tengo mucho aprecio ya que me han quitado mucho trabajo, pero tengo que admitir que estas tablas son extremadamente sencillas y organizadas, y se adaptan muy bien al MVP de GWT.
El funcionamiento es muy sencillo, voy a esquematizarlo porque la documentación de google es mas que completa.
- Te declaras la tabla, en mi caso he cogido CellTable, tienes mas opciones como CellTree y CellBrowser (aunque no he tenido oportunidad de probar), y le indicamos el objeto que va a contener mediante genéricos.
- Nos declaramos las columnas que llevara, indicando en cada una el dato de ese objeto que vamos a mostrar.
- Colocamos la tabla donde queramos.
- Nos declaramos un proveedor que nos dará una interfaz para trabajar con esta tabla.
- Y simplemente añadir nuestros objetos al proveedor, trabajando con listas. Aunque no es necesario, también se puede añadir un listado a la tabla directamente.
- Si queremos alguna columna ordenada, solo hay que implementar un ListHandler y asociarlo a la columna.
Y el punto fuerte de la nueva tabla, la selección de una fila, con declararte un sistema de selección, asignarlo a la tabla y luego implementar un handler de esa selección para hacer lo que queramos cuando hacen click en ella. Esto difiere un poco con la de incubator, que tenias que hacer algunas pirulas mas solapando modelo vista y presenter. De esta manera puedo implementar la acción en el presenter de forma transparente a a la vista. Una maravilla.
Y a poco que investigas un poco, ves como se puede poner de todo con facilidad en las columnas, y que hagan lo que quieras y como quieras. Así que mi primera impresión ha sido impresionante. Esperemos que siga así.
Si alguno lo ha probado o tiene algún problema podéis comentarlo, seguro que entre todos lo solucionamos o aprendemos a utilizarlo.
