Converter JSF com Spring

 

Olá Pessoal,

O post de hoje será bem rápido. Se você está  precisando criar um Converter e fazer com que este seja gerenciado pelo Spring, o que fazer? Ao olhar a documentação do Spring não há nenhuma anotação direta para o Converter. Lets go! Vamos ver na prática como fazer isso…

 

Converter

Um resumo rápido: Sabemos que quando precisamos carregar um selectOneMenu, por exemplo, um valor customizado, é preciso ter um converter, como por exemplo se preciso carregar cidade, estado, status,  etc é necessário ter um converter, e para implementarmos um converter temos que criar uma classe que implementa a interface Converter do JSF. Nada de especial até aqui, certo?

@FacesConverter( value= “com.camilolopes.readerweb.TypeConverter”,forClass=Type.class)

public class TypeConverter implements Converter {

       @Override

public Object getAsObject(FacesContext context, UIComponent component, String value) {

 

return null;

       } 

       @Override

public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {

             

return null;

       } 

}

Mas você está usando o Spring e quer que seu Converter seja gerenciado por ele, e ainda assim poder chamar as classes de serviços, como fazer? Veja o código alterado com Spring e chamando um método na classe de serviço: 

@Component(“typeConverter”)

public class TypeConverter implements Converter {

       @Autowired

       private TypeServiceImpl typeServiceImpl;

       @Override

public Object getAsObject(FacesContext context, UIComponent component, String value) { 

              Type type = typeServiceImpl.searchById(Long.valueOf(value));

              return type;

       } 

       @Override

       public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {

                     if(value!=null){

                           return ((Type)value).getId().toString();

                     }

              return null;

       } 

       public TypeServiceImpl getTypeServiceImpl() {

              return typeServiceImpl;

       } 

       public void setTypeServiceImpl(TypeServiceImpl typeServiceImpl) {

              this.typeServiceImpl = typeServiceImpl;

       } 

}

Basta anotar com @Component e definir um id para o converter. Na página XHTML chamaremos o id usando EL, veja:

<p:selectOneMenu value=“#{userController.selectedType}” converter=“#{typeConverter}”>

<f:selectItems  itemLabel=“#{type.description}” itemValue=“#{type}” var=“type”  value=“#{typeController.listTypes}” />

</p:selectOneMenu>

Pronto, assim temos o converter via Spring. Claro que você precisar ter no seu face-config.xml na tag <application />

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

 Dizendo para o JSF que o Spring vai cuidar da instanciação dos objetos etc. Veja nesse post.

Por hoje é isso. See ya!!

Internacionalização sua aplicação com JSF

Olá Pessoal,

No post de hoje veremos como internacionalizar nossa aplicação JSF.  Eu acho o suporte de internacionalização do JSF muito simples e fácil. É comum você trabalhar em um projeto e o cliente falar que deseja dar suporte pelo menos a 2 idiomas: um default e +1. Veremos como preparar nossa aplicação para isso. Lets go…

Starting…

O JSF procura os arquivos de tradução em um local, que é dentro de resources / src/main/resources, então é lá que vamos colocar os .properties para cada idioma que a aplicação vai suportar. No exemplo aqui será português e inglês, portanto crie dois arquivos .properties chamado: language_en_US e language_pt_BR.  O nome language pode ser qualquer outro. O que teremos nele? Como qualquer arquivo de properties um key=value, é nele que vamos colocar a tradução da aplicação dos labels, message etc. Dentro de src/main/resources crie o seguinte package: com/camilolopes/readerweb/idiom, é onde ficarão nossos arquivos .properties. Poderia deixar na raiz, mas quis colocar em package para ficar organizado.

 

jsfinterproperties

Feito isso, abra o seu face-config.xml e faça isso dentro de application:

<locale-config>

   <default-locale>pt_BR</default-locale>

   <supported-locale>pt_BR</supported-locale>

   <supported-locale>en_US</supported-locale>

  </locale-config>

  <!– Local where is .properties –>

  <resource-bundle>

       <base-name>com.camilolopes.readerweb.idiom.language</base-name>

       <!–  variable will be used in system of context –>

       <var>language</var>

  </resource-bundle>

 

Observe que criamos uma variável. É ela que vamos usar no XHTML passando o key do .properties para que possa ser traduzido com base no idioma definido no browser.

Colocando tradução no .properties

Eu particularmente gosto muito do plugin Resource Bundle http://sourceforge.net/projects/eclipse-rbe/ , pois ele me permite de uma única vez atualizar os dois arquivos  .properties, já inserindo a tradução, veja:

 

jsfpropertiesbundle

Se você usa o Eclipse é só instalar o plugin, mas ele não está no Eclipse Market, é old school, ou seja, você vai na pasta plugin do seu eclipse e cola todo o conteúdo de plugin que está no resource bundle que você acabou de baixar.

Usando na Prática

<h:outputLabel value=“#{language[‘label.type.description’]}” for=“name” />

<h:commandButton value=“#{language[‘command.save’]}” />

 

Resultado:

jsfinterlabelenglish

 

jsfinterlabelpt

Simples, não? Conheça API I4JSF

Espero que tenham gostado. See ya!!!

Abraços.

Overview I4JSF API for JSF Internationalization

Olá Pessoal,

O post de hoje é um pouco diferente. O objetivo é apresentar para vocês o I4JSF API. Ué, mas que API é essa, Camilo? É uma API para JSF com o objetivo de ajudar a evitar a repetição de código para internacionalização. Sim, mas por que usar essa API? Qual o ganho?

 Vamos conhecer a seguir.

Lets go…

O contexto

Antes de apresentar a API vamos entender alguns contextos que já passei e foi de onde veio a ideia de criar I4JSF API que ainda está “verde” e na sua primeira versão. Quando trabalhamos apenas com 1 projeto JSF é comum em alguns casos criar uma classe utilitária para o código de internacionalização, ou melhor, o trecho de código que trata em adicionar uma mensagem no contexto do JSF, independente se veio de um bundle  ou  uma String direta.  Nada de errado aqui. Mas e quando na empresa que você trabalha há mais de um projeto JSF? E que em algum momento há algo em comum referente à implementação entre eles?

Por exemplo, identifiquei que em 2 projetos JSF ambos tinham uma classe para tratar de maneira mais produtiva sem perder a qualidade, com código utilitário, que era criando uma classe utilitária. Daí pensei “se existe uma API em comum, não seria melhor para os dois projetos, desde a melhoria até a manutenção desse código semelhante? Quanto os desenvolvedores gastaram para criar a classe utilitária que normalmente era um código necessário, mas que não estava associado às regras de negocio do projeto, porém era preciso escrever para facilitar o trabalho?”.

I4JSF

Assim nasceu I4JSF API, com o objetivo de evitar esse retrabalho em equipes que usam JSF e vão precisar internacionalizar aplicação e não querem fazer uma classe utilitária para cada projeto JSF.  No GitHub da API você pode encontrar todas as informações de como usar, adicionar ao seu pom.xml ou fazer o download do .jar e ainda há um projeto demo I4JSFDemo, que é um JEE Project que mostra I4JSF in Action.

Claro que há muito trabalho para ser feito e adicionando API, afinal de contas ela acabou de nascer e ai temos uma oportunidade caso deseje contribuir para o desenvolvimento. Veja como:

  1. Faça um fork do projeto no Github;
  2. Implemente a melhoria;
  3. Envie sua mudança;

Um exemplo de uso. Veja a comparação de código usando I4JSF com o código natural do JSF:  

Natural JSF

FacesContext facesContext = FacesContext.getCurrentInstance();

    ResourceBundle bundle = facesContext.getApplication().getResourceBundle(facesContext, “language”);

    String byndleKey = “msg.error”;

    String msgBundle = bundle.getString(bundleKey);

    addFacesMessage(facesContext, msgBundle);

 I4JSF

new I4JSF().addTranslateContext("language", "msg.error");

FAQ

Se for preciso adicionar uma mensagem no contexto JSF via bundle, como faço?

– Simples, chame o método public void addTranslateContext(String bundleVar, String keyProperties) e passe o nome da variável bundle declarada  e a key do bundle e a API se encarrega do resto.

Quero adicionar uma mensagem via bundle para um componente específico, posso?

– Sim. Chame o método addTranslateContext() passando o componentId,variavelBundle e key do bundle

Preciso adicionar uma mensagem para um component, informar a serverity e a mensagem direta. É possível?

– Sim, chame addMessageFaceContext(componentid,serverity, message)

 Preciso adicionar apenas uma mensagem ao contexto, como fazer?

Chame addFacesMessages() passando o FacesContext e  a mensagem que deseja

 Como adicionar uma mensagem para um severity específico sem especificar o component Id?

Chamando  addMessageFaceContext(severity,message).

GitHub 

https://github.com/camilolopes/I4JSF-API

Example Project

https://github.com/camilolopes/I4JSFDEMO

Vou ficando por aqui e aguardo os forks de vocês

Abraços, see ya!!! 

Utilizando o Selenium para testes Automatizado

Olá Pessoal,

No post de hoje vamos ver como usar o Selenium para criação de testes funcionais. A ideia é um teste simples para mostrar a potência do framework e daí cabe a cada um usar de forma que atenda as necessidades do projeto. Para o post vou usar a versão selenium-server-standalone-2.32.0.jar  disponível http://docs.seleniumhq.org/

 lets go…

Overview sobre o Selenium

Bem, se você usar o Google e pesquisar sobre “Selenium unit test” verá vários links para a definição, então não há motivos para repetir no post. Veja no famoso Wikipedia. Há um post que gosto bastante sobre o Selenium  que está no blog da Caelum.

Em poucas palavras, nos permite realizar teste funcionais simulando ações que um usuário estaria fazendo.

Mas por que usar um framework para isso?

Há vários motivos para fazer isso de maneira automatizada, como por exemplo:

  • – produtividade;
  • – qualidade;
  • – custo;
  • – feedback.

Contratar um time de profissionais para fazer testes que você pode automatizar, além de custar caro, o tempo gasto é muito maior que de forma automatizada e isso é importante. Assim podemos contratar profissionais para realizar em pontos estratégicos onde não temos como testar de forma automatizada. Como toda e qualquer ferramenta sempre há uma limitação e ai que entra o fator o humano.

