Poucos dias antes de sair de férias precisei ajudar um amigo a fazer seu primeiro programa em Java e aproveitando o ensejo, fui ensiná-lo a construir, também, sua primeira aplicação em Flex (já que Adobe Flex foi definido como opção oficial da Elotech - onde trabalhamos - para suas aplicações web).
Como o banco de dados já foi definido anteriormente em uso por outros sistemas desktop - Delphi… ecaaa, tivemos que mapear nossas classes de entidades (@Entity) com chaves compostas (@Embeddable e @EmbeddedId). Mapear as classes no lado Java não foi problema, o problema foi descobrir o mapeamento correto no lado do Flex.
Considere o seguinte exemplo:
package com.mariojunior.sys.entidades;
//imports omitidos
@Entity
public class TesteCompositeId implements Serializable {
private static final long serialVersionUID = 1L;
//A classe interna que representa a chave composta
//precisa ser obrigatoriamente PUBLIC para que o BlazeDS
//possa “enxergar” a classe e serializá-la.
@Embeddable
public static class PK implements Serializable {
@Column(length=15)
private String login;
@Column(length=11)
private String cpf;
//getter e setters omitidos
}
//Atributo que representa o Tipo da chave composta.
@EmbeddedId
private PK id;
@Column
private String nome;
@Column
private String sobrenome;
//getters e setters omitidos
}
Em ActionScript 3, uma classe assim PODERIA ser mapeada da seguinte forma:
[Bindable]
[RemoteClass(alias=”com.mariojunior.sys.entidades.TesteCompositeId“)]
public class TesteCompositeId {
public static class PK {
public var login : String;
public var cpf : String;
}
public var id : PK;
public var nome : String;
public var sobrenome : String;
}
Eu disse que PODERIA, porque aqui temos dois problemas:
- Classes não podem ser estáticas.
- AS3 não suporta classes internas (acho isso um pouco chato, mas nada demais)
Além disso, precisamos mapear a classe PK em AS3 para que seja espelhada pela classe PK em Java.
Bem, a solução é simples: criar uma outra classe somente para representar a PK, e então mapeá-la corretamente, vamos ao código:
[Bindable]
[RemoteClass(alias=”com.mariojunior.sys.entidades.????????“)]
public class PK {
public var login : String;
public var cpf : String;
}
E na classe anterior (TesteCompositeId.as), tipar o atributo id com a classe PK:
public var id : PK;
Assim ficamos certo!
Agora, se você está me pergutando o porquê dos ???????? no lugar do nome da classe, já explico:
Como mapear uma classe interna do lado Java para uma classe simples em AS3?
Se você pensou em fazer :
(alias="com.mariojunior.sys.entidades.TesteCompositeId.PK“) saiba que o objeto nunca será tipado corretamente! Pois TesteCompositeId é uma classe e não um pacote, logo não pode ser separado por um “.” (ponto).
A resposta para esse tipo de mapeamento está nos arquivos compilados java (bytecode). Depois de gerar os arquivos .class (resultado da compilação dos arquivos .java), basta olhar nos nomes dos arquivos e descobrir que toda classe interna é gerada em um arquivo .class separado e, por convenção, os arquivos possui a seguinte nomenclatura:
ClassePai$ClasseInterna (reparem o sinal de cifrão no meio dos nomes).
Como os des/serializadores de objetos AS <=> Java trabalham com a manipulaçao de arquivos .class (bytecode), é preciso que o mapeamento de classes no lado AS3 sejam compatíveis com os nomes de arquivos .class, e com isso matamos a charada ao fazermos isso:
[Bindable]
[RemoteClass(alias=”com.mariojunior.sys.entidades.TesteCompositeId$PK“)]
public class PK {
public var login : String;
public var cpf : String;
}
Assim, ao se fazer o Debug no Flex, foi fácil perceber que os objetos foram serializados corretamente. Tanto de Java para Flex como de Flex para Java.
Bem, não há nenhuma grande novidade nessa informação, mas como pesquisei (google) e vi que não havia nada na web falando sobre chaves compostas entre java + flex, então resolvi compartilhar aqui com vocês.
Fica um abraço para galera.
Mário Júnior.
(de férias em Bonito-MS)