Blog do Urubatan
msgbartop
Desenvolvedor, Palestrante, Escritor, Nerd Assumido e Pai do Marcus :D
msgbarbottom

01 Feb 10 Flex For Kids – Aprendendo o que precisa e ajudando a quem precisa :D

Flex for Kids
Ok, o trocadilho do título do post foi muito ruim, mas eu tenho esperança de conseguir ser engraçado uma hora destas :D
Mas o Flex For Kids é um evento que tem dois objetivos principais:

  1. Ajudar a quem precisa, neste caso a Cotolengo
  2. Compartilhar conhecimento sobre Adobe Flex, e o pessoal que vai estar compartilhando conhecimento é muito fera!!

Quem organiza o evento é a e-Genial, que também organiza o Rails for Kids.
No Flex For Kids as doações recebidas vão direto para a Cotolengo, o que é bem legal, na prática você estara assistindo a excelentes palestras de grátis, a única coisa que é cobrada é que você faça um pouquinho de caridade :D
Bom, veja o que você vai poder aproveitar neste evento, e tudo isto sem sair de casa (ou do trabalho) já que o evento utiliza a excelente plataforma Treina Tom (Também da e-Genial)

  • Vicente Maciel Junior

    Palestra: Desenvolvimento Multi-touch com AIR 2.0
    Nesta palestra o participante irá conhecer a API Multi-touch introduzida na versão 2.0 do Adobe Integrated Runtime, que traz grande facilidade para o desenvolvimento de aplicações explorando este recurso.
    Público Alvo: Desenvolvedores, gerentes de projeto e entusiastas no desenvolvimento de soluções utilizando o AIR 2.0

  • Igor Musardo

    Palestra: Construa painéis administrativos em Flex integrados com ASP.NET MVC.
    Você verá na prática como integrar o Flex com a nova abordagem MVC do ASP.NET, indo além do CRUD.
    Público Alvo: Desenvolvedores Flex que utilizem ou querem utilizar o ASP.NET MVC como Back-End.

  • Mário Júnior

    Palestra: Swiz Framework: MVC Simples e Poderoso para projetos Flex/AIR
    Essa palestra visa mostrar a brutal diferença entre seus “concorrentes” e entender melhor a “conceptual constraint” que levou os autores do Swiz Framework a desenvolverem uma solução simples e flexível para projetos Flex/AIR, em relação aos demais frameworks conhecidos. (Cainrgorm, PureMVC, Mate, etc). Pré requisito: Conhecer “Dependency Injection” (DI) e “Inverse of Control” (IoC).
    Público Alvo: Desenvolvedores Flex.

  • Eberton Consolim

    Palestra: Flex e VOIP: Adicione essa tecnologia em suas aplicações
    Essa palestra tem por objetivo demonstrar a desenvolvedores Flex como implementar em suas aplicações funcionalidades de um discador VOIP, usando soluções open source.
    Público Alvo: Desenvolvedores Flex.

  • Daniel Lopes

    Palestra: Desktop com HTML, Javascript e Adobe AIR
    Conheça um novo mundo de possibilidades e tecnologias com Javascript e HTML para desktop e descubra como Adobe Air se integra a este ambiente, utilizando como case o PomoDo.
    Público Alvo: Desenvolvedores de qualquer linguagem.

  • Gabriela Trindade Perry

    Palestra: Estudo de caso: User Experience em um RIA
    Será debatido um estudo de caso onde implementamos um mecanismo de busca semântica através do design (!) A interface apenas pode ser viabilizada pela alta capacidade de componentização do Flex e porque entendemos o que o usuário precisava fazer com a interface.
    Público Alvo: Desenvolvedores Flex e designers de todos os credos e cores.

  • Eric Cavalcanti

    Palestra: Desmistificando o Cairngorm
    O Cairngorm é considerado por muitos como um framework com uma curva de aprendizado elevada. A finalidade desta palestra é desvendar o Cairngorm utilizando uma abordagem diferenciada, com o objetivo de facilitar o aprendizado do mesmo.
    Público Alvo: Desenvolvedores Flex.

  • Fábio Vedovelli

    Palestra: Introdução ao Mate: a importância de um framework MVC para Flex
    Muitos ainda não se convenceram da necessidade da utilização de um dos frameworks MVC (Model – View – Controller) presentes no mercado e esta palestra tem como objetivo mostrar a sua importância e indicar o framework escolhido pela RIA Labs.
    Público Alvo: Desenvolvedores Flex.

  • Igor Costa

    Palestra: Coloque uma interface Flex em seus projetos JEE
    Entenda como funciona a integração Adobe Flex com todos os serializadores disponíveis no mercado (BlazeDs, LivecycleDs,WebOrb for java,Pimento,Red5) para integração com seu back-end Java e crie novas ferramentas com recursos ímpar para seu negócio.
    Público Alvo: Desenvolvedores Java.

  • Beck Novaes

    Palestra: O Quarteto Fantástico: Flash 10.1, Flex 4, Flash Catalyst e Flash Builder
    Como as principais novidades da Plataforma Flash poderão impactar o desenvolvimento de Rich Internet Applications.
    Público Alvo: Pessoas interessadas no desenvolvimento de Rich Internet Applications.

