Trabalhe com Java EE e Spring juntos

Existem várias discussões recentes sobre se devemos utilizar o Spring ou o JavaEE em nossos novos projetos, já que muitas das facilidades fornecidas pelo Spring estão agora disponíveis por padrão a partir do JavaEE 6, talvez indo além. A maioria desses posts realiza comparacões entre o Spring e o JavaEE, mostrando pontos fracos e fortes de cada plataforma e determinando um vencedor na disputa. O que esses autores esquecem é que não é necessário escolher entre um ou outro, sendo plenamente possível utilizar tanto bibliotecas do JavaEE e do Spring em conjunto, conseguindo o melhor dos dois mundos, se houver a necessidade.

Logo Spring

Neste post usaremos como exemplo uma aplicação JSF 2.0 rodando em um servlet container simples (como o Tomcat ou o Jetty, por exemplo), usando o Spring para fornecer injeção de dependências e controlar o ciclo de vida dos ManagedBeans do JSF.

O primeiro passo para realizar a integração é registrar o listener do Spring e informar o local do arquivo de configurações no web.xml. Com isso, todos os serviços do Spring já estarão disponíveis no startup da aplicação.

<!-- Listener do Spring -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
<!-- Local do arquivo de configuração -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/applicationContext.xml</param-value>
  </context-param>

Como iremos delegar para o Spring o controle sobre o ciclo de vida de nossos ManagedBeans, também temos que registrar o listener que nos permitirá utilizar os escopos padrões de uma aplicação web, como request ou session:

  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

Agora, é só indicar ao JSF para delegar a criação dos ManagedBeans para o Spring, registrando um el-resolver no faces-config.xml:

<faces-config>
	<application>
		<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
	<application>
	...
</faces-config>

A partir desse ponto, podemos usar as anotações do Spring para criar os ManagedBeans. Um bean simples com JSF seria escrito normalmente da seguinte maneira:

@ManagedBean
@RequestScoped
public class ProdutoBean{
    private List produtos;
    public List getProdutos(){
        if(produtos == null){
            ProdutoDAO dao = new ProdutoDAO();
            produtos = dao.listaTodos();
        }
        return produtos;
    }
}

Escrever esse mesmo exemplo usando o spring é muito simples, basta trocar as anotações do JSF pelas (quase) equivalentes do Spring:

@Controller // Equivalente à @ManagedBean
@Scope("request") // Equivalente à @RequestScoped
public class ProdutoBean{

    private List produtos;

    public List getProdutos(){
        if(produtos == null){
            ProdutoDAO dao = new ProdutoDAO();
            produtos = dao.listaTodos();
        }
        return produtos;
    }
}

Para acessar a lista de produtos de uma página, é só referenciar o bean usado a Expression Language:

    <h:dataTable value="#{produtoBean.produtos}" var="produto">

A grande vantagem é que agora podemos receber injeções de dependências diretamente em nossos beans. Vamos injetar o ProdutoDAO. Precisamos indicar para o Spring que o ProdutoDAO é um objeto injetável, faremos isso com a anotação @Repository:

@Repository
public class ProdutoDAO{
...
}

E agora, é só fazer a injeção da dependência no ProdutoBean:

@Controller
@Scope("request")
public class ProdutoBean{
    @Autowired // Anotação do Spring para injeção
    private ProdutoDAO dao;

    private List produtos;

    public List getProdutos(){
        if(produtos == null){
            produtos = dao.listaTodos();
        }
        return produtos;
    }
}

O Spring não é a única solucão para injeção de dependências fora de um servidor de aplicação. Poderiamos utilizar o Weld para nos fornecer injeção padrão JavaEE por meio do CDI, permitindo inclusive customizar a criação dos objetos. O uso do Spring, entretanto, torna mais fácil integrar nosso projeto com outras funcionalidades do framework, como Security, AOP, Transaction, etc., pois o ecossistemas Spring é enorme, bastando apenas configurar e habilitar os serviços no applicationContext.xml.

Sempre podemos considerar a integração com o Spring em nossos sistemas, seja para utilizar algum dos seus serviços que não tem especificação equivalente no JavaEE, seja para substituir alguma especificação cuja implementação do Spring forneça mais funcionalidades, ou simplesmente porque a implementação do Spring é a que a equipe mais domina.

E você, já integrou o Spring e o JavaEE em algum projeto?

