Aplicações Web-based são uma realidade em muitas empresas por motivos como a facilidade de manutenção (não sendo necessário reinstalar a aplicação no cliente a cada alteração).
É claro que como toda tecnologia exitem vantagens e desvantagens. A usabilidade na manipulação de dados numa interface baseada numa pagina web, as vezes poder ser trabalhosa dependendo dos mecanismos de controle que a página oferece, como a validação de dados.
O GWT (Google Web Toolkit) é uma excelente alternativa para geração de páginas web voltadas para aplicações (ex: GMail). A facilidade de criar interfaces e comunica-las com servidores, torna esse Toolkit uma ferramenta interessante no desenvolvimento de aplicações web. Além do Toolkit, a extensão GWT-Ext é uma alternativa a mais que facilita, por exemplo, a criação rápida de formulários com recursos muito semelhantes a aplicações desktop (inclusive de validação). Em aplicações web, a manipulação de dados acontece do modelo cliente/servidor. A criação de web-services do lado servidor para manipulação de dados é uma opção onde tanto aplicações web quando desktop podem facilmente fazer operações CRUD, por exemplo.
Neste contexto entra o conceito de persistência de dados, no Java: JPA. O Hibernate é um serviço baseado neste conceito e que através de Annotations é possível definir entidades de persistência de forma rápida e simples. No entanto, essas entidades possuem características que o compilador GWT não consegue interpretar nativamente. Uma das formas de integra a utilização de GWT para aplicações que utilizam entidades de persistência é implementando o padrão de projeto Decorator. Este padrão de projeto do tipo comportamental permite que sejam definidas funcionalidades específicas a um determinado objeto, no caso a definição de persistência. Sendo assim, cria-se um objeto DTO (Data Transfer Object) e uma entidade de persistência que recebe este DTO para que se possa aplicar a persistência dos dados.
No exemplo que será apresentado a seguir, foram criadas duas entidades de persistência: City e State. As entidades representam duas tabelas no banco de dados que possuem relação entre elas através do campo id da tabela State com o campo state_id da tabela City. No lado cliente (GWT) criou-se duas classes DTO contendo as informações que são persistidas no banco de dados. O processo da-se da seguinte maneira:
- O cliente cria um DTO com os dados da tela;
- O cliente passa através do service o DTO;
- O service cria a entidade de persistencia passando como parametro do contrutor o DTO;
- O service faz a persistencia da entidade.
Para melhor exemplificar segue abaixo o código fonte do DTO (cliente) e da entidade da tabela State(servidor):
public class StateBean implements IsSerializable, Serializable {
private Integer id;
private String abbrev;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAbbrev() {
return abbrev;
}
public void setAbbrev(String abbrev) {
this.abbrev = abbrev;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object[] toObjectArray(){
return new Object[]{
this.getId(),
this.getAbbrev(),
this.getName()
};
}
}
@Entity
@Table(name="State")
public class State implements Serializable {
@Transient
private StateBean bean;
private List<City> city;
public State(StateBean bean){
this.bean = bean;
}
public State(){
this.bean = new StateBean();
}
@OneToMany(cascade=CascadeType.ALL,mappedBy="state")
public List<City> getCity() {
return city;
}
public void setCity(List<City> city) {
this.city = city;
}
@Column(name="abbrev")
public String getAbbrev() {
return bean.getAbbrev();
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
public Integer getId() {
return bean.getId();
}
@Column(name="name")
public String getName() {
return bean.getName();
}
public void setAbbrev(String abbrev) {
bean.setAbbrev(abbrev);
}
@Transient
public StateBean getBean(){
return bean;
}
public void setId(Integer id) {
bean.setId(id);
}
public void setName(String name) {
bean.setName(name);
}
public void setBean(StateBean b){
this.bean = b;
}
}
No serviço temos o seguinte:
public class StateServiceImpl extends RemoteServiceServlet implements
StateService {
...
public boolean save(StateBean bean) {
BaseDao
State st = new State(bean);
return bd.save(st);
}
…
}
O BaseDao serve apenas como utilitario para a persistencia. Ele possui o seguinte código:
public class BaseDao
private static SessionFactory factory = InitSessionFactory.getInstance();
…
public boolean save(T obj){
Session em = factory.openSession();
try{
em.getTransaction().begin();
em.persist(obj);
em.getTransaction().commit();
return true;
} catch (Exception e){
em.getTransaction().rollback();
e.printStackTrace();
return false;
} finally {
em.close();
}
}
…
}
Na internet é possível encontrar outras alternativas para utilizar Hibernate e GWT. gwt-hibernate é uma alternativa semelhante a apresentada porém sem a utlização de JPA. hibernate4gwt faz tranformações de classes entre o cliente e o servidor. Este tutorial também apresenta uma alternativa de implementação.