Para se inscrever, ou só para ver mais alguns detalhes antes de se inscrever, é só acessar o site do evento.

Tags: , ,

26 Feb 09 Dicas e truques: Adobe Flex – MXML é para Layout, ActionScript para o código

Uma das melhores idéias do Flex, e o que o torna bastante produtivo na minha opinião é a existencia de uma “linguagem” para layout de telas, é o tal de MXML.
Claro que eu sei que é apenas XML, mas é XML com acesso direto as classes existentes e recem criadas, e uma mão na roda para separar o código do layout, facilitando bastante a escrita de código MVC compliant.
O maior problema da arquitetura básica do Flex é não ser “óbvio” como escrever o código de tratamento dos eventos gerados sem poluir o MXML com muitas tags “mx:Script” e muito código ActionScript.
Claro que existem alguns frameworks para o desenvolvimento de aplicações Flex como o Cairngorm e o PureMVC, mas algumas vezes estes frameworks mais complicam do que ajudam, e mesmo utilizando um deles, esta dica que vou apresentar agora de como simular o “code behind” do “.NET” em flex pode ser utilizada sem maiores problemas …

A idéia principal é separa o código ActionScript do código XML, como se fosse uma “partial class” do “.NET”, o Flex não suporta Partial Classes, mas suporta herança, e podemos tirar proveito disto …

Vou mostrar um exemplo bastante simplista aqui, apenas para que vocês peguem a idéia, vejam o código da tela abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
	<mx:Script>
		<![CDATA[
			import mx.controls.DataGrid;
			import mx.events.ListEvent;
			[Bindable]
			private var current : Object = new Object();
			[Bindable]
			private var all : Array = [];
			private function saveCurrent(nome : String, idade : Number) : void {
				var obj : Object = {nome : nome, idade : idade, id : all.length + 1};
				var temp : Array = all.slice(0,all.length);
				temp.push(obj);
				all  = temp;
				current = obj;
			}
			private function updateCurrent(nome : String, idade : Number) : void {
				current.nome = nome;
				current.idade = idade;
			}
			private function newCurrent() : void {
				current = new Object();
			}
			private function selectionChange(evt : ListEvent) : void {
				current = (evt.target as DataGrid).selectedItem;
			}
		]]>
	</mx:Script>
	<mx:Label fontSize="24" width="100%" textAlign="center" text="Cadastro de Pessoas"/>
	<mx:HBox width="100%">
		<mx:Label text="Nome:" width="100"/>
		<mx:TextInput id="currentNome" text="{current.nome}"/>
	</mx:HBox>
	<mx:HBox width="100%">
		<mx:Label text="Idade:" width="100"/>
		<mx:NumericStepper id="currentIdade" value="{current.idade}" minimum="5" maximum="150"/>
	</mx:HBox>
	<mx:HBox width="100%" horizontalAlign="center">
		<mx:Button label="Salvar" click="saveCurrent(currentNome.text,currentIdade.value)" enabled="{!current.id}"/>
		<mx:Button label="Novo" click="newCurrent()" enabled="{current.id}"/>
		<mx:Button label="Atualizar" click="updateCurrent(currentNome.text,currentIdade.value)" enabled="{current.id}"/>
	</mx:HBox>
	<mx:DataGrid width="100%" dataProvider="{all}" change="selectionChange(event)">
		<mx:columns>
			<mx:DataGridColumn headerText="Id" dataField="id"/>
			<mx:DataGridColumn headerText="Nome" dataField="nome"/>
			<mx:DataGridColumn headerText="Idade" dataField="idade"/>
		</mx:columns>
	</mx:DataGrid>