17 Comentários

  1. José Volmei Dal Prá Junior 31/05/2012 at 10:24 #

    Ótimo post! Usar o melhor dos 2 mundos é a solução correta! Uso tanto CDI e Spring. Cada projeto pede uma abordagem. Parabéns!

  2. Vitor 31/05/2012 at 10:32 #

    Sem contar que, para quem precisa ViewScope no JSF usando Spring, pode tranquilamente implementá-lo. Já fiz isso e funciona 100%.
    Segue link com o exemplo: http://www.esseconhece.com.br/programacao/java/disponibilizando-viewscope-para-spring/

  3. Renato 31/05/2012 at 14:21 #

    Grande Mario
    Grande post
    Grande tema
    Parabéns pela iniciativa

  4. Allan 31/05/2012 at 23:42 #

    Olha, para ser sincero, só pelo exemplo citado, não vi grande vantagem em adicionar o Spring ao projeto. (pelo que foi apresentado).

    Na primeira parte, do @ManagedBean, fica igual, só trocam as anotações.

    Na segunda, “se for só pelo cdi”, eu optaria pelo Weld, assim fica transparente quando se a aplicação for para um servidor de aplicação ou, mesmo se não for, você escapa desses montes de xml de configuração do Spring.

    Sei das vantagens do Spring. Mas se for “só pra isso”, não usaria não.

    Abs!!!!

  5. Frederico Maia 05/06/2012 at 09:48 #

    Neste exemplo realmente não houve vantagem alguma. Pelo contrário o CDI resolve tudo isso muito bem e mais simples ainda se já estiver em um container EE.

    Vitor – No JEE já temos o escopo de ViewScope além de podermos criar escopos customizados.

    Caso haja alguma integração com os serviços do Spring como Security por exemplo, aí sim, concordo que seria vantajoso.

  6. Paulo Silveira 05/06/2012 at 13:53 #

    oi Frederico

    É mais esse o caso mesmo: onde voce já tenha um sistema dependente de Spring, em especial dos seus milhares de templates/beans/extensões.

  7. Gilmar M. dos Santos 06/06/2012 at 10:51 #

    Muito bom o post, nunca desenvolvi uma aplicação que o spring gerenciasse o ciclo de vida do jsf, eu sempre criava uma classe de serviço onde o Menaged Bean se comunicava. Agora vou fazer desse jeito.

    Parabéns pelo post!!!!!

  8. Luiz 06/06/2012 at 20:40 #

    Show de bola!! Excelente Post. É sempre bom saber que temos opções e que essas opções podem se integrar!!

    Abraço

  9. Elizeu Santos 07/06/2012 at 05:44 #

    Muito bom.
    QUANDO posso optar, costumo utilizar o Spring para IoC e JSF2 para as camadas. Procuro aproveitar o melhor de cada tecnologia.

  10. Rafael Roque 11/06/2012 at 09:23 #

    Apenas como dica:
    Caso a localização do arquivo seja WEB-INF/applicationContext.xml o context-param não precisa ser informado,o Spring já entende esse caminho como padrão.

    Muito bom texto!

  11. João Henrique 28/06/2012 at 11:19 #

    Excelente post , simples e claro.(Muito show).

    É muito bom ver artigos práticos e objetivos como esse.

  12. felipe 05/09/2012 at 16:13 #

    Vou fugir do assunto, tenho uma aplicação com spring e meu serv de homologação não tem acesso para fora (web) agora quando eu coloco a aplicação na homologação ela não funciona.
    como eu faço as declarações apontando para endereços locais.
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd

    Desculpa se fuji muito, muito, muito, do assunto em questão

  13. Fabio Pedrosa 25/07/2013 at 10:23 #

    Eu já usei essa combinação em diversos projetos JSF + Spring para todo o back-end e integrações EJB, particularmente não gosto de JSF, não gosto de ficar amarrado a um tipo de view, nisso o Spring MVC é matador, não gosta de JSP coloque um Freemaker, Velocity e seja feliz, tente fazer formulários mais avançados com JSF para ver o grau de dificuldade sem contar a lentidão.

  14. Assis 24/09/2013 at 10:40 #

    Excelente!!
    parabéns!!

  15. João 30/04/2014 at 13:56 #

    E o contrario? Se eu quiser utilizar Spring MVC injetando Beans CDI no controller?

  16. Caio Luiz 13/02/2019 at 11:21 #

    No seu caso, o exemplo foi concedido para uma aplicação que utiliza jsf e portanto teve que configurar o arquivo faces-config para delegar a construção dos beans para o spring.
    Se fizessemos um webservice utilizando jax-rs, como faríamos para delegar a criação dos beans para o spring? Teria alguma configuração adicional?

    Obrigado.

Deixe uma resposta