Presentation Layer Validation: Bean Validation Within JSF 2.0

This week, at Elsa Development, we’ve been implementing some customized validators using Bean Validation API. Everything was going fine, until the shadows of Murphy appear. OK, putting aside the drama, a few validators have been implemented successfully, passing all tests, all of them but one...

The Problem

Two constraints were created and for each one, a validator was implemented (which executes the validation logic). Both constraints were used at field-level on JPA entities, the Username and FloatRange constraints were annotated on fields of type string and float, respectively. However, just the Username constraint worked.. Hereunder you can take a look at the implemented code, or part of it :)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UsernameValidator.class)
@Target({
    ElementType.METHOD,
    ElementType.FIELD,
    ElementType.ANNOTATION_TYPE
})
public @interface Username {
    String message() default "{constraint.username.invalid}";
    Class<? extends Payload>[] payload() default {};
    Class<?>[] groups() default {};
}
Code 1. The working constraint.

public class UsernameValidator
        implements ConstraintValidator<Username, String> {
    @Override
    public void initialize(Username annotation) {}

    @Override
    public boolean isValid(String value,
            ConstraintValidatorContext context) {
        // validation logic ommited
    }
}
Code 2. The validation for @Username constraint.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FloatRangeValidator.class)
@Target({
    ElementType.METHOD,
    ElementType.FIELD,
    ElementType.ANNOTATION_TYPE
})
public @interface FloatRange {

    String message() default "{constraint.range}";
    Class<? extends Payload>[] payload() default {};
    Class<?>[] groups() default {};
    float min();
    float max();
}
Code 3. The “murphyfied” constraint (i.e. did not work).

public class FloatRangeValidator
        implements ConstraintValidator<FloatRange, Float> {
    private float min;
    private float max;
 
    @Override
    public void initialize(FloatRange annotation) {
        this.min = annotation.min();
        this.max = annotation.max();
    }

    @Override
    public boolean isValid(Float value,
            ConstraintValidatorContext context) {
        // validation logic ommited
    }
}
Code 4. The “murphyfied” constraint.

The Solution

After a lot of googling and force brute tests... A co worker (Marcelo Yamashita) came with the solution. He tried to use the @FloatRange constraint at property-level, man... that worked! Then, reading more carefully the Hibernate Validator documentation, more specifically the item 2.1.1. Field-level constraints, i noticed the note that says:

Static fields and properties cannot be validated.

 

Well, if i've got it right, by properties it means POJO fields which have getter/setter, or not? If so, then houston, we have a problem... both target annotated fields, belong to JPA entities thus, they have getters and setters! It doesn’t make them properties? Anyway, the workaround rocks, but if you have any idea about the why this happens, please, feel free to share it with the world :)

Test Party

Inspirados em uma Lightening Talk assistida por alguns membros da equipe, realizamos uma Test Party (ou Testing Day, como também é conhecido). Uma Test Party consiste em um momento onde todos os envolvidos no desenvolvimento (desenvolvedores, QA, "gerência", e P.O.s) realizariam testes no sistema, em busca de possíveis erros, de forma que estes não cheguem à produção. O uso de pontuação e gratificação ao final serviriam como estímulo aos participantes.
No nosso caso, participaram as equipes de desenvolvimento e QA. O objetivo era deixar o sistema mais confiável e aumentar a interação das equipes com o sistema do ponto de vista de usuário e não de desenvolvedor.


Os participantes foram organizados em duplas através de sorteio. As regras foram então apresentadas para as duplas:
- O que testar? Deixamos livre a decisão sobre o que cada dupla iria testar, pois o sistema possui diferentes funcionalidades e, portanto,  havia a possibilidade de que a intersecção dos erros encontrados fosse pequena.
- Como testar? Os testes seriam feitos manualmente, de acordo com um objetivo da dupla (realização de uma tarefa no sistema) ou focados na funcionalidade sendo testada. Casos de teste ou erros encontrados poderiam ter scripts de reprodução/automatização criados.
- Pontuação: 1 ponto para bug encontrado, 2 pontos para caso de teste automatizado, e 3 pontos para script que reproduza o bug. A ferramenta utilizada foi o Selenium IDE (pela facilidade e agilidade no uso).
- Gratificação: chocolate para a dupla vencedora.
- Juiz: uma analista de QA foi designada como juiza, confirmando se o comportamento encontrado era de fato um erro e atribuindo os pontos para cada dupla. 