</mx:VBox>

Apenas para este bastatne simples, já temos quase metade do arquivo contendo ActionScript e metade contendo MXML.
Em um caso simples destes isto não chega a incomodar, mas quando o arquivo começa a crescer, isto atrapalha a leitura do código fonte, o que é bastante ruim. Então a minha sugestão, ou “dica” de como resolver isto, é separar o código ActionScript em um arquivo .as e manter apenas o layout no arquivo MXML, como pode ser visto no seguinte exemplo (considerando que o nome do arquivo mostrado acima seja telaexemplo.mxml)
Criar a classe “exemplo.TelaExemploBase” no diretório correspondente com o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package exemplo
{
	import mx.containers.VBox;
	import mx.controls.DataGrid;
	import mx.events.ListEvent;
 
	public class TelaExemploBase extends VBox
	{
		[Bindable]
		protected var current : Object = new Object();
		[Bindable]
		protected var all : Array = [];
		public function TelaExemploBase()
		{
			super();
		}
		protected function saveCurrent(nome : String, idade : Number) : void {
			var obj : Object = {nome : nome, idade : idade, id : all.length + 1};
			var temp : Array = all.slice(0,all.length);
			temp.push(obj);
			all  = temp;
			current = obj;
		}
		protected function updateCurrent(nome : String, idade : Number) : void {
			current.nome = nome;
			current.idade = idade;
		}
		protected function newCurrent() : void {
			current = new Object();
		}
		protected function selectionChange(evt : ListEvent) : void {
			current = (evt.target as DataGrid).selectedItem;
		}
 
	}
}

Alterar o arquivo MXML para o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<TelaExemploBase xmlns="exemplo.*" xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" >
	<mx:Label fontSize="24" width="100%" textAlign="center" text="Cadastro de Pessoas"/>
	<mx:HBox width="100%">
		<mx:Label text="Nome:" width="100"/>
		<mx:TextInput id="currentNome" text="{current.nome}"/>
	</mx:HBox>
	<mx:HBox width="100%">
		<mx:Label text="Idade:" width="100"/>
		<mx:NumericStepper id="currentIdade" value="{current.idade}" minimum="5" maximum="150"/>
	</mx:HBox>
	<mx:HBox width="100%" horizontalAlign="center">
		<mx:Button label="Salvar" click="saveCurrent(currentNome.text,currentIdade.value)" enabled="{!current.id}"/>
		<mx:Button label="Novo" click="newCurrent()" enabled="{current.id}"/>
		<mx:Button label="Atualizar" click="updateCurrent(currentNome.text,currentIdade.value)" enabled="{current.id}"/>
	</mx:HBox>
	<mx:DataGrid width="100%" dataProvider="{all}" change="selectionChange(event)">
		<mx:columns>
			<mx:DataGridColumn headerText="Id" dataField="id"/>
			<mx:DataGridColumn headerText="Nome" dataField="nome"/>
			<mx:DataGridColumn headerText="Idade" dataField="idade"/>
		</mx:columns>
	</mx:DataGrid>