Colocando mão na massa

Vamos colocar a mão na massa e criar um projeto muito simples. Faremos um teste que terá como objetivo acessar uma determinada página na internet e fazer uma pesquisa. Se tudo ocorrer bem, o teste vai passar. Mas, por exemplo, se a página estiver indisponível ou o endereço informado para o teste for inválido o teste vai falhar.  

  1. Crie um Java project e dê o nome que quiser;
  2. Adicione a biblioteca do Selenium ao  classpath do projeto;
  3. Crie uma classe de teste, ou seja, Junit Class. No meu caso criei com o nome de HelloSeleniumTest.java

helloseleniumproject

Vamos criar o nosso primeiro teste que vai acessar a página do Google e pesquisar por “Camilo Lopes”. Veja o código a seguir.

public class HelloSeleniumTest { 

       @Before

       public void setUp() throws Exception {

       } 

       @Test

       public void testSearchInGooglePage() {

             WebDriver driver  = new FirefoxDriver();            

//           Digo qual url para acessar

             driver.get(“http://www.google.com”);            

//           Agora vamos buscar o elemento na página

             WebElement inputTextGoogle = driver.findElement(By.name(“q”));

             inputTextGoogle.sendKeys(“Camilo Lopes”);        

/*           faz um submit na página

 *           poderia buscar o botão search e fazer o submit tb.

 */

             inputTextGoogle.submit();            

             assertTrue(driver.getPageSource().contains(driver.findElement(By.id(“gbqfq”)).getText()));

       } 

}

Entendendo o código

Apesar de que em alguns trechos eu coloquei comentários somente para facilitar o entendimento, vou explicar alguns pontos que considero importantes.

WebDriver: é uma interface do Selenium que todo Web Browser Drivers implementa. O Firefox Browser tem  sua implementação, assim como IE e Chrome, cada um com sua particularidade, e é preciso dar uma olhada na documentação sobre como implementar.

Depois que instanciamos o driver,  dizemos a URL que queremos testar (nesse caso será do Google), mas em um projeto JEE, por exemplo, vamos colocar o caminho onde está nossa aplicação.

Em seguida pesquisamos pelos elementos na página, para isso no Chrome podemos usar o atalho F12, clica na lupa que fica no rodapé e clica sobre o input text e ver qual o nome daquele campo. Podemos usar o id, nome etc. Veja:

seleniuminputgooglesearch

Depois que fizemos isso, criamos uma variável para representar esse campo :

WebElement inputTextGoogle = driver.findElement(By.name(“q”));

 

E em seguida invocamos o método sendKeys(…) e passamos o valor que queremos que seja digitado no input. Para descobrir e conhecer melhor os métodos disponíveis tem que passar por alguns minutos vendo o que temos na documentação do framework.

inputTextGoogle.sendKeys(“Camilo Lopes”);

 

Logo em seguida fizemos o submit página

inputTextGoogle.submit();

 

Criando o assert

Bem, para que  seja testado precisamos usar algum assertXXX do framework Junit. Então vamos verificar se após ter feito o submit há um elemento com o id informado na página.

seleniumtestgreen

O teste passa. Na verdade esse teste  não tem nada de inteligente. Se você reparar, ele verifica se o input que pesquisamos na primeira página do Google é o mesmo na página do resultado da busca.

Claro que em nossa aplicação íamos testar algo mais voltado para regras de negócio. E o método getPageSource() nos ajuda nisso, em busca de um elemento na página corrente.

 

Execute o teste

Vamos executar os testes e aguardar por alguns segundos e veremos que o Selenium vai abrir o browser que definimos (no caso do post foi o Firefox)  e realizar a pesquisa.

 seleniumfirefox

Convertendo isso para uma aplicação

Em uma aplicação web, vamos ter que usar a url onde nossa aplicação está rodando. Claro que vamos evitar que o endereço seja informado dentro da classe Java, este pode ser informado de um arquivo .properties por exemplo, efaremos assert voltado para as regras de negócio.

Conclusão

O objetivo desse post não era explorar como escrever bons testes com o Selenium, a ideia era apresentar o framework e vê-lo em ação. Após isso podemos tirar nossas próprias conclusões sobre a eficiência e produtividade gerada  quando usamos corretamente.  Já passei por algumas empresas e projetos onde falaram que o Selenium foi o responsável pelo aumento do dos prazos nas entregas. Acredito que o problema certamente não foi com o Selenium, mas sim na forma de como este foi usado ou adotado dentro do projeto.

 

E você tem usado o Selenium em seus projetos? Compartilhe sua experiência…

Abraços, see ya!!! 

Troubleshooting cglib AOP Exception

 

Olá Pessoal,

O post esse acho que é o menor que já escrevi. Vamos ver como resolver a exceção AopConfigException quando estamos adicionando ao nosso projeto Java. veja:

O problema

Se você está recebendo:

org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

Solução

Adicione cglib ao seu projeto, faça o download http://cglib.sourceforge.net/

Muito simples não?

Abraços, see ya!!