Integrando Vaadin com Spring em cinco minutos
Autor: Rafael | Publicado: 2010-02-21T00:36:00-03:00


Vaadin é um framework para criar aplicações web ricas (RIA) que usa os componentes do GWT e mapeia os eventos para o servidor, ou seja, abstrai o mapeamento dos serviços do GWT.








Uma aplicação em Vaadin

Basicamente uma aplicação web com Vaadin é bem simples:


import com.vaadin.ui.*;
public class HelloWorld extends com.vaadin.Application {
    public void init() { 
        Window main = new Window("Hello window"); 
        setMainWindow(main);
        main.addComponent(new Label("Hello World!")); 
    }
}&nbsp;

Baixe o vaadin-6.2.3.jar, coloque dentro do lib e configure o web.xml:


&lt;context-param&gt;
&nbsp;&nbsp; &nbsp;&lt;description&gt;Vaadin production mode&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&lt;param-name&gt;productionMode&lt;/param-name&gt;
&nbsp;&nbsp; &nbsp;&lt;param-value&gt;false&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;servlet&gt;
&nbsp;&nbsp; &nbsp;&lt;servlet-name&gt;Myproject Application&lt;/servlet-name&gt;
&nbsp;&nbsp; &nbsp;&lt;servlet-class&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;com.vaadin.terminal.gwt.server.ApplicationServlet
&nbsp;&nbsp; &nbsp;&lt;/servlet-class&gt;
&nbsp;&nbsp; &nbsp;&lt;init-param&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;description&gt;Vaadin application class to start&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;param-name&gt;application&lt;/param-name&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;param-value&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;HelloWorld
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;/param-value&gt;
&nbsp;&nbsp; &nbsp;&lt;/init-param&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&nbsp;&nbsp; &nbsp;&lt;servlet-name&gt;Myproject Application&lt;/servlet-name&gt;
&nbsp;&nbsp; &nbsp;&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;  


Sua aplicação funcionando:


&nbsp;





Integrando com o Spring


Estendi a classe AbstractApplicationServlet, que é uma servlet que indica qual a classe Application será usada.

package br.com.dev.naskar.integ.vaadin.spring;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;

