Aprendiendo Vaadin #6: Usando SpringVaadinIntegration con soporte de navegación

Gestor de proyectosLlevaba tiempo buscando una forma de poder desarrollar una aplicación RIA sin tener que sufrir una dura curva de aprendizaje, aprovechando mis conocimientos de Java y obteniendo unos resultados suficientemente buenos. De primeras, GWT me pareció una buena opción, pero después descubrí Vaadin, que bajo mi punto de vista va un paso más allá y me convenció mucho más. En esta serie de entradas compartiré mis primeras experiencias con este framework.

En mi anterior post sobre Vaadin expliqué de una forma práctica cómo implementar soporte de navegación en una aplicación Vaadin. Para ello creé dos vistas, y para poder usar autowiring de spring en las vistas, las clases para las vistas debían ser internas a la clase UI que albergaba al navegador encargado de dar el soporte para navegación.
Usando el plugin SpringVaadinIntegration tendremos la posibilidad de usar autowiring en las clases vista de forma independiente a la clase UI. Para conseguir esto, voy a partir del mismo código del ejemplo anterior para ir modificándolo.

Como primer paso copiamos el proyecto del post anterior a un nuevo proyecto al que llamaré ApVaadinSpringVaadinIntegration. Para añadir la dependencia en maven de SpringVaadinIntegration necesitaremos definir en nuestro pom.xml el repositorio de Vaadin add-ons (si no lo tenemos ya definido, como en mi caso) y ya podremos definir la dependencia. Para añadir el repositorio al pom (si es que no lo tenemos ya agregado):

<repositories>
    <repository>
        <id>vaadin-addons</id>
        <url>http://maven.vaadin.com/vaadin-addons</url>
    </repository>
</repositories>

Y para añadir la dependencia del plugin:

<dependencies>
    <dependency>
        <groupId>ru.xpoft.vaadin</groupId>
        <artifactId>spring-vaadin-integration</artifactId>
        <version>1.7.3</version>
    </dependency>
</dependencies>

Antes de terminar con el pom nos aseguraremos de que aún contamos con la dependencia heredada al copiar el proyecto spring-web, pues la necesitaremos.

Ahora haremos los cambios necesarios al archivo web.xml. Es necesario redefinir el servlet de entrada de Vaadin y sustituirlo por el servlet aportado por el plugin SpringVaadinIntegration. Ahora podremos eliminar todas las referencias a la clase UIProvider que en nuestro ejemplo habíamos denominado MyUIProvider. La referencia al servlet en nuestro web.xml debe quedar así:

<servlet>
    <servlet-name>Test Application</servlet-name>
    <servlet-class>ru.xpoft.vaadin.SpringVaadinServlet</servlet-class>
    <init-param>
        <param-name>beanName</param-name>
        <param-value>MyVaadinUI</param-value>
    </init-param>
</servlet>

Y ahora podemos eliminar la clase MyUIProvider y también la clase Inject, ambas heredadas del ejemplo anterior al copiar el proyecto. A continuación modificaremos nuestra clase MyVaadinUI para hacerla funcionar con el plugin. La etiquetamos como @Component y @Scope(«prototype»). Los diferentes valores que podemos usar para la etiqueta @Scope son:

  • @Scope(«prototype»): crea una nueva instancia por cada nueva página.
  • @Scope(«session»): guarda la instancia UI en la sesión de usuario para ser reusada.
  • Opción por defecto: si no definimos el @Scope se usará en modo Singleton. Esto es, en todas las llamadas y en todos los casos se usará la misma instancia UI.

Ahora es posible extraer de nuestra clase UI las clases vista internas. Nos las llevamos fuera, al mismo paquete donde tenemos declarada la clase MyVaadinUI.

Al extraer las clases vista hay que etiquetarlas con las etiquetas ya conocidas @Component, @Scope, y con la etiqueta @VaadinView. Además, lo que normalmente hacíamos en el constructor ahora lo haremos en un método PostConstruct debidamente etiquetado. Así nuestras vistas serán instanciadas automáticamente, gracias al plugin.

Un problema con el que nos encontramos tras hacer todo esto es que nuestras vistas ya no conocen el servicio helloService. Ahora sí podremos inyectarlo mediante autowiring gracias al plugin SpringVaadinIntegration. De hecho, este servicio ya no nos sirve de nada en nuestra clase UI, así que lo mejor será borrarlo de ella.

El siguiente problema con el que nos encontramos es que nuestras vistas, que antes conocían a la instancia de nuestro Navigator, ahora han dejado de conocerla. La buena noticia es que ya no la vamos a necesitar en nuestras vistas para navegar de una vista a otra, usaremos Links (enlaces) para navegar. Eso sí, para seguir contando con soporte de navegación necesitaremos definir un nuevo Navigator haciendo uso de la clase DiscoveryNavigator que es proporcionada por el plugin y sustituyendo al antiguo Navigator en nuestra clase MyVaadinUI.
Por último, eliminamos de nuestras vistas todas las referencias al antiguo botón que ya no usaremos.

Después de todo esto, nuestra clase MyVaadinUI tendrá este aspecto, muy limpio:

@Component("MyVaadinUI")
@Scope("prototype")
public class MyVaadinUI extends UI {
	
	DiscoveryNavigator navigator;
	protected static final String STARTVIEW = "";
	protected static final String MAINVIEW = "main";  

	@Override
	protected void init(VaadinRequest request) {    	
        	getPage().setTitle("Ejemplo de navegación");        
       		navigator = new DiscoveryNavigator(this, this);        
    	}    
}

Del mismo modo, las vistas también han quedado bastante reducidas y limpias. El código para la vista StartView quedaría así:

@Component
@Scope("prototype")
@VaadinView(MyVaadinUI.STARTVIEW)
public class StartView extends VerticalLayout implements View {
	
	@Autowired
	HelloService helloService;
	
	@PostConstruct
	public void PostConstruct() {
		setSizeFull();
        	addComponent(new Link("Ir a la vista principal (MainView)", new ExternalResource("#!" + MyVaadinUI.MAINVIEW)));
	}
	
	@Override
	public void enter(ViewChangeEvent event) {
		Notification.show(helloService.sayHello(this));
	}
}

y el código para la vista MainView quedaría muy similar:

@Component
@Scope("prototype")
@VaadinView(MyVaadinUI.MAINVIEW)
public class MainView extends VerticalLayout implements View {

	@Autowired
	HelloService helloService;
	
	@PostConstruct
	public void PostConstruct() {
		setSizeFull();
		addComponent(new Link("Ir a la vista inicial (StartView)", new ExternalResource("#!" + MyVaadinUI.STARTVIEW)));
	}
	
	@Override
	public void enter(ViewChangeEvent event) {
		Notification.show(helloService.sayHello(this));
	}
}

Tras todo esto, tenemos una aplicación muy similar a la que teníamos, pero con menos clases y menos líneas de código, mucho más limpia y sencilla. Ahora podemos usar autowiring en las vistas, y podemos definir las vistas externamente a la clase UI.

Puedes descargar el código fuente de este ejemplo aquí.

8 pensamientos en “Aprendiendo Vaadin #6: Usando SpringVaadinIntegration con soporte de navegación

  1. Muy interesantes posts. Añadido al RSS 😉

    Estoy interesándome por Vaadin, aunque el no gustarme Java tiene mucho que ver que lo haga lentamente.

    Tienes pensamiento de hacer algún post con persistencia? Como comento aquí(*) lo veo jodidamente complicado..algo tan sencillo….
    Qué ventajas finales realmente tiene el incrustar Spring sobre la app Vaadin? Es obligatorio? opcional?

    Gracias.

    (*) https://vaadin.com/forum#!/thread/3978678

  2. Giu, gracias por el comentario 🙂
    Hasta ahora lo que he intentado hacer con Vaadin es mostrar cómo trabajar con herramientas como Maven y Spring (entre otras), ya que me pareció que esto no estaba bien explicado en el libro oficial de Vaadin.
    En principio no tenía pensado hacer nada de persistencia con Vaadin pues la persistencia es un aspecto más relacionado con el back-end, mientras Vaadin lo enfoco más de cara al front-end. Existen controles en Vaadin que te cubren todo, desde la presentación visual hasta la persistencia, pero no soy partidario de mezclar esos conceptos. De todas formas me apunto la sugerencia de cara a hacer un post de Vaadin con Hibernate y JPA.
    Usar Spring con Vaadin por supuesto que es opcional, pero al mismo tiempo te digo que es muy recomendable. El uso de Spring te aporta muchas ventajas. Puedes empezar leyendo sobre Spring en la wikipedia (http://es.wikipedia.org/wiki/Spring_Framework) para ir cogiendo las primeras ideas.
    Saludos.

  3. Hola David,

    Me parecen muy buenos tus posts sobre vaadin, ya que lo explicas de manera clara y sencilla. Una pregunta no has pensado hacer un post sobre como integrar vaadin con spring securty o apache shiro?. O conoces tú otra manera de hacer la autentificación en las aplicaciones vaadin. Soy nuevo en vaadin y estoy buscando un ejemplo claro de como hacer la autentificación y el manejo de roles dentro de una aplicación vaadin.

    Gracias.
    Slds.

  4. Muy interesantes posts sobre vaadin, ya que se explican de forma clara y sencilla. Una pregunta nos has pensado hacer un post de la integración de vaadin con spring security o apache shiro?… o conoces algún otro método de autentificación y manejo de roles dentro de las aplicaciones vaadin, soy nuevo en vaadin he probado con varios ejemplos para la integración de spring security y apache shiro pero ningun a funcionado completamente bien, ojalá tu puedas hacer un post sobre estos temas o recomendarme algo para solucionar mi inconveniente.

    Gracias.

  5. Buenas tardes David me han sido de mucha utilidad estos post pero veo que este fue el ultimo? no se si allan mas o si ya no pensas realizar mas post sobre vaadin. De antemano gracias por el aporte y felicitaciones

  6. Muchas Gracias por todo este valioso contenido, 6 pots sobre vaadin muy básico muy elementales y muy técnicos, mucha pedagogía Garcias desde Venezuela

Deja un comentario