Parte 1Parte 2Parte 3Parte 4.1Parte 4.2

Nesta parte do tutorial, vamos fazer um exemplo um pouquinho mais complicado que o anterior. Iremos criar quatro serviços, um para cada operação matemática. Cada um dos serviços vai receber dois números como parâmetro e vai retornar o valor da operação. Iremos também montar a interface gráfica para utilizar estes serviços e todo o mapeamento da parte em Flex para o backend em Java. Então vamos lá!

Antes de iniciarmos a implementação dos serviços, primeiro vamos configurar nossa aplicação para que quando executada, a página do swf seja aberta automaticamente. Não podemos configurar para abrir o HTML diretamente via web.xml, então teremos que usar o nosso index.jsp para fazer o redirecionamento. Para isso, basta adicionar um <meta http-equiv=”Refresh” …/> no nosso index.jsp. Segue então o código completo do index.jsp, onde já removi o “Hello World!” e o título da página. Esta página vai servir apenas como ponto de entrada da aplicação.

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta http-equiv="Refresh" content="0; url=swf/IntegracaoFlexJavaGUI.html">
    </head>
    <body>
    </body>
</html>

Com o index.jsp atualizado, teste novamente sua aplicação. Agora a página do swf vai ser carregada automaticamente. Vamos aos serviços.

No NetBeans, com o projeto aberto, vamos no pacote “servicos” que criamos na parte anterior e vamos criar uma nova classe, com o nome de “ServicosCalculadora”. Nesta classe iremos implementar quatro métodos: double somar(double n1, double n2), double subtrair(double n1, double n2), double multiplicar(double n1, double n2) e double dividir( double n1, double n2). A implementação de cada método é muito simples. Eles irão retornar o resultado da operação denotada pelo nome do método sob os operandos. Segue então a implementação da classe ServicosCalculadora:

servicos.ServicosCalculadora.java

package servicos;

/**
 * Serviços de cálculo.
 *
 * @author David Buzatto
 */
public class ServicosCalculadora {

    public double somar( double n1, double n2 ) {
        return n1 + n2;
    }

    public double subtrair( double n1, double n2 ) {
        return n1 - n2;
    }

    public double multiplicar( double n1, double n2 ) {
        return n1 * n2;
    }

    public double dividir( double n1, double n2 ) {
        return n1 / n2;
    }

}

Note que não estamos nos preocupando com divisão por zero. Legal! O segundo passo agora é editar o remoting-config.xml informar tanto ao BlazeDS quanto ao compilador do Flex que a classe ServicosCalculadora é uma classe que contém serviços. Abra então o remoting-config.xml e adicione mais um destination que agora aponta para a nova classe e de um id para ele. Segue o remoting-config.xml completo:

remoting-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>

    <default-channels>
        <channel ref="my-amf"/>
    </default-channels>

    <destination id="testeServicos">
        <properties>
            <source>servicos.ServicosTeste</source>
        </properties>
    </destination>

    <destination id="servicosCalculadora">
        <properties>
            <source>servicos.ServicosCalculadora</source>
        </properties>
    </destination>

</service>

Ótimo, a parte do lado Java está pronta. Simples não é? Vamos para o Flash Builder agora. Vamos reorganizar nossa interface, pois vamos utilizá-la a mesma tela para todos os exemplos. Na interface Design, vamos criar um painel (categoria Layout da paleta de componentes) e arrastar o botão do primeiro exemplo para dentro dele. Criaremos outro painel então para conter os componentes do exemplo que estamos implementando agora. Note que do lado direito da interface do Flash Builder existe a aba de propriedades do componente que está selecionado no momento. Lá você pode alterar as propriedades do componente que está editando. Veja como ficou:

 

Figura 1

Interface do exemplo de Calculadora

 

Temos então os campos para os números que serão calculados, alguns radios para as operações, um botão para chamar o serviço de cálculo e um campo para o resultado. Para mentermos um padrão, segue o código do mxml que temos até o momento. Já defini os ids dos componentes.