/**
&nbsp;* Inicializa o Spring e configura a application do Vaadin.
&nbsp;* 
&nbsp;* @author rafael
&nbsp;*/
@SuppressWarnings("serial")
public class SpringVaadinApplicationServlet extends AbstractApplicationServlet {

&nbsp;&nbsp;&nbsp; /**
&nbsp;&nbsp;&nbsp; &nbsp;* nome do bean do spring que sera usado como application.
&nbsp;&nbsp;&nbsp; &nbsp;*/
&nbsp;&nbsp;&nbsp; private String nameSpringBeanApplication;
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; /**
&nbsp;&nbsp;&nbsp; &nbsp;* Class do application.
&nbsp;&nbsp;&nbsp; &nbsp;*/
&nbsp;&nbsp;&nbsp; private Class applicationClass;
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; /**
&nbsp;&nbsp;&nbsp; &nbsp;* Contexto do spring.
&nbsp;&nbsp;&nbsp; &nbsp;*/
&nbsp;&nbsp;&nbsp; private ApplicationContext springContext;

&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp; protected final Class getApplicationClass()
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throws ClassNotFoundException&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return applicationClass;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp; public final void init(final ServletConfig config) throws ServletException {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; super.init(config);
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nameSpringBeanApplication = 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; config.getInitParameter("nameSpringBeanApplication");
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String contextConfigLocation = 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; config.getInitParameter("contextConfigLocation");
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (contextConfigLocation == null || contextConfigLocation.equals("")) {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new RuntimeException(
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Parametro contextConfigLocation nao configurado: "
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; + contextConfigLocation
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; );
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; springContext = 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; new ClassPathXmlApplicationContext(contextConfigLocation);
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Application application = 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (Application) springContext.getBean(nameSpringBeanApplication);
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (application == null) {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new RuntimeException(
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Spring Bean nao encontrado: " + nameSpringBeanApplication
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; );
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; applicationClass = application.getClass();
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp; protected final Application getNewApplication(
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; final HttpServletRequest request
&nbsp;&nbsp;&nbsp; ) throws ServletException {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return (Application) springContext.getBean(nameSpringBeanApplication);
&nbsp;&nbsp;&nbsp; }

}

A cada HttpSession criada para um usuário, é chamado o método getNewApplication, ou seja, precisamos lembrar sempre de configurar o bean com escopo de prototype, para que a cada get do contexto do Spring, seja criado uma nova aplicação.

package br.com.dev.naskar.apres;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.vaadin.Application;
import com.vaadin.ui.Label;
import com.vaadin.ui.Window;

/**
&nbsp;* Blank application.
&nbsp;*/
@Component
@Scope("prototype")
@SuppressWarnings("serial")
public class BlankApplication extends Application {
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; /**
&nbsp;&nbsp;&nbsp; &nbsp;* Mostra a iniciacao da aplicacao.
&nbsp;&nbsp;&nbsp; &nbsp;*/
&nbsp;&nbsp;&nbsp; public BlankApplication() {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Iniciando application...");
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; /**
&nbsp;&nbsp;&nbsp; &nbsp;* Cria o layout da janela principal.
&nbsp;&nbsp;&nbsp; &nbsp;* 
&nbsp;&nbsp;&nbsp; &nbsp;* @return Janela principal.
&nbsp;&nbsp;&nbsp; &nbsp;*/
&nbsp;&nbsp;&nbsp; public final Window crieWindow() {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Window mainWindow = new Window("Blank Vaadin Spring");
&nbsp;&nbsp;&nbsp; &nbsp; Label label = new Label("Hello Vaadin Spring!");
&nbsp;&nbsp;&nbsp; &nbsp; mainWindow.addComponent(label);
&nbsp;&nbsp;&nbsp; &nbsp; return mainWindow;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp; public final void init() {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.setMainWindow(crieWindow());
&nbsp;&nbsp;&nbsp; }

}

Nessa classe podemos usar as injeções, aspectos, ferramentas de teste e tudo que o Spring tem sem problemas.

Veja que temos que trocar a definição da servlet, indicando qual o nome do bean do spring será usado e o onde está o applicationContext.xml do Spring.


  &lt;context-param&gt;
&nbsp;&nbsp; &nbsp;&lt;description&gt;Vaadin production mode&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&lt;param-name&gt;productionMode&lt;/param-name&gt;
&nbsp;&nbsp; &nbsp;&lt;param-value&gt;false&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;servlet&gt;
&nbsp;&nbsp; &nbsp;&lt;servlet-name&gt;main&lt;/servlet-name&gt;
&nbsp;&nbsp; &nbsp;&lt;servlet-class&gt;br.com.dev.naskar.integ.vaadin.spring.SpringVaadinApplicationServlet
&nbsp;&nbsp; &nbsp;&lt;/servlet-class&gt;
&nbsp;&nbsp; &nbsp;&lt;init-param&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;nome do bean do spring&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;nameSpringBeanApplication&lt;/param-name&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;blankApplication&lt;/param-value&gt;
&nbsp;&nbsp; &nbsp;&lt;/init-param&gt;
&nbsp;&nbsp; &nbsp;&lt;init-param&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;nome do bean do spring&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;META-INF/applicationContext*.xml&lt;/param-value&gt;
&nbsp;&nbsp; &nbsp;&lt;/init-param&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&nbsp;&nbsp; &nbsp;&lt;servlet-name&gt;main&lt;/servlet-name&gt;
&nbsp;&nbsp; &nbsp;&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
  


Pronto, temos a aplicação funcionando com todo o backend do Spring.




Conclusão

Estive procurando um framework para a camada de apresentação que&nbsp; não me
 desse tanto trabalho com detalhes da própria web. Utilizei o JBoss 
RichFaces, IceFaces (que é o que recomendo se você precisa mesmo usar 
JSF), mas vieram os problemas inerentes da própria API do ciclo de vida 
dos managed beans que o JBoss Seam resolveu muito bem com os seus 
escopos de conversação, mas que de vez em quando dá um nó na cabeça pra entender o fluxo de uma aplicação mais complexa.

Então, pesquisando no velho e bom google encontrei o Vaadin, que é tão simples quanto usar swing ou SWT. A princípio pensei que seria um framework mais orientado ao JavaScript como o Echo, SmartClient, etc. Adoro os protótipos e os ponteiros de função do JavaScript, mas a questão que você não trabalha sozinho num projeto e contratar ficar mais complicado.

Seguindo para a camada de negócio, Spring já um framework maduro e robusto, e que sinceramente, mesmo com o EJB 3.1 e a tendência de aplicações stateful (JBoss Seam), acho que a maioria das aplicações podem ser desenvolvidas com ele sem problemas (stateless). E com o lançamento do Spring Integration, as integrações entre sistemas não precisaram ficar exportando JAX-WS para tudo que é lado e tendo problemas de performance com XML até o ponto de lançarem hardware específico pra isso (WebSphere DataPower Integration Appliance). 

Enfim, Vaadin é simples para apresentação e Spring é Robusto.

Em algum futuro post quero vê se coloco o HiIbernate Validator como Validator do Vaadin.


Referências

O código está no Gitorious:&nbsp; http://gitorious.org/naskar/springvaadinblank/trees/master
Git: git://gitorious.org/naskar/springvaadinblank.git