Todos entraram no clima de competição e cada ponto obtido era comemorado pelas duplas. A dinâmica foi bem recebida pela equipe, que se empenhou em fazer bons testes, com mais probabilidade de encontrar erros. 
Algo interessante foi o pouco overlap que ocorreu entre os bugs encontrados, pois cada equipe explorou aspectos diferentes do sistema. Até mesmo em áreas exploradas por mais de uma dupla, diferentes bugs foram encontrados por cada uma. Isso ocorreu não necessariamente pela quantidade de erros naquela região, mas pelo tipo de abordagem de cada dupla.

Em retrospectiva com as equipes, após a "festa", reflexões sobre os pontos positivos e negativos foram feitas. A técnica ajudou os desenvolvedores a sair da zona de conforto e ter contato com problemas que os usuários enfrentam durante o uso. Mesmo com a reformulação do sistema e a aplicação de boas práticas de desenvolvimento, foi possível ver que somente estas não resolvem todos os problemas, e erros podem "escapar" e chegar ao usuário final. A ideia é que o raciocínio utilizado para encontrar os erros seja aplicado na programação, evitando que se repitam.

Sugestões para as próximas edições incluem: 
- Cada dupla ter definidos os seus usuários e os seus participantes específicos para os testes, para não haver conflitos;
- A versão do sistema que será utilizada para os testes deve ser implantada com maior antecedência;
- Definir horário de início e fim, ao invés de aguardar que as duplas terminem suas tarefas;
- Fazer a "festa" fora do horário de expediente para que todos possam se dedicar sem ficar preocupados com as tarefas que "deveriam estar fazendo". Fazendo fora do expediente também permite um clima mais informal, sem pessoas entrando na sala e estranhando as tiaras coloridas e o "clima de festinha" em pleno expediente.

Os erros encontrados foram registrados na nossa ferramenta bug tracker (com seus respectivos scripts de reprodução), geraram tarefas para programação e estão em fase de correção.

A técnica gerou bons resultados e teve feedback positivo. Muitos dos bugs encontrados já foram resolvidos, o uso do Selenium foi incentivado e membros que ainda não o utilizavam com frequência passaram a usar.

Aguardemos então as próximas edições. :)

Tutorial de Instalação do dcm4chee

O dcm4chee é um PACS open source que implementa o padrão DICOM. Ele é compatível com diferentes SGBD’s (MySQL, PostgreSQL, Oracle, etc.) e sistemas operacionais (Windows, Linux e Mac OS).

Neste tutorial vamos descrever a instalação do dcm4chee 2.17.0 em sua versão para o PostgreSQL na plataforma Windows 7 (32 bits). A instalação num ambiente diferente deste pode requerer configurações extras, não descritas neste tutorial.

1. Requisitos básicos

JDK versão 5 ou superior

As instruções de instalação da JDK 6 e a configuração da variável de ambiente JAVA_HOME estão disponíveis aqui.

PostgreSQL

Apesar de já disponível, a versão 9 do PostgreSQL exige configurações extras não abordadas neste tutorial. Recomendamos a versão 8.4, cujas instruções de instalação estão disponíveis aqui.

2. Downloads

JBossAS

O dcm4chee roda sobre o servidor de aplicação JBoss 4.2.3 GA, especificamente. Faça o download do JBoss do site oficial através deste link: jboss-4.2.3.GA.zip.

dcm4chee

Faça o download do dcm4chee em sua versão para o PostgreSQL do site oficial através deste link: dcm4chee-2.17.0-psql.zip.

ARR

O dcm4chee permite a auditoria das operações realizadas, como transferência de arquivos, buscas, etc. Porém esta funcionalidade está num módulo separado, o Audit Record Repository (ARR). Faça o download do ARR em sua versão para o PostgreSQL do site oficial através deste link: dcm4chee-arr-3.0.11-psql.zip.

3. Estrutura de pastas

Descompacte os arquivos baixados na seção anterior numa pasta de sua preferência. É importante o caminho da pasta não conter espaços, pois isto pode acarretar em erros na instalação.

No exemplo deste tutorial vamos extraí-los na pasta “C:\dicom”. Assim, teremos a estrutura de pastas da figura abaixo:



4. Bases de dados

pacsdb

Para criar a base de dados utilizada pelo dcm4chee, abra o prompt de comando e execute o comando “createdb” passando o nome da nova base de dados, “pacsdb”. No exemplo deste tutorial o comando fica assim: “createdb -U postgres pacsdb”.