IntegracaoFlexJavaGUI.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;

			private function botaoExecutarClick( event: Event ): void {
				servicos.imprimirMensagem();
			}

			private function imprimirMensagemFault( event: FaultEvent ): void {
				Alert.show( "Ocorreu um erro...", "ERRO" );
			}

			private function imprimirMensagemResult( event: ResultEvent ): void {
				Alert.show( "Serviço executado com sucesso!", "Mensagem" );
			}

		]]>
	</fx:Script>

	<fx:Declarations>

		<s:RemoteObject
			id="servicos"
			destination="testeServicos"
			showBusyCursor="true">

			<s:method
				name="imprimirMensagem"
				fault="imprimirMensagemFault(event)"
				result="imprimirMensagemResult(event)"/>

		</s:RemoteObject>
		<s:RadioButtonGroup id="grupoOperacoes"/>

	</fx:Declarations>

	<s:Panel x="11" y="10" width="250" height="200" title="Testes Serviços (ServicosTeste.java)">
		<s:Button x="15" y="13" label="Executar" click="botaoExecutarClick(event)"/>
	</s:Panel>
	<s:Panel x="269" y="10" width="250" height="241" title="Calculadora (ServicosCalculadora.java)">
		<s:Label x="12" y="20" text="Número 1:"/>
		<s:Label x="13" y="50" text="Número 2:"/>
		<s:TextInput x="79" y="14" width="64" id="campoN1"/>
		<s:TextInput x="80" y="44" width="63" id="campoN2"/>
		<s:Label x="13" y="102" text="Operação:"/>
		<s:RadioButton x="77" y="84" label="+" groupName="grupoOperacoes" selected="true" id="radioSomar"/>
		<s:RadioButton x="111" y="84" label="-" groupName="grupoOperacoes" id="radioSubtrair"/>
		<s:RadioButton x="77" y="110" label="*" groupName="grupoOperacoes" id="radioMultiplicar"/>
		<s:RadioButton x="111" y="110" label="/" groupName="grupoOperacoes" id="radioDividir"/>
		<s:Label x="10" y="184" text="Resultado:"/>
		<s:TextInput x="79" y="176" id="campoResultado" width="159"/>
		<s:Button x="10" y="141" label="Calcular!" width="228"/>
	</s:Panel>
</s:Application>

Da mesma forma que fizemos para o primeiro exemplo, precisamos agora definir o <s:RemoteObject> que vai apontar para a nossa classe e mapear todos os métodos. Como exercício, logo abaixo do <s:RemoteObject> do exemplo anterior, declare no novo <s:RemoteObject> e os quatro métodos. Lembre-se que o destination tem que ser o mesmo que declaramos no remoting-config.xml (servicosCalculadora). Para os eventos fault e result de cada um dos métodos, aponte para as funções calculadoraFault(event) e calculadoraResult(event) respectivamente. Vamos utilizar os mesmo tratadores de eventos para cada um dos métodos. Em cada um deles, coloque um Alert, indicando um erro ou que o cálculo foi executado. Terminou? Veja se ficou parecido com isso aqui:

IntegracaoFlexJavaGUI.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;

			private function botaoExecutarClick( event: Event ): void {
				servicos.imprimirMensagem();
			}

			private function imprimirMensagemFault( event: FaultEvent ): void {
				Alert.show( "Ocorreu um erro...", "ERRO" );
			}

			private function imprimirMensagemResult( event: ResultEvent ): void {
				Alert.show( "Serviço executado com sucesso!", "Mensagem" );
			}

			private function calculadoraFault( event: FaultEvent ): void {
				Alert.show( "Ocorreu um erro...", "ERRO" );
			}

			private function calculadoraResult( event: ResultEvent ): void {
				Alert.show( "Serviço executado com sucesso!", "Mensagem" );
			}

		]]>
	</fx:Script>

	<fx:Declarations>

		<s:RemoteObject
			id="servicos"
			destination="testeServicos"
			showBusyCursor="true">

			<s:method
				name="imprimirMensagem"
				fault="imprimirMensagemFault(event)"
				result="imprimirMensagemResult(event)"/>

		</s:RemoteObject>

		<s:RemoteObject
			id="calculadora"
			destination="servicosCalculadora"
			showBusyCursor="true">

			<s:method
				name="somar"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

			<s:method
				name="subtrair"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

			<s:method
				name="multiplicar"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

			<s:method
				name="dividir"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

		</s:RemoteObject>

		<s:RadioButtonGroup id="grupoOperacoes"/>

	</fx:Declarations>

	<s:Panel x="11" y="10" width="250" height="200" title="Testes Serviços (ServicosTeste.java)">
		<s:Button x="15" y="13" label="Executar" click="botaoExecutarClick(event)"/>
	</s:Panel>
	<s:Panel x="269" y="10" width="250" height="241" title="Calculadora (ServicosCalculadora.java)">
		<s:Label x="12" y="20" text="Número 1:"/>
		<s:Label x="13" y="50" text="Número 2:"/>
		<s:TextInput x="79" y="14" width="64" id="campoN1"/>
		<s:TextInput x="80" y="44" width="63" id="campoN2"/>
		<s:Label x="13" y="102" text="Operação:"/>
		<s:RadioButton x="77" y="84" label="+" groupName="grupoOperacoes" selected="true" id="radioSomar"/>
		<s:RadioButton x="111" y="84" label="-" groupName="grupoOperacoes" id="radioSubtrair"/>
		<s:RadioButton x="77" y="110" label="*" groupName="grupoOperacoes" id="radioMultiplicar"/>
		<s:RadioButton x="111" y="110" label="/" groupName="grupoOperacoes" id="radioDividir"/>
		<s:Label x="10" y="184" text="Resultado:"/>
		<s:TextInput x="79" y="176" id="campoResultado" width="159"/>
		<s:Button x="10" y="141" label="Calcular!" width="228"/>
	</s:Panel>
