Back-End

15 abr, 2009

Login Flex + BlazeDS + Java + Spring + Hibernate Annotations – Parte 2

Publicidade

Olá, pessoal, espero que tenham gostado do primeiro artigo, foi algo simples. Agora vamos incrementar aquele exemplo da parte 1 para tornar esse login interessante. Vocês perceberam que ele ainda não tem nenhuma integração com algum back-end, portanto vocês podem utilizar esse artigo como referência, mesmo se utilizarem uma linguagem diferente do Java. Porém, para aqueles que usam Java, fica mais fácil, pois mostrarei o caminho que utilizei.

O que vamos fazer?

A integração com o Java pode ser feita de diversas maneiras – por HTTPService, RemoteObject, entre outras. No nosso caso, iremos utilizar o BlazeDS para fazer uma chamada de um objeto remoto.

Esse é um ponto que eu não havia lembrado quando pensei em fazer essa série de artigos, eu levei em consideração que todos saberiam e estariam com a integração feita. Porém, também não está no escopo desse texto a explicação de como fazer essa integração. Portanto, procurei alguns links na internet (em português) que demonstram como fazer essa integração, e também disponibilizo o link do projeto base.

Vamos utilizar o seguinte ambiente:

  • BlazeDS + Java + Hibernate Annotations + Spring

Um ótimo tutorial existente na internet dessa integração (inclusive foi muito útil quando comecei, me serve de referência até hoje), é esse:

Só que fiz algumas alterações, porque não gosto de trabalhar com os hbm’s do hibernate, prefiro trabalhar com annotations.