O parâmetro “postgres” é o usuário utilizado para conectar no banco de dados, no caso o super-usuário, por questões de permissão. O mesmo será passado como parâmetro nos comandos seguintes.

O script de criação das tabelas e outras estruturas da base de dados “pacsdb” está disponível no arquivo “create.psql”, presente na pasta “sql”, dentro da pasta raiz de instalação do dcm4chee.

Execute o comando “psql” passando como parâmetros o nome da base de dados, “pacsdb”, e o arquivo que contém o script. No exemplo deste tutorial o comando fica assim: “psql -d pacsdb -U postgres -f C:\dicom\dcm4chee-2.17.0-psql\sql\create.psql”.



arrdb

O ARR possui sua própria base de dados, de nome “arrdb”. Para criar esta base de dados, no prompt de comando execute o comando “createdb” passando o nome da nova base de dados, “arrdb”. No exemplo deste tutorial o comando fica assim: “createdb -U postgres arrdb”.



O script de criação das tabelas e outras estruturas da base de dados “arrdb” está disponível no arquivo “dcm4chee-arr-sql.ddl”, presente na pasta “sql”, dentro da pasta raiz de instalação do ARR.

Execute o comando “psql” passando como parâmetros o nome da base de dados, “arrdb”, e o arquivo que contém o script. No exemplo deste tutorial o comando fica assim: “psql -d arrdb -U postgres -f C:\dicom\dcm4chee-arr-3.0.11-psql\sql\dcm4chee-arr-sql.ddl”.



Permissões

Para que o dcm4chee e o ARR consigam acessar as suas bases de dados é preciso configurar as respectivas conexões no arquivo “pg_hba.conf”, localizado na pasta “data” dentro da pasta raiz de instalação do PostgreSQL.
No exemplo deste tutorial é a pasta: “C:\Program Files\PostgreSQL\8.4\data”.

Neste arquivo adicione as linhas:
host    pacsdb      postgres    127.0.0.1/32          trust
host arrdb postgres 127.0.0.1/32 trust
Logo acima da linha:
host    all         all         127.0.0.1/32          md5
Conforme a figura abaixo.



Salve o arquivo. Esta configurção dá permissão de acesso às bases de dados pacsdb e arrdb para o usuário “postgres” (utilizado pelo dcm4chee e pelo ARR por padrão) para conexões solicitadas pelo IP local (127.0.0.1). Para outras conexões é solicitada a senha do usuário.

5. Scripts finais de instalação

O próximo passo da instalação do dcm4chee é rodar o script “install_jboss.bat”, localizado na pasta “bin” dentro da pasta raiz de instalação do dcm4chee, passando a pasta raiz de instalação do JBoss como parâmetro. No exemplo deste tutorial o comando para executar este script fica assim:
“install_jboss C:\dicom\jboss-4.2.3.GA”.



Este script vai integrar o dcm4chee com o JBoss, copiando arquivos deste último para a estrutura de pastas do dcm4chee.

Para completar a instalação, temos de rodar o script “install_arr.bat”, localizado na pasta “bin” dentro da pasta raiz de instalação do dcm4chee, passando a pasta raiz de instalação do ARR. No exemplo deste tutorial o comando para executar o script fica assim: “install_arr C:\dicom\dcm4chee-arr-3.0.11-psql”.



Este script vai integrar o dcm4chee com o ARR, copiando arquivos deste último para a estrutura de pastas do dcm4chee.

Pronto. A instalação está completa.

6. Testando a instalação

Para testar a instalação, execute o script “run.bat”, localizado na pasta “bin” dentro da pasta raiz de instalação do dcm4chee. Este script vai inicializar o servidor dcm4chee.



Se todos os passos anteriores deram certo, não haverá mensagem de erro (ERROR) na console, apenas informativas (INFO), como na figura abaixo.



Para testar o dcm4chee, acesse a URL “http://localhost:8080/dcm4chee-web” no seu navegador. Faça o login com o usuário “admin” e senha “admin”.

Para testar o ARR, clique no link “Audit Repository”. Forneça o usuário “admin” e a senha “admin”.

Para parar o dcm4chee pressione as teclas Ctrl + C na console onde o dcm4chee foi inicializado.

7. Configurações adicionais

Permissões do sistema de arquivos

Para configurar as permissões de escrita e leitura do dcm4chee no sistema de arquivos do Windows, acesse a URL “http://localhost:8080/jmx-console” no seu browser (o dcm4chee tem de estar inicializado). Forneça o usuário “admin” e a senha “admin”.

