Técnico

Spring 3.1 RC1 – Profiles

Profiles e Environments no novo Spring 3.1

A SrpingSource adotou a estratégia de soltar mais versões do Spring com mais velocidade e escopos de funcionalidades menores.
Seguindo tal estratégia acabou de sair do forno o primeiro release candidate da versão 3.1 do framework.
Para uma estratégia de escopos menores, até que tiveram bastante trabalho e adicionaram várias novidades. Vamos cobrir as novidades aos poucos, começando com uma muito interessante: Profiles e Environments.

Especificando Profiles nos Beans

A idéia de um profile é simples. Um profile define um escopo, envirnmente como é chamado no framework, em que certos beans estarão disponíveis e outros não.
Imagine que você precisa de uma conexão com o banco de dados de testes, que é diferente do banco de dados de desenvolvimento. Com profiles podemos definir um data source do profile de desenvolvimento, e outro do profile de testes, instanciando o correto de acordo com o ambiente que a aplicação irá rodar.

Anotações

Para especificar um profile no seu bean, basta adicionar a anotação @Profile com o nome do profile correspondente. Lembrando que este é o caso em que seus Beans estão sendo criados pelo component-scan usando package scan. Vamos criar um exemplo pra ficar mais claro o que acontece.
Vamos criar uma interface comum para nossos beans:


[cc lang=”java” width=”100%”]
public interface ProfileEspecificBean {

String recoverActiveProfile();

}
[/cc]


Agora vamos criar dois profiles e dois beans diferentes para a mesma interface. Um é o bean de desenvolvimento (dev) e o outro de testes (qa).


[cc lang=”java” width=”100%”]
public final class Profiles {

private Profiles() {
}

public static final String DEV_PROFILE = “dev”;

public static final String QA_PROFILE = “qa”;

}
[/cc]


[cc lang=”java” width=”100%”]
package br.com..tentativas.beans;

@Component(“profileBean”)
@Profile(DEV_PROFILE)
public class DevEspecificBean implements ProfileEspecificBean {

@Override
public String recoverActiveProfile() {
return DEV_PROFILE;
}

}
[/cc]


[cc lang=”java” width=”100%”]
package br.com..tentativas.beans;

@Component(“profileBean”)
@Profile(QA_PROFILE)
public class QAEspecificBean implements ProfileEspecificBean {

@Override
public String recoverActiveProfile() {
return QA_PROFILE;
}

}
[/cc]


Repare que já anotei os beans com @Profile respeitando os profiles especí­ficos de cada bean.
Agora criamos o arquivo de beans do spring, dei o nome de spring31-test-beans.xml:


[cc lang=”xml” width=”100%”]


[/cc]


Feito isso, vamos criar um teste para verificar a lógica de criação dos beans. estou usando JUnit 4.8.1.


[cc lang=”java” width=”100%”]
public class ProfileBeansTest {

@Test
public void testProfileDev() {

GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles(DEV_PROFILE);
ctx.load(“classpath:spring31-test-beans.xml”);
ctx.refresh();

// Profile de DEV
ProfileEspecificBean profileBean = ctx.getBean(“profileBean”,
ProfileEspecificBean.class);

Assert.assertEquals(DEV_PROFILE, profileBean.recoverActiveProfile());
}

@Test
public void testProfileQA() {

GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles(QA_PROFILE);
ctx.load(“classpath:spring31-test-beans.xml”);
ctx.refresh();

// Profile de QA
ProfileEspecificBean profileBean = ctx.getBean(“profileBean”,
ProfileEspecificBean.class);

Assert.assertEquals(QA_PROFILE, profileBean.recoverActiveProfile());
}
}
[/cc]