Tomando como base esse link [http://forum.flexbrasil.com.br/viewtopic.php?f=8&t=97], fiz um projeto de base e disponibilizo para vocês a base para seguir o restante do artigo. Clique aqui para fazer o download do projeto-base.

Agora que tudo está configurado, vamos realmente colocar a mão na massa.

1. Primeiramente, vamos criar o banco de dados

Ele tem uma tabela chamada usuario, na qual serão salvos todos os usuários.Tem cinco campos usu_codigo auto-incremento, necessário para o funcionamento do hibernate, seu nome e cargo, que depois serão recuperados dentro do sistema, e seu login e senha necessários para se logar ao sistema.

Para facilitar disponibilizo para vocês a tabela já criada e com os dados:

CREATE TABLE IF NOT EXISTS `usuario` (
`usu_codigo` int(10) unsigned NOT NULL AUTO_INCREMENT,
`usu_nome` varchar(70) DEFAULT NULL,
`usu_cargo` varchar(25) DEFAULT NULL,
`usu_login` varchar(15) DEFAULT NULL,
`usu_senha` varchar(15) DEFAULT NULL,
PRIMARY KEY (`usu_codigo`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Extraindo dados da tabela `usuario`
--

INSERT INTO `usuario` (`usu_codigo`, `usu_nome`, `usu_cargo`, `usu_login`, `usu_senha`) VALUES
(1, 'Rafael Rodrigues Viana', 'Nome do Cargo', 'rafael', 'rafael123'),

OBS:Você precisa alterar no WebContent/WEB-INF/applicationContext.xml o driver de conexão com o banco de dados (se for diferente do MySql), nome do banco de dados, usuario e senha.

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>driverdobancodedados</value>
</property>
<property name="url">
<value>jdbc:mysql://endereçodoservidor/nomedobancodedados</value>
</property>
<property name="username">
<value>usuariodobancodedados</value>
</property>
<property name="password">
<value>senhadobancodedados</value>
</property>
</bean>

2. Vamos agora criar um serviço para que o Flex consiga acessar uma classe Java através do BlazeDS

2.1 Crie uma classe Java, que será a entidade Usuario, dentro do package entity:

Usuario.java

package br.com.cauirs.model.entity;

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Entity;

@Entity
@Table(name="usuario")
public class Usuario {

@Id
@GeneratedValue
private Integer usu_codigo;

private String usu_nome;
private String usu_cargo;

private String usu_login;
private String usu_senha;

/*Getter's e Setter's*/
}

Depois de criada a entidade, precisamos mapear a entidade Usuario.

Vamos lá no applicationContext e vamos retirar o comentário ao redor das tags da propriedade “annotedClasses”.

OBS: Toda entidade criada precisa ser “anotada” aqui.

2.2  Crie uma classe Java dentro do package services

Conforme citado por Digows em seu artigo,

“Services são classes que não implementam diretamente as regras de negócio da aplicação, apenas coordenam a interação entre os componentes, elas são quase sempre beans gerenciados pelo Spring. É muito importante que as classes do tipo Services não implementem as regras de negócio, elas apenas atuam como Façades coordenando as interações.”

UsuarioService.java

package br.com.cauirs.model.service;

import br.com.cauirs.model.entity.Usuario;

public interface UsuarioService {
Usuario doLogin(String usuario, String senha) throws Exception;
}

OBS: Todo serviço criado precisa ser declarado no remoting-config.xml

2.3 Dentro do package entity crie uma classe actionScript com o nome Usuario

package br.com.cauirs.view.entity
{
[RemoteClass(alias="br.com.cauirs.model.entity.Usuario")]
[Bindable]
public class Usuario
{
public var usu_codigo:Number;
public var usu_nome:String;
public var usu_cargo:String;
public var usu_login:String;
public var usu_senha:String;
}
}

Conforme citado por Digows em seu artigo:

“A Classe Usuario do Flex é nada mais nada menos do que o espelho do Entity do java, nesta classe não realizei get’s set’s. Para fazer o espelho dos objetos usei a metatag [RemoteClass] mapeando a localização exata (Com package e nome da Classe) da mesma classe no java. A metatag Bindable é uma annotation muito importante, mas agora vamos apenas abstrair ela.”

2.4 Dentro do package model.repository.hibernate, irão ficar todas as classes que implementam o Pattern DAO usando o Hibernate

Crie dentro desse package um DAO para a entidade Usuario. Para isso, crie uma classe java chamada UsuarioHibernateDao, ela ficará assim:

UsuarioHibernateDao.java


package br.com.cauirs.model.repository.hibernate;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import br.com.cauirs.model.entity.Usuario;
import br.com.cauirs.model.repository.UsuarioRepository;

@Repository(value="usuarioRepository")
public class UsuarioHibernateDao extends HibernateDaoSupport
implements UsuarioRepository {

@Autowired
public UsuarioHibernateDao(@Qualifier("sessionFactory")SessionFactory factory) {
super.setSessionFactory(factory);
}

@Override
public Usuario doLogin(String usuario, String senha) {
return null; //método será implementado aqui
}

}

OBS: Para compreender melhor o funcionamento dessa classe, consulte os links de referência.

OBS²: Classe terá seu método implementado no item 2.7

2.5 O package model.repository irá conter interfaces do tipo repository que dará comportamento aos DAO’s

Crie uma interface chamada UsuarioRepository, que ficará assim:

UsuarioRepository.java

package br.com.cauirs.model.repository;

import br.com.cauirs.model.entity.Usuario;

public interface UsuarioRepository {
Usuario doLogin(String usuario, String senha);
}

Ela é igual a interface do UsuarioService.

2.6 Vamos agora implementar a interface UsuarioService, para que se comporte como uma classe de serviço gerencia pelo Spring. Ela ficará assim:

UsuarioServiceImpl.java

package br.com.cauirs.model.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.cauirs.model.entity.Usuario;
import br.com.cauirs.model.repository.UsuarioRepository;

@Service(value="usuarioService")
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public class UsuarioServiceImpl implements UsuarioService{

private UsuarioRepository usuarioRepository;

@Autowired
public void setUsuarioRepository(UsuarioRepository usuarioRepository) {
this.usuarioRepository = usuarioRepository;
}

@Override
public Usuario doLogin(String usuario, String senha) throws Exception {
try {
return this.usuarioRepository.doLogin(usuario, senha);
} catch (Exception e) {
throw new Exception("Não foi possível fazer o login."+e.getMessage());
}
}

}

OBS: Para compreender melhor o funcionamento dessa classe, consulte os links de referência.

2.7 E agora, finalmente, vamos implementar o método doLogin na classe UsuarioHibernateDao

O método é simples, teoricamente ele pesquisa na base de dados na tabela de usuario pelo usuario e senha, e se achar algum resultado permite a entrada. Mas também queremos que ele retorne um objeto Usuario para que, posteriormente, possamos acessá-lo de dentro do sistema.

Para isso usei o método requiredUniqueResult da classe DataAccessUtils do Spring (http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/dao/support/DataAccessUtils.html). Ele vai retornar um único objeto, e com ele vou fazer um cast falando que é do tipo Usuario.

O método vai ficar assim:

@Override
public Usuario doLogin(String usuario, String senha) {
return (Usuario) DataAccessUtils.requiredUniqueResult(getHibernateTemplate()
.find("from Usuario WHERE usu_login = ? AND usu_senha = ?",
new Object[]{usuario, senha}));
}

Ufa! Enfim, a parte do back-end está pronta, sei que este artigo está ficando extenso, mas vamos continuar. Estamos quase prontos.

3. Vamos agora alterar o formulário de login criado na primeira parte, vamos agora abstrai-lo para um componente

3.1 Crie um novo Flex Componente dentro da package view/components, vamos usar o mesmo código usado anteriormente, ele deve estar assim:

LoginForm.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Panel id="pnlLogin" layout="absolute" title="Sistema de Login - Imasters"
x="10" y="10"
width="250" height="141"
horizontalCenter="0" verticalCenter="0">

<mx:Label text="Login:"
x="10" y="10" />
<mx:TextInput id="tfLogin"
x="58" y="8"/>

<mx:Label text="Senha: "
x="5" y="36"/>
<mx:TextInput id="tfSenha"
x="58" y="34"
displayAsPassword="true"/>

<mx:Button x="84" y="64"
label="Entrar"/>

</mx:Panel>

</mx:Canvas>

Vamos agora modificar esse componente para acessar o objeto remoto e fazer o login pelo banco de dados.

3.2 Como será feito por objeto remoto, precisaremos das tags (ficará dentro do canvas porém fora do panel)

A sua tag ficará assim:

<mx:RemoteObject id="usuarioService" showBusyCursor="true"
destination="usuarioService">
<mx:method name="doLogin" fault="loginServiceFaultHandler(event)"
result="loginServiceResultHandler(event)"/>
</mx:RemoteObject>

Nessa tag falamos que chamaremos o usuarioService (nomeado anteriormente). Precisaremos de dois métodos loginServiceFaultHandler, que será chamado caso ocorra um erro no login, e o método loginServiceResultHandler, que será chamado se o login for efetuado com sucesso.

3.3 Vamos criar essas duas funções, entre as tags .

<mx:Script>
<![CDATA[
import mx.core.Application;
import br.com.cauirs.view.entity.Usuario;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;

private function loginServiceFaultHandler(event:FaultEvent):void{
if(event.fault.faultString
== "java.lang.Exception : Não foi possível fazer o login.Incorrect
result size: expected 1, actual 0")
Alert.show("Usuário ou senha inválida", "Erro");
else
Alert.show(event.fault.message, "Erro");
}

private function loginServiceResultHandler(event:ResultEvent):void{
Application.application.usuario = (Usuario)(event.result);
tfLogin.text = "";
tfSenha.text = "";
Alert.show("Usuário
Logado: " + Application.application.usuario.usu_login + "\n Senha: " +
Application.application.usuario.usu_senha +
"\n Nome: " + Application.application.usuario.usu_nome + "\n Cargo: " + Application.application.usuario.usu_cargo);
}

private function onFault(event:FaultEvent):void{
Alert.show("Erro: " + event.fault.message);
}

]]>
</mx:Script>

Clique aqui para fazer o download do projeto final, com todos os Jars.