Selecione o link “group=ONLINE_STORAGE, service=FileSystemMgt”, sob o cabeçalho “dcm4chee.archive”.



Localize o cabeçalho “addRWFileSystem()”



Clique no botão “Invoke”.

Instalar o dcm4chee como serviço

Para não ter de executar o comando “run” a cada vez que for utilizar o dcm4chee, você pode instalá-lo como um serviço do Windows. Assim, ele será inicializado a cada vez que o Windows iniciar.

Para tanto, execute o script “install_service.bat”, localizado na pasta “bin” dentro da pasta raiz de instalação do dcm4chee, passando o parâmetro “service”.



Se receber uma mensagem de acesso negado, abra o prompt de comando como administrador (clique com o botão direito do mouse sobre o ícone do prompt de comando e selecione a opção “Executar como administrador”) e tente novamente.

Instalação do PostgreSQL

Neste tutorial vamos instalar o PostgreSQL 8.4 no Windows 7 Professional.

Faça o download da versão 8.4.8-1 para Windows do PostgreSQL:

http://www.enterprisedb.com/products-services-training/pgdownload

Execute o instalador baixado (arquivo postgresql-8.4.1-1-windows.exe).

Aparecerá a tela de boas vindas.



Clique no botão “Next”.


Será solicitada a escolha de um diretório raiz para a instalação do PostgreSQL. Por padrão a instalação ocorre no diretório “C:\Program Files\PostgreSQL\8.4”.



Clique no botão “Next”.


Será solicitada a escolha de um diretório de armazenamento dos dados do banco. Por padrão a instalação ocorre no diretório “C:\Program Files\PostgreSQL\8.4\data”.



Clique no botão “Next”.


Será solicitada a escolha da senha do super-usuário do banco de dados. Digite a senha escolhida e repita-a no segundo campo para a confirmação.



Clique no botão “Next”.


Será solicitada a escolha do número da porta, a ser utilizado por outras aplicações para conectarem-se ao banco de dados. Recomenda-se deixar o padrão 5432.



Clique no botão “Next”.


Na próxima tela será solicitada a escolha da localidade, para as configurações de linguagem da interface e formatos de data. Selecione “Portuguese, Brazil”. Nesta mesma tela você também pode escolher se deseja que a linguagem pl/psql seja instalada.



Clique no botão “Next”.


A próxima tela apenas informa que o instalador está pronto para iniciar a instalação.



Clique no botão “Next”.


Aguarde a instalação terminar.



Clique no botão “Next”.


Pronto, a instação está conculída. Caso queira instalar complementos ao PostgreSQL deixe marcada a opção “Launch Stack Builder at exit?”. Senão, desmarque esta opção.



Clique no botão “Finish”.


A partir de agora você pode gerenciar seu banco de dados através da aplicação pgAdmin, que oferece uma interface gráfica pra tanto.



Você também pode gerenciá-lo através do prompt de comando, chamando o comando “psql” na pasta “bin” dentro do diretório de instalação do PostgreSQL (para o diretório padrão da instalação, é a pasta “C:\Program Files\PostgreSQL\8.4\bin”).


No exemplo abaixo, estou chamando o comando psql passando o nome do usuário “postgres” como parâmetro. Para maiores detalhes sobre os parâmetros, chame o comando “psql --help”.



Para mostrar a lista de comandos do psql digite “\?”. Para mostrar a lista de comandos SQL digite “\h”. Para sair do psql digite o comando “\q”.
Para executar o psql de qualquer diretório, adicione o caminho da pasta “bin” do PostgreSQL à variável de ambiente “Path” do Windows.

A mensagem de aviso da imagem acima ocorre porque a página de código padrão do prompt de comando do Windows difere da utilizada pelo psql. Para evitar este problema, temos de alterar a página de código do prompt de comando do windows. Para isso, antes de chamar o psql, digite o comando "cmd /c chcp 1252".



Isto vai recarregar o prompt de comando com a página de código utilizada pelo psql. Porém, a fonte padrão do prompt de comando não é adequada para esta página de código, tendo de ser alterada. Para tanto, clique com o botão direito do mouse sobre a barra superior da janela e selecione a opção "Propriedades".



Na aba "Fonte", selecione a fonte "Lucida Console" e clique no botão "OK".



Pronto, agora você pode chamar o comando psql sem problemas.