Categoria: Java
Usando Maven Archetype WebApps Module
Olá Pessoal,
O post de hoje é mais uma contribuição. Quero compartilhar com vocês um archetype maven que criamos aqui na empresa e deixamos no github. A seguir resumo o que já vem nele. Veja também como criar seu archetype.
Lets go…
webapps-module archetype maven
Esse archetype nasceu com o objetivo de ter um template com a base da maioria dos projetos aqui na empresa e evitar trabalho repetitivo sempre que formos criar um novo projeto. Este é baseado em modules. Sabemos que no catalogs do maven há uma pilha de archetypes, mas alguns que tentamos usar para o nosso cenário aqui sempre estavam com erros muito chatos para resolver, dai vamos fazer o nosso.
Vou fazer uma pequena apresentação desse archetype.
Github
https://github.com/camilolopes/archetype-webapps-module
O readme.md tem as informações mais pontuais, sem muito detalhe.
A divisão em módulos
O archetype foi dividido em módulos. Quando você cria vai ter:
- módulo principal: terá o nome da app que você informar na criação;
- webapps-core: é o nome default. Esse módulo cuida de todo back-end da aplicação. Aqui tem os testes unitários, persistência com hibernate etc;
- webapps-web: é o nome default, mas pode ser alterado e esse cara cuida de todo front-end da aplicação e tem uma dependência do modulo webapps-core.
Note: quando você cria o projeto baseado no archetype, este vem com configurações default. Você precisa customizar de acordo ao seu projeto, portanto:
1. Remova a dependencia de webapps-core no projeto webapps-web. E adicione a dependência webapps-core do seu projeto. Importe o projeto webapps-core para IDE antes;
Qual a vantagem de usar esse archetype?
- Todos os módulos já vem prontos para uso, com as configurações feitas para Spring, Hibernate, teste em memória com HSQLDB usando o DBUnit;
- Spring core configurado;
- Hibernate configurado;
- DBunit configurado e usando uma estrutura que desenvolvi para evitar repetição de setup;
- Há um arquivo chamado its-dataset.xml que é para o dbunit, mas você pode alterar o nome do arquivo e atualizar a classe DBUnitConfiguration.java para o nome correspondente;
- Jersey configurado. Se você precisar, o arquivo web.xml já está ok. Caso não precise, pode remover;
Criando projeto baseado no archetype
Passo 1
Vou assumir que você baixou o archetype no github e seguiu os passos no arquivo readme, ok?
Passo 2
Após ter instalado o archetype localmente, vá no Eclipse (e considerando que você tem o plugin do maven)
crie um novo projeto maven project.
Passo 3
Agora vamos procurar pelo archetype. Escolha all catalogs.
Observe que ele apareceu. Escolha e clique em next.
Passo 4
Preencha com as informações do seu projeto.
Clique em finish e aguarde o projeto ser criado
Passo 5
Observe que temos dois módulos:
Pronto. Preciso mudar mais alguma coisa?
Sim. Como todo template ele vem vazio, com informações de banco de dados. Os packages usados pelo spring são
o default do archetype, e você precisa informar o seu. Então aqui vai um checklist do que você precisa alterar:
- app-context.xml
- test-context.xml
- parent/pom.xml: se você for usar o plugin flyway informe aqui as configurações do banco de dados. Não é requerido fazer essa alteração.
Você pode renomear o diretório (algo como myapps-core) ou manter como está. Os packages do projeto também podem ser renomeados, mas fique atento porque se você mudar o nome do package apenas precisa informar isso no arquivo app-context.xml e test-context.xml do Spring. Não se assuste, porque a mudança é bem pequena e simples.
Espero que tenham gostado e sugestões são bem vindas. Essa é a primeira versão do archetype e estamos criando outros para cenários bem comuns de projetos Java. Archetype sempre baseado em módulos. Temos que fazer algumas configurações mais pontuais, mas o tempo gasto é menor do que criar tudo manualmente sempre que tem um novo projeto.
Eu te recomendo testar o archetype com as configurações default, ver se atende ao que precisa e depois gerar um novo projeto customizado para o que vai desenvolver.
Abracos. See ya!!
Criando um archetype no maven
mvn archetype:create-from-project
seuProjeto\target\generated-sources\
mvn clean install
mvn install archetype:update-local-catalog
Assim as alterações são atualizadas localmente.
Review de um leitor: Livro SCJP e TDD na Prática
Opa Pessoal,
Hoje recebi um email do leitor Thiago, autor do blog http://www.varallos.com.br que fez um review: Guia do Exame SCJP e TDD na Prática.
Confiram aqui:
Review Guia do Exame SCJP
http://www.varallos.com.br/site/review-guia-do-exame-scjp/
Review TDD na Prática
http://www.varallos.com.br/site/review-tdd-na-pratica/
abraços, see ya!!!
Implementando UserDetailsService Spring Security
Olá Pessoal,
No post de hoje veremos como implementar a interface UserDetailsService do Spring. Mas para que serve ela, Camilo? É o que vamos ver logo a seguir…
Lets go…
Starting…
Este post será bem pontual e vou considerar que você já usa e conhece o Spring Security. Uma das opções mais comum de validar autenticação do usuário seria algo mais ou menos assim:
<jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT email, password, 'true' as enable FROM user WHERE email=?;" authorities-by-username-query="select distinct u.email,ro.role_description from user u, user_role r, role ro where u.id = r.role_id and ro.id=r.role_id and u.email=?;" />
Independente de como está seu relacionamento no banco, a questão é que você usaria o jdbc-user-service />
Mas você pode estar perguntando “e se quiser usar minha classe de serviço (service) ou meu DAO, se nessas classes eu já tenha a implementação de busca de um usuário, como fazer?”.
Implementando UserDetailsService
Por default, o Spring a implementa. O que vamos fazer é um override dessa implementação e dizer que é pra chamar um serviço de busca customizado.
Vou mostrar a seguir apenas o código principal e o que você precisa fazer. Será bem pontual.
Step 1
Crie uma classe para esse tratamento (chamei de AuthenticationService). Veja :
@Service public class AuthenticationService implements UserDetailsService { @Autowired @Qualifier("userServiceImpl") private UserService userServiceImpl; @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException, DataAccessException { List<GrantedAuthority> listGrantAuthority = new ArrayList<GrantedAuthority>(); User user = userServiceImpl.getByEmail(email); checkGrantAuthorities(user, listGrantAuthority); UserDetails userDetails = validateUser(email, listGrantAuthority,user); return userDetails; }
O método que vamos trabalhar não é difícil de saber, já que tem anotação @Override. É nele que vamos realizar a busca usando as classes de serviço que chama o DAO. No caso acima o username é o email do usuário, por isso realizo a busca por email. O método checkGrantAuthorities(…) verifica a role do usuário e adiciona em uma lista de Grant:
private void checkGrantAuthorities(User user, List<GrantedAuthority> listGrantAuthority) { if(user!=null && user.getRoles()!=null && user.getRoles().isEmpty()==false) for(Role roleUser : user.getRoles()){ final String PREFIX = "ROLE_"; String role = PREFIX + roleUser.getRoleDescription(); listGrantAuthority.add(new GrantedAuthorityImpl(role)); } }
Precisamos fazer isso para que o Spring Security possa validar se o usuário passado possui Role de permissão para a página que deseja. O PREFIX que criamos é que no BD você não salva ROLE_ADMIN, daí precisamos fazer isso. Caso já salve como prefixo, você deve remover essa concatenação do código. Uma vantagem de não salvar o prefixo é que se amanhã você mudar de framework que faça essa parte de segurança, terá que fazer update em todo banco. Então é melhor deixar a aplicação tratar isso para seu banco ficar transparente.
Em seguida criei um método que valida se o usuário retornado é válido:
private UserDetails validateUser(String email,List<GrantedAuthority> listGrantAuthority, User user) { UserDetails userDetails= null; if(user!=null){ boolean accountNonLocked=true; boolean enabledUser=true; boolean accountNonExpired=true; boolean credentialsNonExpired=true; userDetails = new org.springframework.security.core.userdetails.User(email, user.getPassword(), enabledUser, accountNonExpired, credentialsNonExpired, accountNonLocked, listGrantAuthority); } return userDetails; }
Eu tive que colocar o caminho completo do User referente ao Spring devido já ter um import para minha classe User.
Altere o arquivo de contexto do SpringSecurity. No meu caso, tenho um arquivo XML chamado de springsecurity.xml e no authenticationManager preciso dizer como vamos validar o usuário. Para usar a implementação acima precisamos dizer isso:
<authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="authenticationService"> </authentication-provider> </authentication-manager>
Pronto. Feito isso, agora basta testar sua aplicação e ver que vai funcionar da mesma forma que o jdbc default, porém agora os dados vem de um serviço de pesquisa que você implementou, que pode ser em HQL, Criteria etc.
A documentação do Spring é muito bacana:
http://docs.spring.io/spring-security/site/docs/3.1.4.RELEASE/reference/ns-config.html
Abraços. Vou ficando por aqui e espero que tenham gostado
See ya!!