</TelaExemploBase>

A idéia básica é utilizar o MXML para extender a classe ActionScript que contem o código, a diferença é que tudo o que deve ser acessado do MXML na classe criada não pode ser privado, tem que ser no mínimo protected (o que foi utilizado no exemplo).
Outro truque é definir o “xmlns” para o pacote da classe que vai ser extendida como pode ser visto na linha 2.
E para testar isto é necessária uma “aplicação flex”, eu utilizei apenas o código abaixo para o projeto de testes:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*">
	<local:telaexemplo width="100%" height="100%"/>
</mx:Application>

Mas claro que você pode fazer algo mais elaborado :D

Espero que esta dica ajude alguem, ja que eu tive bastante trabalho reorganizando código depois que descobri que isto era muito melhor do que colocar tudo no MXML logo que comecei a trabalhar com Flex.

Tags: , ,

06 Feb 09 Dicas e truques: Adobe Flex – Evitando acesso a objetos nulos

Uma forma possível de se iterar pelo conteúdo de um array em Flex é:

1
2
3
4
5
private function iterarSobreArray(arr : Array) : void {
  for(var i : int = 0; i < arr.length; i++){
    fazerAlgumaCoisaCom(arr[i]);
  }
}

Mas esta forma vai causar problemas caso o array seja nulo, para evitar isto basta utilizar a forma abaixo.

1
2
3
4
5
private function iterarSobreArray(arr : Array) : void {
  for each(var o : Object in arr){
    fazerAlgumaCoisaCom(o);
  }
}

Desta forma temos menos variáveis declaradas, e não corremos risco de tentar ler o tamanho de um “null” na linha 2 do primeiro exemplo …

Tags: , ,

29 Nov 07 Java + Flex = Aplicação bonita e rápida e backend confiável!

Vocês provavelmente ja ouviram falar do Adobe Flex.
O Flex é um SDK para desenvolver aplicações Ricas para Internet, estas aplicações irão rodar no Flash Player que ja esta presente em quase todos os browsers que acessam a internet hoje.
Uma aplicação Flex, gera um arquivo SWF e este arquivo se comunica com um servidor, e este servidor pode ser um Adobe Lifecycle Data Server, mas vocês também podem utilizar Java e Open Source :D

Estes 2/3 exemplos rodam sem nenhum software pago, as únicas coisas necessárias são:
Flex SDK – O Flex SDK é gratuito e a versão 3 vai ser Open Source também.
Um Servlet Container – Eu estou utilizando o Tomcat
– Para o primeiro exemplo é só isto :D
E para os outros dois exemplos, também será necessário baixar os seguintes softwares:
OpenAMF – Uma implementação do protocolo AMF0 (Flex Remoting) em Java
RemoteObjectAMF0 – Uma implementação da tag RemoteObject que suporta a versão 0 do AMF (OpenAMF ainda não suporta a versão 3 e o Flex 2 por padrão utiliza a versão 3)

Então, comecemos criando uma aplicação Web Java na sua IDE favorita, crie um servlet de nome TestServlet, eu vou utilizar JAXB para renderizar XML, mas vocês podem utilizar qualquer outra coisa, se você quiser utilizar JAXB também, o schema que eu utilizei para este exemplo esta abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/example" xmlns:tns="http://www.example.com/example" elementFormDefault="qualified">
    <element name="TestSVo" type="tns:TestList"></element>
        <complexType name="TestSVoType">
    	<attribute name="id" type="int"></attribute>
    	<attribute name="name" type="string"></attribute>
    	<attribute name="other" type="string"></attribute>
    </complexType>
    <complexType name="TestList">
    	<sequence minOccurs="1" maxOccurs="unbounded">
    		<element name="all" type="tns:TestSVoType"></element>
    	</sequence>
    </complexType>
</schema>

Este Schema é para um XML parecido com este:

1
2
3
4
5
<TestSVo>
<all id="0" name="foo" other="bar"/>
<all id="1" name="foo1" other="bar1"/>
...
</TestSVo>

Agora é preciso gerar os stubs para o JaxB ou utilize qualquer outra ferramenta que gere um XML parecido com este.
Generate the stubs for the XML generation using JaxB or use any other tool to generate a XML with this schema.

Como em qualquer outra aplicação Java WEB, eu vou começar poluindo meu código com XML (o web.xml neste caso):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd ">
	<servlet>
		<servlet-name>testServlet</servlet-name>
		<servlet-class>....servlet.TestServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>AdvancedGateway</servlet-name>
		<servlet-class>org.openamf.AdvancedGateway</servlet-class>
		<init-param>
			<description>
				Location of the OpenAMF config file.
			</description>
			<param-name>OPENAMF_CONFIG</param-name>
			<param-value>/WEB-INF/openamf-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>AdvancedGateway</servlet-name>
		<url-pattern>/gateway2</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>testServlet</servlet-name>
		<url-pattern>/TestServlet</url-pattern>
	</servlet-mapping>
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
	<welcome-file-list>
		<welcome-file>teste.html</welcome-file>
	</welcome-file-list>
</web-app>

Para o primeiro exemplo, apenas o TestServlet é utilizado, para os outros o AdvancedGateway que será utilizado …

Agora vamos começar codificando o Servlet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
 
/**
 * Servlet implementation class for Servlet: TestServlet
 * 
 */
public class TestServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet
{
	static final long serialVersionUID = 1L;
	private JAXBContext jc;
	private Marshaller marc;
	private Unmarshaller unmarc;
	private ObjectFactory factory;
 
