Arquivo para Junho, 2008

Curso on-line de Flex + Vídeos

Só repassando, daqui algumas semanas ocorrerá mais uma boa oportunidade para o desenvolvimento Flex, A e-Genial ta promovendo um curso on-line. O curso terá 18 aulas/horas e irá iniciar em Agosto, vamos fazer a matrícula:

Curso On-Line de Flex e Vídeos (streaming)

Você já pode baixar a grade, e ao termino será feito uma aplicação exemplo.

Introspecção Performance: Java x ActionScript3

Bom, hoje vou falar um pouco de um recurso muito importante no desenvolvimento de aplicações, que é o processo pelo qual se pode obter informações sobre a estrutura e comportamento do programa em tempo de execução, de uma maneira estreitamente dependente das características de abstração do código, ou seja, o programa tem a habilidade para “observar” e possivelmente modificar a estrutura e comportamento. Levando em consideração esse conceito vou mostrar como esse pode ser aplicado tanto na linguagem Java como em ActionScript3(AS3).

Em AS3 ultilizada no desenvolvimento Flex, reflexão é referenciada como object introspection (introspecção de Objeto). Existem duas formas de introspecção em AS3: Usando o laço for…in e a API introspecção. Em Java esta atividade é auxiliada pelo pacote java.lang.reflect. É bom deixar bem claro que a API introspecção em ActionScript não é tão avançada como em Java, porem permite você ler métodos, propriedades e invocar métodos de objetos em tempos de execução, tao bem quanto. Bom, chega de conversa e mãos a obra.

Para nosso exemplo vamos definir nossa classe que ira servir como base para fazer nossos testes, precisamos de duas classes uma em Java .class e outra em ActionScript .as:

Vamos por parte, primeiramente aprender como pegar a definição de classe e logo em seguida criar uma instancia da mesma, primeiro em Java:

...
Class classePessoa = Class.forName(”Pessoa”);
Object instance = classePessoa.newInstance();

Muito fácil não? Em ActionScript é mais fácil ainda, com a utilização do método getDefinitionByName() definido em flash.utils, onde contem diversas funções de manipulação de classes e objetos em tempo de execução, podemos criar uma definição de classe.

...
var classePessoa: Class = getDefinitionByName(”Pessoa”) as Class;
var instance = new classePessoa ();

Agora Vamos tentar recuperar a estrutura do Objeto Pessoa em tempo de execução, primeiro em Java:

Class classePessoa = Class.forName("Pessoa");
String str=”";
for (Field field : classePessoa.getDeclaredFields()) {
str+=”Variaveis: “+
field.getName()+
“=(”+field.getType().getSimpleName()+
“)”+
“\n”;
}
for (Method method : classePessoa.getDeclaredMethods()) {
str+=”Metodo: “+
method.getName()+
“=(”+method.getReturnType()+
“)”+
“\n”;
}
System.out.println(str);

Agora o processo em ActionScript, é feito com a utilização do for..in e a função describeType() que vem também no pacote flash.utils, recebe como parâmetro o objeto a ser introspectivo sobre um retorno descrito em XML do tipo do objeto e toda sua estrutura:

var ClassePessoa:Class = getDefinitionByName(”Pessoa”) as Class;
var classInfo:XML = describeType(classePessoa);
var str:String=”;
for each (var v:XML in classInfo..variable) {
str += “Variavel: ” + v.@name + “=” + ” (” + v.@type + “)\n”; }
for each (var v:XML in classInfo..method) {
str += “Metodo: ” + v.@name + “=” + ” (” + v.@returnType + “)\n”;
}
trace(str);

Abas imprimem o seguinte trace:

Variavel : nome=(String)

Variavel : nacionalidade=(String)

Variavel : idade=(String)

Metodo: falar=(void)

Metodo: ouvir=(void)

Outra coisa muito utilizada quando se utiliza reflexão e invocação de métodos por definição explicita de assinatura e parâmetro, em Java podemos criar um objeto Method a partir do getMethod() passando o nome do método como parâmetro, e em seguida utilizar seu método invoke() , passando o objeto, e parâmetro, no argumento:

...
Class classePessoa = Class.forName(”Pessoa”);
Method m = classePessoa.getMethod(”falar”, null);
m.invoke(classePessoa.newInstance(), null);

Em ActionScript é um pouco diferente, pois o tipo Object é uma classe dinâmica então não precisamos fazer o hard-code do método para que o metodo seja invocado, basta fazer instanciar com new e invocar explicitamente.

var classePessoa:Class = getDefinitionByName("Pessoa") as Class;
var instance:Object = new classePessoa()
instance["falar"](); //
ou instance.falar(); os dois sao equivalentes

Um outro método muito utilizado na introspecção AS3 é o getClassInfo(), no qual retorna um objeto com nome e propriedades do mesmo e o toString() que retorna uma espécie de “mapa” do Objeto, todos dois da classe ObjetoUtils.

...
var o:Object = ObjectUtil.getClassInfo(Pessoa);
trace(ObjectUtil.toString(o));

Bom, espero ter colaborado para um entendimento do que vem a ser introspecção de objetos e como se comporta em cada uma das linguagens, tanto em Java quando em AS3, podendo ser uma técnica poderosa no desenvolvimento de soluções um tanto quanto genéricas.

RIA com Java: BlazeDS e AMF

Ultimamente com o uso de ferramentas como Adobe Flex, Flash CS3 vem crescendo muito o numero de Rich Internet Applications (RIA), aplicações desktop com o Adobe AIR e aqueles que rodam em browser com Flash Player atuando como client-side, que por sua vez tem que de alguma forma se comunicar com um servidor para leitura e manipulação de dados, dados esses que geralmente são transportados via HTTP, mas a diferença em como esses dados são passados pelo protocolo pode comprometer drasticamente a performance, bem como a produtividade no desenvolvimento dos sistemas.

Muitas dessas aplicações utilizam-se de XML-sobre-HTTP para a comunicação cliente-servidor e acabam se dando conta da carga que sistema sofre com a serialização e deserialização dos XMLs que correm de um lado para outro.

O Action Message Format(AMF) se trata de um protocolo binário que pode ser usado sobre o HTTP ao invés do XML, evitando o tempo de parse entre a comunicação com o servidor. Nesse intuito, a Adobe tratou de lanca o tantas vezes renomeado LiveCycle Data Service, que prove as APIs necessárias para o server-side trabalhar com o AMF. Porém, não muito difundido pelos desenvolvedores por ser uma ferramenta liberada apenas para um único servidor(CPU) como demonstração. Em dezembro de 2007 a Adobe anuncio que a especificação AMF seria liberada e uma poção do LiveCycle Data Service seria open-source denominado BlazeDS que incluiria a implementação Java de AMF em servidores de aplicação como: Tomcat, JBoss, WebLogic, WebSphere, etc.

James Ward e Shashank Tiwari publicaram um artigo que explica em detalhes todo esse processo e a criação de um exemplo com back-end Java com o BlazeDS sobre o desenvolvimento Flex para um cliente RIA.

O artigo pode ser encontrado aqui postado na infoQ.

Comunicação entre componentes distribuídos por mensagens assíncronas com MDB

Após um tempo estudando Enterprise JavaBeans (EJB’s) para um projeto em que estava participando, percebi que estava confuso em relação ao conceito do tipo de ambiente(arquitetura) que o Beans de Sessão(Sessions Beans) são utilizados, pois cheguei a seguinte situação; queria que meu cliente acessasse por JNDI serviços registrados em outro servidor remoto e esses me devolviam informações(objetos) de um sistema heterogêneo , sendo que o mesmo estava em uma outra rede de uma filial da empresa, interligadas por uma WAN, ou seja, queria uma interação direta e síncrona entre meus componentes. Mas essa solução não é adequada por uma serie de condições adversas tais como: Link esta fora, servidor remoto parar no meio de uma transação, pico de luz e etc. A não ser que meu cliente espere longos 30min para receber apenas um timeout como resposta de uma conexão falha, nem mesmo quando pode voltar a estabelecer uma nova conexão com esse servidor. Então, como sair dessa situação? Depois de muito queimar a ‘cuca‘, encontramos a resposta na seguinte solução:

Invocar serviços através mensagens assíncronas, monitoradas por um tipo de especial de EJB denominado Message Driven Bean (MDB). Antes de começar explicar, vou explanar alguns conceitos importantes da solução apresentada:

  • MDB: São beans consumidores de JMS dentro do container JEE.
  • Queue: Filas de mensagens onde só vai ser consumida por um único MDB.
  • Producer: Produtor de mensagens para um Provider JMS.
  • Consumer: Recebe as mensagens de uma Queue que esta ‘escutando’.
  • Provider: Ambiente responsável pela organização e entrega de JMS.

O Conceito do funcionamento de uma JMS Application pode ser muito bem ilustrada na figura abaixo:

Isso nos trouxe mais confiança à comunicação entre nossos componentes distribuídos, pois não temos que nos preocupar em “busca coisas” em serviços de um servidor remoto, pois ele se encarrega de enviá-los através de um Producer construído somente para empilhar mensagens em uma Queue, escutada pelo nosso Consumer em um servidor local. O processando das mensagens é forma ordenada e durável, ou seja, somente sai da fila quando for realmente processada na ordem de chegada. Então a disposição de comunicação de nossos componentes ficou da seguinte forma:

A grande sacada foi como um MDB acessa uma Queue remota e fazer com que minhas mensagens sejam consistentes o bastante para garantirem a entrega no meu Consumer. Para isso foi feito algumas configurações no JBoss(no meu caso v.405), primeiramente foi adicionado mais um mbean(Managed Bean) em <$JBOSS_HOME/server/<your-configuration>/deploy/jms/jms-ds.xml, que defini um Provider remoto (que pode ser gerenciado via jmx-console). Lembrando esta alteração é no container em que o MDB esta rodando. Por padrão todos os MDBs acessam o DefaultJMSProvider também declarado no arquivo como Provider.

<mbean code=“org.jboss.jms.jndi.JMSProviderLoader”

name=“jboss.mq:service=JMSProviderLoader,name=RemoteJMSProvider,server=remotehost”>

<attribute name=“ProviderName”>RemoteJMSProvider</attribute>

<attribute name=“ProviderAdapterClass”>org.jboss.jms.jndi.JNDIProviderAdapter</attribute>

<!– The connection factory –>

<attribute name=“FactoryRef”>UIL2XAConnectionFactory</attribute>

<!– The queue connection factory –>

<attribute name=“QueueFactoryRef”>UIL2XAConnectionFactory</attribute>

<!– The topic factory –>

<attribute name=“TopicFactoryRef”>UIL2XAConnectionFactory</attribute>

<!– Connect to JNDI on the host “the-remote-host-name” port 1099–>

<attribute name=“Properties”>

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.factory.url.pkgs=org.jnp.interfaces

java.naming.provider.url=the-remote-host-name:1099

</attribute>

</mbean>

Troque “the-remote-host-name” para o IP do servidor que a Queue se encontra. E para fazer com que o MDB consuma de um provider remoto é mais fácil ainda:

@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName=”destinationType”, propertyValue=”javax.jms.Queue”),
@ActivationConfigProperty(propertyName=”destination”, propertyValue=”queue/testQueue”),
@ActivationConfigProperty(propertyName=”providerAdapterJNDI”, propertyValue=”java:/RemoteJMSProvider”)
})
public class MDB implements MessageListener
{

}

Agora para garantir com que as mensagens fossem persistentes. Definimos o envio do nosso Producer maneira persistente:


QueueSender sender = session.createSender(myQueue);
Message message = session.createTextMessage(”hello”);
int priority = 4;
sender.send(message, DeliveryMode.PERSISTENT, priority, 0);

Fazendo isto, garantimos a entrega da mensagem para o MDB pelo menos uma vez após uma exceção, se tornar a persistir, a mensagem é levada para o DLQ (ou mais conhecida como “lixão”), mas para que isso não ocorra você pode indicar que não quer tratamento de DLQ utilizando useDQL, desta forma, sempre ira tentar entregar a mensagem sem retirar da Queue enquanto houver exceção. Outra configuração que pode fazer também é numero de vezes que ele vai tentar entregar antes de mandar para DLQ o DLQMaxResent. A configuração do MDB pode ficar da seguinte forma:


@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName=”destinationType”, propertyValue=”javax.jms.Queue”),
@ActivationConfigProperty(propertyName=”destination”, propertyValue=”queue/testQueue”),
@ActivationConfigProperty(propertyName=”useDLQ”, propertyValue=”true”),
@ActivationConfigProperty(propertyName=”DLQMaxResent”, propertyValue=”100″),
@ActivationConfigProperty(propertyName=”providerAdapterJNDI”, propertyValue=”java:/RemoteJMSProvider”)
})
public class MDB implements MessageListener
{

}

Fiquei muito satisfeito com a facilidade de criação de aplicações desse tipo e ainda existe uma serie de configurações que podem ser feitas customizando a utilização de um MDB aumentando ainda mais a escalabilidade de sistemas, pois de uma solução JMS não se resume apenas apresentação unilateral de comunicação entre componentes, mais de uma interação substancial de processos definidos em uma margem de requisitos do funcionamento do sistema como um todo, tornando-o como uma ferramenta essencial na aplicação de grandes projetos.

Bom, vou ficando por aqui espero ter colaborado da alguma forma para o entendimento de aplicações JMS com MDB boa sorte e ate à próxima.