</s:Application>

Certo, configuramos nosso objeto remoto, mapeamos os métodos, registramos os eventos de erro (FaultEvent) e de execução bem sucedida (ResultEvent). Falta agora fazer funcionar. Para isso iremos criar um método para tratar o evento click do botão, e neste método verificar qual a operação a ser executada e chamar o método correspondente do serviço. Para poupar espaço, vou colocar apenas o código do método que trata o evento click e como o código do botão “Calcular!” deve ficar.

private function botaoCalcularClick( event: Event ): void {

	/*
	 * Declaração de duas variáveis do tipo Number que recebem
	 * a conversão em número do texto dos seus respectivos campos.
	 * Note que não há nenhuma validação.
	 */
	var n1: Number = Number( campoN1.text );
	var n2: Number = Number( campoN2.text );

	/*
	 * grupoOperacoes é um RadioButtonGrupo que está relacionado
	 * aos quatro radios criados. O propriedade selectedValue retorna
	 * o valor da propriedade label do radio selecionado no momento.
	 * Perceba que em ActionScript, nós podemos fazer switch com Strings
	 * diferentemente do Java (até a versão 6.0) onde isso não é suportado
	 */
	switch ( grupoOperacoes.selectedValue.toString() ) {

		case "+":
			calculadora.somar( n1, n2 );
			break;

		case "-":
			calculadora.subtrair( n1, n2 );
			break;

		case "*":
			calculadora.multiplicar( n1, n2 );
			break;

		case "/":
			calculadora.dividir( n1, n2 );
			break;

	}

}

Código do botão “Calcular!”:

<s:Button x="10" y="141" label="Calcular!" width="228" click="botaoCalcularClick(event)"/>

Teste e veja se está ocorrendo algum erro. Se estive, corrija. Perceba que ainda não tratamos o resultado retornado. Isso será realizado no método que trata o ResultEvent, pois só quando ele é executado significa que o método remoto (nosso serviço) foi executado corretamente. Então vamos fazer a modificação necessária no método calculadoraResult para que o resultado do serviço seja colocado no campo de resultado. Segue então o método alterado:

private function calculadoraResult( event: ResultEvent ): void {

	/*
	 * a propriedade result do objeto event (do tipo ResultEvent)
	 * contém o valor de retorno do método remoto que foi executado
	 * essa propriedade é do tipo Object, então caso haja a necessidade
	 * de se converter o valor retornado, é necessário saber que tipo que está
	 * sendo retornado.
	 *
	 * Como os números no ActionScript também são objetos, aqui
	 * não é feita nenhuma conversão, só chamando o método toString()
	 * do valor, retornando assim a representação em String do número retornado.
	 */
	var valor: Object = event.result;
	campoResultado.text = valor.toString();

	Alert.show( "Serviço executado com sucesso!", "Mensagem" );

}

Teste para verificar se está funcionando. Caso após executar o projeto do NetBeans o aplicativo swf não tiver sido atualizado, segure a tecla Shift e clique no botão atualizar do seu navegador. Assim ele é forçado a recarregar do “zero” o swf. Não se esqueça de sempre salvar o projeto no Flash Builder para que o projeto seja recompilado. Segue então o código mxml final deste exemplo:

IntegracaoFlexJavaGUI.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;

			private function botaoExecutarClick( event: Event ): void {
				servicos.imprimirMensagem();
			}

			private function imprimirMensagemFault( event: FaultEvent ): void {
				Alert.show( "Ocorreu um erro...", "ERRO" );
			}

			private function imprimirMensagemResult( event: ResultEvent ): void {
				Alert.show( "Serviço executado com sucesso!", "Mensagem" );
			}

			private function calculadoraFault( event: FaultEvent ): void {
				Alert.show( "Ocorreu um erro...", "ERRO" );
			}

			private function calculadoraResult( event: ResultEvent ): void {

				/*
				 * a propriedade result do objeto event (do tipo ResultEvent)
				 * contém o valor de retorno do método remoto que foi executado
				 * essa propriedade é do tipo Object, então caso haja a necessidade
				 * de se converter o valor retornado, é necessário saber que tipo que está
				 * sendo retornado.
				 *
				 * Como os números no ActionScript também são objetos, aqui
				 * não é feita nenhuma conversão, só chamando o método toString()
				 * do valor, retornando assim a representação em String do número retornado.
				 */
				var valor: Object = event.result;
				campoResultado.text = valor.toString();

				Alert.show( "Serviço executado com sucesso!", "Mensagem" );

			}

			private function botaoCalcularClick( event: Event ): void {

				/*
				 * Declaração de duas variáveis do tipo Number que recebem
				 * a conversão em número do texto dos seus respectivos campos.
				 * Note que não há nenhuma validação.
				 */
				var n1: Number = Number( campoN1.text );
				var n2: Number = Number( campoN2.text );

				/*
				 * grupoOperacoes é um RadioButtonGrupo que está relacionado
				 * aos quatro radios criados. O propriedade selectedValue retorna
				 * o valor da propriedade label do radio selecionado no momento.
				 * Perceba que em ActionScript, nós podemos fazer switch com Strings
				 * diferentemente do Java (até a versão 6.0) onde isso não é suportado
				 */
				switch ( grupoOperacoes.selectedValue.toString() ) {

					case "+":
						calculadora.somar( n1, n2 );
						break;

					case "-":
						calculadora.subtrair( n1, n2 );
						break;

					case "*":
						calculadora.multiplicar( n1, n2 );
						break;

					case "/":
						calculadora.dividir( n1, n2 );
						break;

				}

			}

		]]>
	</fx:Script>

	<fx:Declarations>

		<s:RemoteObject
			id="servicos"
			destination="testeServicos"
			showBusyCursor="true">

			<s:method
				name="imprimirMensagem"
				fault="imprimirMensagemFault(event)"
				result="imprimirMensagemResult(event)"/>

		</s:RemoteObject>

		<s:RemoteObject
			id="calculadora"
			destination="servicosCalculadora"
			showBusyCursor="true">

			<s:method
				name="somar"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

			<s:method
				name="subtrair"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

			<s:method
				name="multiplicar"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

			<s:method
				name="dividir"
				fault="calculadoraFault(event)"
				result="calculadoraResult(event)"/>

		</s:RemoteObject>

		<s:RadioButtonGroup id="grupoOperacoes"/>

	</fx:Declarations>

	<s:Panel x="11" y="10" width="250" height="200" title="Testes Serviços (ServicosTeste.java)">
		<s:Button x="15" y="13" label="Executar" click="botaoExecutarClick(event)"/>
	</s:Panel>
	<s:Panel x="269" y="10" width="250" height="241" title="Calculadora (ServicosCalculadora.java)">
		<s:Label x="12" y="20" text="Número 1:"/>
		<s:Label x="13" y="50" text="Número 2:"/>
		<s:TextInput x="79" y="14" width="64" id="campoN1"/>
		<s:TextInput x="80" y="44" width="63" id="campoN2"/>
		<s:Label x="13" y="102" text="Operação:"/>
		<s:RadioButton x="77" y="84" label="+" groupName="grupoOperacoes" selected="true" id="radioSomar"/>
		<s:RadioButton x="111" y="84" label="-" groupName="grupoOperacoes" id="radioSubtrair"/>
		<s:RadioButton x="77" y="110" label="*" groupName="grupoOperacoes" id="radioMultiplicar"/>
		<s:RadioButton x="111" y="110" label="/" groupName="grupoOperacoes" id="radioDividir"/>
		<s:Label x="10" y="184" text="Resultado:"/>
		<s:TextInput x="79" y="176" id="campoResultado" width="159"/>
		<s:Button x="10" y="141" label="Calcular!" width="228" click="botaoCalcularClick(event)"/>
	</s:Panel>
</s:Application>

Na próxima (e última) parte do nosso tutorial, iremos ver como trabalhar com objetos criados por nós mesmos, enviando e recebendo esses objetos entre as camadas feitas em ActionScript (swf) e Java (com suporte do BlazeDS). Utilizaremos banco de dados também, fazendo então um exemplo completo de um CRUD (Create Read Update Delete).

Espero que estejam gostando!

Parte 1Parte 2Parte 3Parte 4.1Parte 4.2

Anúncios