	public TestServlet()
	{
		super();
		factory = new ObjectFactory();
		try {
			jc = JAXBContext.newInstance("....servlet");
			marc = jc.createMarshaller();
			unmarc = jc.createUnmarshaller();
		} catch (JAXBException e) {
			e.printStackTrace();
		}
 
	}
 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		float v = Float.parseFloat(request.getParameter("v"));
		float v1 = Float.parseFloat(request.getParameter("v1"));
		response.getWriter().print(v * v1);
	}
 
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
		IOException
	{
		System.out.println("List called");
		TestList res = new TestList();
		for(int i=0;i<40;i++){
			res.getAll().add(new TestSVoType(i,"Téste ã " + i));
		}
		JAXBElement<TestList> elem = factory.createTestSVo(res);
		System.out.println(elem.toString());
		try {
			marc.marshal(elem, response.getWriter());
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

O método doGet deste servlet é uma calculadora, ele apenas multiplica dois parâmetros recebidos e imprime o resultado.
Já o doPost imprime um XML como o mostrado anteriormente, o conteúdo é praticamente estático, mas isto é só um exemplo :D

Agora vamos começar a brincar com Flex …
Crie um arquivo de nome xmltest.mxml na pasta raiz da sua aplicação WEB.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	 layout="vertical"	backgroundColor="#F4F4F4">
	 <mx:HTTPService id="calc" method="GET" url="http://localhost:8080/teste/TestServlet" >
	 </mx:HTTPService>
	 <mx:HTTPService id="list" method="POST" url="http://localhost:8080/teste/TestServlet" >
	 </mx:HTTPService>
	<mx:Script>
		<![CDATA[
			import mx.controls.DataGrid;
            import mx.controls.Alert;
        ]]>
	</mx:Script>
	<mx:Panel width="80%" height="531" title="Teste">
		<mx:Label width="100%" color="blue"
			text="Type two numbers and press calculate." />
		<mx:TextInput id="v1" text="3" />
		<mx:TextInput id="v2" text="5" />
		<mx:Label id="lbl"  text="{calc.lastResult}"/>
		<mx:Button label="Calculate" click="calc.send({v:v1.text,v1:v2.text});" />
		<mx:DataGrid dataProvider="{list.lastResult.TestSVo.all}" width="100%" height="195" change="Alert.show(DataGrid(event.currentTarget).selectedItem.other)">
			<mx:columns>
				<mx:DataGridColumn headerText="Id" dataField="id" />
				<mx:DataGridColumn headerText="Nome" dataField="name" />
			</mx:columns>
		</mx:DataGrid>
		<mx:Button label="List" click="list.send({v:v1.text,v1:v2.text})" />
	</mx:Panel>
</mx:Application>

A interface com o código java neste exemplo é feita via HTTP padrão, utilizando as tags mx:HTTPService, a primeira faz um GET para a URL e por tanto chama a nossa calculadora, a segunda faz um post, buscando o XML do exemplo Java …

Quando o primeiro botão (Calculate) é clicado, o primeiro serviço é chamado [calc.send(parameters)] e o texto na primeira label é atualizado de acordo com o binding configurado.
Quando o segundo botão é clicadl (List) o segundo serviço é chamado [list.send(params)] e os dados da grid serão atualizados automaticamente.

É só isto :D
Dica: se você utilizar list.send sem parâmetros, a tag HTTPservice dispara um GET e não um POST, ou pelo menos foi o que aconteceu com o Flex 2, eu não testei com FLex 3 ainda …

Esta abordagem é bastante simples e não necessita de muito código, mas não parece muito com OOP …


E o Flex tem um suporte excelente a Remoting, então, o que vocês acham de criar um POJO em Java e usa-lo como um objeto remoto no código Flex?
Gostou da idéia?

Então vamos escrever a classe TestService com as duas mesmas operações (calc e list)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.ArrayList;
import java.util.List;
 
public class TestService
{
	public float calc(float v, float v1){
		System.out.format("%f X %f\n", v, v1);
		return v * v1;
	}
 
	public List<TestVo> list(){
		System.out.println("List called");
		ArrayList<TestVo> res = new ArrayList<TestVo>();
		for(int i=0;i<40;i++){
			res.add(new TestVo(i,"Testé  ã " + i));
		}
		return res;
	}
}

E agora não sera necessária toda aquela parafernalha XML (bom, pelo menos a parte de código que criamos antes), podemos utilizar um Value Object simples :D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class TestVo
{
	private String name;
	private int id;
	public TestVo(int id, String name)
	{
		this.id = id;
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
	public int getId()
	{
		return id;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public void setId(int id)
	{
		this.id = id;
	}
}

Para usar este serviço a partir do Flash, nos precisamos configurar o OpenAMF usando o arquivo WEB-INF/openamf-config.xml, o nome e local onde este arquivo se encontra foram configurados no web.xml anteriormente.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<config>
	<amf-serializer>
			<force-lower-case-keys>false</force-lower-case-keys>
	</amf-serializer>
	<invoker>
		<name>Java</name>
		<class>org.openamf.invoker.JavaServiceInvoker</class>
	</invoker>
	<custom-class-mapping>
		<java-class>....TestVo</java-class>
		<custom-class>TestVo</custom-class>
	</custom-class-mapping>
	<service>
		<name>TestService</name>
		<service-location>....TestService</service-location>
		<invoker-ref>Java</invoker-ref>
		<method>
			<name>calc</name>
			<parameter>
				<type>*</type>
			</parameter>
		</method>
		<method>
			<name>list</name>
			<parameter>
				<type>*</type>
			</parameter>
		</method>
	</service>
</config>

Eu limpei quase todo o código do arquivo, removi tudo o que não seria utilizado neste exemplo :D
O OpenAMF tem diversas opções de configuração, é possível chamar diretamente EJBs, WebServices, qualquer classe Java, objetos JMX e Beans do Spring Framework a partir do seu código Flex sem problema algum …

Não é possível utilizar a tag padrão mx:RemoteObject para chamar este serviço, por que o OpenAMF não suporta o AMF3, e eu não consegui encontrar uma forma de configurar a versão do AMF para a tag mx:RemoteObject …

Então, para o primeiro exemplo, vamos utilizar apenas uma instância da classe NetConnection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="vertical"
	backgroundColor="#F4F4F4"
	initialize="init()">
	<mx:Script>
		<![CDATA[
            import mx.controls.Alert;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;   
            [Bindable]
            public var lista:ArrayCollection; 
            public var nc : NetConnection;
 
            function init() : void{
            	nc = new NetConnection();
            	nc.objectEncoding = ObjectEncoding.AMF3;
            	nc.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
            	nc.connect("http://localhost:8080/teste/gateway2");
            }
            function netStatus(event : NetStatusEvent) : void {
            	Alert.show(event.info.code);
            }
            function onRetornaLista(event):void{
            	var e : Array = event;
            	lista = new ArrayCollection(e);
            }       
            function onRetornaCalc(event):void{
            	lbl.text = String(event);
            }
            function calc(v1 : Number, v2 : Number) : void {
            	var r : Responder = new Responder(onRetornaCalc);
            	nc.call("TestService.calc",r,v1,v2);
            }
            function list() : void{
            	var r : Responder = new Responder(onRetornaLista);
            	nc.call("TestService.list",r);
            }
 
        ]]>
	</mx:Script>
	<mx:Panel width="80%" height="531" title="Teste">
		<mx:Label width="100%" color="blue"
			text="Type two numbers and press calculate." />
		<mx:TextInput id="v1" text="3" />
		<mx:TextInput id="v2" text="5" />
		<mx:Label id="lbl"  />
		<mx:Button label="Calculate" click="calc(Number(v1.text),Number(v2.text))" />
		<mx:DataGrid dataProvider="{lista}" width="100%" height="195">
			<mx:columns>
				<mx:DataGridColumn headerText="Id" dataField="id" />
				<mx:DataGridColumn headerText="Nome" dataField="name" />
			</mx:columns>
		</mx:DataGrid>
		<mx:Button label="List" click="list()" />
	</mx:Panel>
</mx:Application>

O método init() apenas criou e configurou a instância NetConnection da aplicação (nc).
Os botões realizam as mesmas operações do exemplo anterior, mas agora é utilizada a sintaxe Classe.metodo, por exemplo TestService.calc para chamar o método de um serviço via NetConnection.

A novidade aqui é que precisamos dos Responders para tratar os retornos de cada método.
Eu acho esta abordagem um pouco melhor, mas ainda tenho esta sensação de estar fazendo alguma coisa errada …
Então, procurando pela internet eu encontrei a biblioteca RemoteObjectAMF0
Esta é uma pequena biblioteca escrita em ActionScript que cria uma tag nova para chamar serviços AMF0 a partir de uma aplicação Flex2.
Para utiliza-la basta fazer estas pequenas alterações na aplicação anterior …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:renaun="com.renaun.rpc.*" layout="vertical"
	backgroundColor="#F4F4F4">
	<mx:Script>
		<![CDATA[
            import mx.controls.Alert;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;   
            [Bindable]
            public var lista:ArrayCollection; 
 
            NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0;
 
            function onRetornaLista(event:ResultEvent):void{
            	lista = ArrayCollection(event.result);
            }       
            function onRetornaCalc(event:ResultEvent):void{
            	lbl.text = String(event.result);
            }
        ]]>
	</mx:Script>
	<renaun:RemoteObjectAMF0
		endpoint="http://localhost:8080/teste/gateway2" id="TST"
		source="....TestService" showBusyCursor="true"
		makeObjectsBindable="true"
		fault="Alert.show(String(event.fault)), 'Error'">
		<renaun:methods>
			<renaun:method name="list" result="onRetornaLista(event)"></renaun:method>
			<renaun:method name="calc" result="onRetornaCalc(event)"></renaun:method>
		</renaun:methods>
	</renaun:RemoteObjectAMF0>
	<mx:Panel width="80%" height="531" title="Teste">
		<mx:Label width="100%" color="blue"
			text="Type two numbers and press calculate." />
		<mx:TextInput id="v1" text="3" />
		<mx:TextInput id="v2" text="5" />
		<mx:Label id="lbl"  />
		<mx:Button label="Calculate" click="TST.calc(Number(v1.text),Number(v2.text))" />
		<mx:DataGrid dataProvider="{lista}" width="100%" height="195">
			<mx:columns>
				<mx:DataGridColumn headerText="Id" dataField="id" />
				<mx:DataGridColumn headerText="Nome" dataField="name" />
			</mx:columns>
		</mx:DataGrid>
		<mx:Button label="List" click="TST.list()" />
	</mx:Panel>
</mx:Application>

Ainda não ficou perfeito, esta quase tão bom quanto com as tags de remoting nativas, mas não tão bom quanto, mesmo assim é a melhor possibilidade deste post :D
Eu não gosto da idéia de precisar informar o nome completo da classe Java no flex para chamar um serviço Java, acho que a minha solução final vai ser algo parecido com um proxy usando uma NetConnection como backend, mas esta ja esta suficiente por enquanto :D

Eu espero que este post ajude algum de vocês, eu passei dois dias procurando uma solução aceitável para este tipo de comunicação, ja que infelizmente no meu projeto atual, o Lifecycle Data Services não á uma opção viável …

PS.: para compilar os arquivos .mxml você pode utilizar o comando mxmlc do Flex 2 SDK
PS2.: Você precisara corrigir as URLs para o caminho completo da aplicação
PS3.: os é e ã não são problemas com a codificação da página, eu adicionei eles propositalmente para ver como seria tratado o encoding diferente no flex e no java, e tudo correu muito bem :D

Tags: , , , , ,

06 Nov 07 Flex2/ActionScript 3 – Transformando objetos em XML

Trabalhando com Flex com um backend em Java, cheguei a conclusão que a melhor alternativa para o projeto seria simplesmente fazer posts de dados do flex para o java e receber XML de volta (o Flex trabalha muito bem com XML).
Mas tem um problema nisto, passar um ou dois valores desta forma é bastante fácil, mas quando eu precisava passar objetos complexos era muito chato passar milhares de parâmetros para uma URL, então tive a idéia de mandar também XML de volta para o Java …
desta forma, o único problema que continuou foi eu precisar escrever manualmente o XML para cada post, sendo que na maioria das vezes eu ja tinha um objeto Flex …
Solucionei isto com uma pequena função utilitária que transforma qualquer objeto em XML, tentei procurar alguma coisa na API padrão, mas não encontrei nada, então escrevi isto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package teste
{
	import mx.utils.ObjectUtil;
 
	public class Utils
	{
		public static function objectToXml(obj : Object, name : String) : XML{
			var result : XML;
			var info:Object = ObjectUtil.getClassInfo(obj);
			if(name==null)
				name = info.name;
			result = new XML("<" + name + "></"+ name + ">");
			for each (var qn : QName in info.properties){
				var val : Object = obj[qn.toString()];
				if(ObjectUtil.isSimple(val))
					result[qn.toString()] = val;
				else
					result.appendChild(objectToXml(val,qn.toString()));
			}
			return result;			
		}
	}
}

Para usar também é bem fácil:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="appInit()">
<mx:Script>
	<![CDATA[
		import teste.Utils;
		import mx.utils.ObjectUtil;
		import mx.controls.Alert;
		public function appInit() : void {
			var obj : Object = {name:'teste',address:{street:'rua',number:20}};
			Alert.show(Utils.objectToXml(obj,'teste').toXMLString());
		}
	]]>
</mx:Script>
 
</mx:Application>

e o XML gerado no exemplo é este:

1
2
3
4
5
6
7
<teste>
  <address>
    <number>20</number>
    <street>rua</street>
  </address>
  <name>teste</name>
</teste>

Bom, não sei se esta é a melhor forma de se trabalhar, mas até que gostei da solução :D

Tags: , , ,