Algumas coisas diferentes estão acontecendo nesse teste.
Estou instanciando um GenericXmlApplicationContext para carregar meus arquivos de beans, isso porque esse application context me disponibiliza um método que é importante para nosso teste: getEnvironment(). Com isso conseguimos acessar o environment do application context, e mais do que isso, conseguimos setar os profiles que estão ativos usando setActiveProfiles. Repare que é possí­vel de setar mais de um profile como ativo, e que os beans podem precisar de mais de um profile para serem instanciados.
Outro fato importante, é que este environment que está disponí­vel, é uma instância de ConfigurableEnvironment. Se você tentar acessar o profile diretamtente em ApplicationContext, você estará acessando um Environment o qual não permite ativar e desativar profiles. Fica a dica.


Após ativar o profile que queremos, basta chamar o load no contexto seguido do refresh para que os beans sejam criados.
Uma vez que o bean foi criado, basta recuperá-lo e executar o teste para se certificaro que se trata do bean que estamos esperando. Note que o nome dos dois beans é o mesmo, e que apenas um deles existe no application context, pois o outro profile não está ativo.

Nested Beans

Outra maneira de definir profiles nos beans é diretamente no XML do spring. Para que isso seja possí­vel foi necessário permitir nested beans nos arquivos de beans, ou seja, definições de beans dentro de outra definição.
Além de possibilitar a definição de diferentes profiles, essa nova funcionalidade permite que sejam definidos alguns padrões de comportamento para os beans que só se apliquem no conjunto de beans que está nested. Mas isto veremos em um próximo post.
Para testar a definição de profiles direto no XML, vamos criar um outro XML chamado spring31-test-nested-beans.xml:


[cc lang=”xml” width=”100%”]






[/cc]


Feito isso, vamos criar um novo teste que é idêntico ao primeiro, com exceção do arquivo de beans especificado, afinal o comportamento deve ser o mesmo em ambos os casos:


[cc lang=”java” width=”100%”]
@Test
public void testProfileDevXml() {

GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles(DEV_PROFILE);
ctx.load(“classpath:spring31-test-nested-beans.xml”);
ctx.refresh();

// Profile de DEV
ProfileEspecificBean profileBean = ctx.getBean(“profileBean”,
ProfileEspecificBean.class);

Assert.assertEquals(DEV_PROFILE, profileBean.recoverActiveProfile());
}

@Test
public void testProfileQAXml() {

GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles(QA_PROFILE);
ctx.load(“classpath:spring31-test-nested-beans.xml”);
ctx.refresh();

// Profile de QA
ProfileEspecificBean profileBean = ctx.getBean(“profileBean”,
ProfileEspecificBean.class);

Assert.assertEquals(QA_PROFILE, profileBean.recoverActiveProfile());
}
[/cc]


Sua barra do JUnit vai ficar verde e você vai ficar feliz com essa brincadeira rápida com profiles.

Ativando Profiles de outras maneiras

Ativa os profiles no código funciona muito bem no caso dos testes, mas o que realmente se aplica a vida real é poder ativar tais profiles de maneira independente da aplicação e do código propriamente dito. Por isso podemos ativar os profiles setando uma variável global chamada spring.profiles.active.
Podemos ativar tal variável de diversas maneiras, dentre elas no próprio web.xml como um parâmetro da sua Servlet do Spring:


[cc lang=”xml” width=”100%”]

dispatcher
org.springframework.web.servlet.DispatcherServlet
spring.profiles.activeqa

[/cc]


Podemos usar também JNDI, ou até mesmo uma variável de ambiente da VM Java. Se você preferir também pode ativar profiles diretamente no maven:


[cc lang=”xml” width=”100%”]
-Dspring.profiles.active=”profile1,profile2″
[/cc]

Fazendo Download

Se você usa o maven, basta adicionar o seguinte no seu pom:


[cc lang=”xml” width=”100%”]


org.springframework.maven.milestone
Spring Maven Milestone Repository
http://maven.springframework.org/milestone



org.springframework
spring-core
3.1.0.RC1


org.springframework
spring-beans
3.1.0.RC1


org.springframework
spring-context
3.1.0.RC1


[/cc]


Caso você queira baixar diretamente do site, acesse o site do spring.

Espero ter sido útil, qualquer pergunta basta enviar nos comentários.

Por @Gust4v0_H4xx0r

2 Comments

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Compartilhe isso: