Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Crie aplicativos da Web Flex 4 e Java

Descubra a comunicação remota de objetos

Arron Ferguson, College Instructor, British Columbia Institute of Technology
Photo of Arron Ferguson
Arron Ferguson é instrutor de universidade há 13 anos, ensinando engenharia de software no British Columbia Institute of Technology (Instituto de Tecnologia da Colúmbia Britânica). Suas áreas de experiência e de interesse são Java, XML, tecnologias da Web, animação 2D e 3D e criação de mídia digital. Arron cria software e faz trabalhos freelance como editor técnico, revisor e escritor, incluindo o livro publicado Creating Content Management Systems in Java (Delmar Cengage Learning).

Resumo:  Rich Internet Applications (RIAs) geralmente usam diferentes tecnologias em pacote configurável. Escolher o grupo correto de tecnologias pode agilizar o tempo de desenvolvimento e fornecer aos usuários uma experiência completa e complexa na Internet. Descubra como usar os componentes da plataforma Java™ EE no lado do servidor, a plataforma Adobe® Flex™ no lado do cliente e o servidor de banco de dados MySQL® para obter persistência de armazenamento.

Data:  17/Mai/2011
Nível:  Intermediário Também disponível em :   Inglês
Atividade:  1757 visualizações
Comentários:  


As tecnologias da Web atuais estão sob demanda crescente. Elas precisam poder gerenciar contas de usuário, fazer upload de conteúdo e streaming de vídeo. Essa demanda exige que desenvolvedores de RIA procurem tecnologias que simplifiquem o fluxo de trabalho de desenvolvimento e, ao mesmo tempo, ofereçam recursos muito procurados. O desafio dos desenvolvedores é escolher o conjunto certo de tecnologias para fornecer esses serviços.

Acrônimos usados frequentemente

  • AMF: Action Message Format
  • API: Interface de Programação de Aplicativos
  • CSS: Cascading stylesheet
  • GUI: Interface Gráfica com o Usuário
  • HTTP: Protocolo de transporte de Hipertexto
  • JAR: Java archive
  • POJO: Plain old Java object
  • RIA: Rich Internet Application
  • RPC: Chamada de Procedimento Remoto
  • SDK: Kit de Desenvolvimento de Software
  • SQL: Linguagem de Consulta Estruturada
  • UI: Interface com o usuário
  • WAR: Archive Web
  • XML: Linguagem de marcação extensível

Adobe Flex é uma tecnologia do lado do cliente que fornece a desenvolvedores um conjunto complexo de chamadas de API para criar GUIs, desenhar gráficos, reproduzir e fazer streaming de mídia e conectar serviços da Web. No lado do servidor, a tecnologia Java fornece recursos tais como conexão a sistemas de gerenciamento de banco de dados relacional (RDBMSs), processo em vários encadeamentos de solicitações de serviço e escala ótima com aumento da demanda. Usar essas duas tecnologias juntas oferece uma pilha de tecnologia poderosa que satisfaz a demanda de aplicativos RIA.

Este artigo demonstra como escrever um RIA simples, porém poderoso, que usa Flex para o cliente, tecnologia Java para o servidor de MySQL para o banco de dados backend.

O aplicativo de amostra

O aplicativo de amostra (disponível na seção Download abaixo) oferece uma UI complexa que suporta criação, leitura, atualização e exclusão (CRUD) de informações de contato por meio de um aplicativo Adobe Flash® (SWF). Essa arquitetura da Web com três camadas é representada na Figura 1, na qual o cliente é representado pelo arquivo SWF integrado dentro da página da Web, o aplicativo do servidor é executado dentro de um contêiner de servlet Java (neste caso, Apache Tomcat) e o banco de dados é MySQL. Combinados, essas três camadas criam um aplicativo distribuído com poder.


Figura 1. O aplicativo Contacts

Para comunicação entre o aplicativo Flash e o contêiner do servlet Java, a estrutura Adobe BlazeDS oferece comunicação remota de objetos—uma forma de RPC que permite que objetos Adobe ActionScript™ chamem objetos Java e vice-versa. Comunicação entre o aplicativo do servidor Java e o banco de dados relacional fica a cargo da estrutura Hibernate Object Relational Mapping (ORM). Hibernate permite que objetos Java sejam transformados em código SQL e vice-versa.


O aplicativo: camada do servidor

A primeira etapa é criar uma classe Java que abrange as informações exigidas para armazenar informações de contato. O aplicativo de amostra contém um modelo simples com informações básicas. Os atributos e os tipos de dados exigidos para os objetos de Contact são:

- String emailAddress
- String firstName
- long id
- String lastName
- String phoneNumber
- long serialVersionUID
+ Contact()
+ Contact(String first, String last, String email, String number)
+ String getEmailAddress()
+ String getFirstName()
+ long getId()
+ String getLastName()
+ String getPhoneNumber()
+ void setEmailAddress(String address)
+ void setFirstName(String first)
+ void setId(long newId)
+ void setLastName(String last)
+ void setPhoneNumber(String number)
+ StringtoString()

Anotando o objeto de negócios

A classe Java Contact é considerada um POJO (Plain old Java object) que age como um objeto de negócios, o que significa que ela representa características e comportamentos do domínio de negócios. Os dados dentro dos objetos de Contact precisam persistir no banco de dados. A solução é usar uma estrutura ORM, como Hibernate, que realiza a maior parte do trabalho de mapear objetos para registros nas tabelas de banco de dados vice-versa. Se forem usadas anotações Java Persistence API (JPA), é necessário muito pouco código para completar o ORM. A Listagem 1 demonstra a classe demonstra a classe Java Contact anotada.


Listagem 1. A classe Java Contact
	
package bcit.contacts;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table(name="contact")
@NamedQueries( {
    @NamedQuery(name = "contact.findAll", query = "from Contact"),
    @NamedQuery(name = "contact.getById", query =
        "select c from Contact c where c.id = :id")
} )
public class Contact {

    private static final long serialVersionUID = 123456789L;

    public Contact() {
        firstName = "N/A";
        lastName = "N/A";
        emailAddress = "N/A";
        phoneNumber = "N/A";
    }

    public Contact(String first, String last, String email, String number) {
        firstName = first;
        lastName = last;
        emailAddress = email;
        phoneNumber = number;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false, updatable=false)
    private long id;

    @Column(name = "lastName", nullable = false, unique = false)
    private String lastName;

    @Column(name = "firstName", nullable = false, unique = false)
    private String firstName;

    @Column(name = "emailAddress", nullable = false, unique = false)
    private String emailAddress;

    @Column(name = "phoneNumber", nullable = false, unique = false)
    private String phoneNumber;

    public void setPhoneNumber(String number) { phoneNumber = number; }

    public String getPhoneNumber() { return phoneNumber; }

    public String getEmailAddress() { return emailAddress; }

    public void setEmailAddress(String address) { emailAddress = address; }

    public String getFirstName() { return firstName; }

    public void setFirstName(String first) { firstName = first; }

    public String getLastName() { return lastName; }

    public void setLastName(String last) { lastName = last; }

    public long getId() { return id; }

    public void setId(long newId) { id = newId; }

    @Override
    public String toString() {
        return id + " " + firstName + " " + lastName + " " + emailAddress
            + " " + phoneNumber;
    }
}

A classe é simples, mas muita coisa está acontecendo nas anotações:

  • @Column: Rotula a propriedade como uma coluna no banco de dados, com as escolhas incluindo o nome da coluna, se ela é única e se a coluna é anulável
  • @Entity: Declara a classe como um bean de entidade, o que significa que ela é um POJO marcado para persistência
  • @GeneratedValue: Especifica a estratégia para gerar chaves primárias; as opções são AUTO, IDENTITY, SEQUENCE e TABLE
  • @Id: Declara que a propriedade é o identificador exclusivo (ou seja, a chave primária) para cada objeto Java
  • @NamedQueries: Lista um grupo de consultas nomeadas
  • @NamedQuery: Declara uma consulta predefinida como uma cadeia de caractere literal, que pode mais tarde ser referenciada para execução
  • @Table: Designa a classe Java como uma tabela dentro do banco de dados

Sempre que for preciso que um objeto Java na memória persista, Hibernate transforma as informações de estado de qualquer objeto Java em uma atualização SQL. Da mesma maneira, instruções SQL com conjuntos de resultados são usadas para preencher objetos Java. O resultado é que todos os objetos podem ser salvos como registros no banco de dados, e todos os registros podem ser recuperados e transformados novamente em objetos Java.

As anotações informam ao Hibernate o que deve ser considerado persistente na classe. Mas elas são apenas parte da figura.

O serviço de negócios: conectividade do banco de dados

Uma classe de serviço é necessária para realizar as chamadas ao Hibernate para executar o ORM. A Listagem 2 exibe a classe ContactsService, que age como o serviço de aplicativo.


Listagem 2. A classe ContactsService
	
public class ContactsService {

    private static Logger logger = Logger.getLogger(ContactsService.class);

    private static final String PERSISTENCE_UNIT = "contacts";

    private static EntityManagerFactory emf = null;

    static {
        logger.info("LOADING CONTACTSSERVICE CLASS.");
        emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
    }

    public ContactsService() {
        super();
    }

    public void addContact(Contact c) {
        if(c == null) {
            return;
        }

        EntityManager em = emf.createEntityManager();
        logger.info("PERSISTENCE ENTITYMANAGER ACQUIRED.");

        logger.info("ABOUT TO ADD CONTACT: fName: " + c.getFirstName()
            + ", lName: " + c.getLastName() + ", email:" + c.getEmailAddress()
            + ", phone: " + c.getPhoneNumber());
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            em.merge(c);
            tx.commit();
        } catch (Exception e) {
            logger.error("CONTACT APP PERSISTING ERROR: " + e.getMessage());
            tx.rollback();
        } finally {
            logger.info("CONTACT APP CLOSING ENTITY MANAGER.");
            em.close();
        }
    }

    public void editContact(Contact c) {
        logger.info("CONTACT TO UPDATE: " + c);
        addContact(c);
    }

    public void deleteContact(Long id) {
        logger.info("ABOUT TO DELETE CONTACT");

        EntityManager em = emf.createEntityManager();
        logger.info("PERSISTENCE ENTITYMANAGER ACQUIRED.");

        Query contactByIdQuery = em.createNamedQuery("contact.getById");
        contactByIdQuery.setParameter("id", id);
        Contact c = (Contact) contactByIdQuery.getSingleResult();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            em.remove(c);
            tx.commit();

        } catch (Exception e) {
            logger.error("CONTACT APP PERSISTING ERROR: " + e.getMessage());
            tx.rollback();
        } finally {
            logger.info("CONTACT APP CLOSING ENTITY MANAGER.");
            em.close();
        }
    }

    public List<Contact> getContacts() {
        logger.info("ABOUT TO RETRIEVE CONTACTS");

        EntityManager em = emf.createEntityManager();
        logger.info("PERSISTENCE ENTITYMANAGER ACQUIRED.");

        Query findAllContactsQuery =
            em.createNamedQuery("contact.findAll");
        List<Contact> contacts = findAllContactsQuery.getResultList();

        if (contacts != null) {
            logger.debug("CONTACT APP RETRIEVED: " + contacts.size()
                + " CONTACT(S)");
        }
        return contacts;
    }
}

Cada método recebe uma referência a um EntityManager, que representa o cache na memória. O armazenamento em cache é um recurso poderoso que garante eficiência, pois enviar e receber dados de um banco de dados pode ser uma operação cara. É necessário apenas garantir que cada cache criado seja confirmado no banco de dados ou retrocedido se não for desejado.

Em JPA, o termo dado para o cache é contexto persistente, e é representado pela classe EntityManager. Cada contexto de persistência gerencia um conjunto de entidades, que são objetos Java que foram anotados com a anotação @Entity. A classe EntityManagerFactory representa uma unidade de persistência, que é responsável por configurar conexões para um armazenamento de dados (por exemplo, um banco de dados relacional), gerenciar tipos de entidade (ou seja, todas as classes em um dado contexto que seja necessário mapear para o armazenamento de dados) e, por fim, fornecer instâncias de um contexto de persistência (ou seja, um EntityManager).

Experimente uma versão gratuita do servidor de banco de dados DB2 Express 9

O DB2 Express-C foi projetado para estar ativo em alguns minutos, é fácil de usar e integrar, inclui recursos de autogerenciamento e contém todos os recursos essenciais do DB2 para Linux®, UNIX® e Windows® tais como pureXML™. DB2 Express-C oferece os mesmos recursos básicos de servidor de dados que as outras edições do DB2 Express, e fornece uma base sólida para desenvolver e implementar aplicativos desenvolvidos usando C/C++, Java, .NET®, PHP, Ruby on Rails, Python e outras linguagens de programação.

Embora o processo de criação de um contexto de persistência não demande muito tempo, o processo de criação de uma unidade de persistência é dispendioso. Estabelecer conectividade para um armazenamento de dados, encontrar todas as classes anotadas como entidades e configurar a lógica de persistência para ligar essas classes a entidades no armazenamento de dados não é uma operação rápida. Portanto, deve-se criar uma instância EntityManagerFactory assim que o aplicativo iniciar. Quanto a contextos de persistência, é preciso garantir que um EntityManager seja destruído antes que outro seja criado. Outra importante regra a seguir é o padrão entitymanager-per-request. Esse padrão agrupa chamadas de banco de dados (por exemplo, solicitações e atualizações) para que eles possam todos ser enviados de uma vez. Fazer isso garante vantagem total do mecanismo de cache JPA.

O próximo requisito é o lado do cliente.


O aplicativo: camada do cliente

A estrutura Flex permite criar aplicativos que usuários podem reproduzir no Adobe Flash Player. Flex consiste em:

  • Uma linguagem de UI XML declarativa conhecida como MXML
  • A linguagem de programação ActionScript
  • Bibliotecas de tempo de execução para criar UIs, conectividade da Web e muitos outros recursos
  • Ferramentas de desenvolvedor para compilar aplicativos em arquivos SWF

O aplicativo cliente referenciado neste artigo usa Flex versão 4. Antes de abordar o aplicativo no lado do cliente, é importante entender como aplicativos Flex são criados e como eles existem como executáveis no Flash Player.

Primeiro, é possível criar aplicativos usando uma combinação de marcação MXML e código ActionScript. Um fluxo de trabalho comum é criar a maior parte da GUI (apresentação) usando o formato MXML e em seguida usar o código ActionScript para identificação de eventos e lógica de negócios. Como MXML e ActionScript são baseados em texto, um editor de texto padrão e o SDK Flash são todos os elementos necessários para criar aplicativos Flash.

Segundo, após criar o aplicativo Flex, compila-se o código usando o compilador MXML. O compilador MXML cria arquivos SFW que podem ser executados dentro de um navegador da Web (através do plug-in do navegador do Flash Player).

Por fim, aplicativos Flash são executados dentro da ActionScript Virtual Machine 2 (AVM2), que usa o paradigma de linha de tempo. Esse paradigma divide a execução em quadros—como em um filme. O número de quadros por segundo é especificado no aplicativo no tempo de compilação. Adicionalmente, o Flash Player divide a execução nas seguintes tarefas ordenadas:

  • Eventos do Flash Player, tais como eventos do timer e do mouse
  • Código do usuário
  • Lógica de pré-renderização, na qual o Flash Player tenta determinar se a GUI precisa ser atualizada devido a alterações nos valores dos dados
  • Código de usuário que estava ligado às alterações de valores de dados
  • Renderização do Flash Player

Se houver poucos quadros por segundo para renderizar, a maior parte do código do usuário pode ser executado. Se, no entanto, a taxa de quadros for alta (por exemplo, 60 quadros por segundo), o Flash Player pode não conseguir executar a maior parte do código do usuário, pois o código pode levar mais tempo que o concedido. É importante lembrar-se disso ao criar para Flash Player.

MXML

MXML é um formato XML declarativo poderoso que ajuda a:

  • Minimizar a quantidade de código necessária para desenvolver uma GUI, devido à natureza declarativa do formato XML
  • Reduzir a complexidade do código GUI ao permitir uma separação clara entre a lógica de apresentação e a lógica de interação
  • Promover o uso de padrões de design ao abordar desenvolvimento de software

A Listagem 3 exibe a classe MXML Application.


Listagem 3. A classe ContactsApp
	
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  xmlns:contact="bcit.contacts.*" creationComplete="initPage();"
  layout="vertical" frameRate="30" pageTitle="Contacts Example"
  horizontalAlign="center" verticalAlign="middle" 
  backgroundColor="#A9C0E7">


  <mx:Style>
    .mainBoxStyle {
      borderStyle: solid;
      paddingTop: 5px;
      paddingBottom: 5px;
      paddingLeft: 5px;
      paddingRight: 5px;
    }

    .textMessages {
      fontWeight: bold;
    }
  </mx:Style>


  <mx:RemoteObject id="remotingService" showBusyCursor="false"
    destination="contacts" fault="handleFault(event);"
    result="handleResult(event);"/>

  <mx:Script>
    <![CDATA[

        import mx.rpc.events.FaultEvent;
        import mx.rpc.events.ResultEvent;
        import mx.collections.ArrayCollection;
        import bcit.contacts.dto.Contact;

        [Bindable]
        private var contacts:ArrayCollection = new ArrayCollection();

        // For more on the Bindable metadata tag, see the devguide_flex3.pdf
        // document, page 1249 (1257 in PDF page numbering)
        [Bindable]
        private var message:String = "Status: Ready";

        private var contact:Contact;

        public function setControlBarValid(valid:Boolean):void {
            if(valid) {
                // if the selected item is -1, then no item is selected but at
                // the same time the fields are valid which means the user chose
                // to add a contact, not update one
                if(contactsDataGrid.selectedIndex == -1) {
                    createButton.enabled = valid;
                } else {
                    editButton.enabled = valid;
                }
              } else {
                  // else nothing is valid
                  createButton.enabled = false;
                  editButton.enabled = false;
            }
        }

        private function initPage():void {
            editContactForm.setApp(this);
            contact = new Contact();
            getAllContacts();
            resetPage();
        }

        private function createContact():void {
            contact = editContactForm.getContact();
            remotingService.addContact(contact);
            message = "Status: Contact Added";
            getAllContacts();
        }

        private function editContact():void {
            var id:Number = contact.id;
            contact = editContactForm.getContact();
            contact.id = id;
            remotingService.editContact(contact);
            message = "Status: Contact Edited";
            getAllContacts();
        }

        private function deleteContact():void {
            if(contactsDataGrid.selectedItem != null) {
                var c:Contact = contactsDataGrid.selectedItem as Contact;
                // no sense in sending the whole contact - just send the id
                // to cut down on bandwidth
                remotingService.deleteContact(c.id);
                message = "Status: Contact Deleted";
            }
            getAllContacts();
        }

        private function getAllContacts():void {
            loadButton.enabled = false;
            remotingService.getContacts();
            loadButton.enabled = true;
            resetPage();
        }

        private function populateFormWithContact():void {
            contact = contactsDataGrid.selectedItem as Contact;
            editContactForm.setContact(contact);
            editButton.enabled = true;
            deleteButton.enabled = true;
        }

        private function resetPage():void {
            editContactForm.clearForm();
            contact = new Contact();
            createButton.enabled = false;
            editButton.enabled = false;
            deleteButton.enabled = false;
            contactsDataGrid.selectedIndex = -1;
        }

        private function handleFault(e:FaultEvent):void {
            message = "Status: Error"
                + "\nFault code: " + e.fault.faultCode
                + "\nFault detail: " + e.fault.faultDetail
                + "\nFault string: " + e.fault.faultString;
        }

        private function handleResult(e:ResultEvent):void {
            // can get the results by accessing e.result property
            //mx.controls.Alert.show(e.toString());
            contacts = e.result as ArrayCollection;
            var number:int = contacts.length;
            //if(number == 1) {
            //    message = "Status: Retrieved 1 contact";
            //} else {
            //    message = "Status: Retrieved " + contacts.length + " contacts";
            //}
        }

    ]]>
  </mx:Script>

  <mx:VBox styleName="mainBoxStyle">

    <mx:Text id="titleText" text="Single click to select a contact"/>

    <contact:ContactsDataGrid id="contactsDataGrid" dataProvider="{contacts}"
      itemClick="populateFormWithContact();"
      doubleClick="populateFormWithContact();"/>

    <contact:EditContactForm id="editContactForm"/>

    <mx:ControlBar horizontalAlign="center">
      <mx:Button label="List" id="loadButton" click="getAllContacts()"
        toolTip="Retrieve contacts from the server"/>
      <mx:Button label="Add" id="createButton" click="createContact()"
        toolTip="Create a new contact"/>
      <mx:Button label="Update" id="editButton" click="editContact()"
        toolTip="Edit a selected contact"/>
      <mx:Button label="Delete" id="deleteButton" click="deleteContact()"
        toolTip="Delete a selected contact"/>
      <mx:Button label="Clear Form" id="clearButton" click="resetPage()"
        toolTip="Clear the form"/>
    </mx:ControlBar>

    <mx:TextArea text="{message}" styleName="textMessages" wordWrap="true"
      verticalScrollPolicy="auto" horizontalScrollPolicy="off" editable="false"
      width="100%"/>

  </mx:VBox>

</mx:Application>

Eis mais alguns comentários sobre a listagem 3:

  • O elemento-raiz de um documento MXML é uma subclasse da classe Application.
  • O elemento mx:Style permite que propriedades CSS definam estilo local para componentes de UI. O estilo pode ser feito usando definições de estilo locais (como na Listagem 3), referências a folhas de estilo externas, fazendo inlining de estilos nos componentes e usando o método setStyle em ActionScript.
  • A classe RemoteObject representa um objeto de serviço HTTP que realiza operações de comunicação remota com um servidor.
  • O elemento mx:Script inclui blocos de código ActionScript em uma seção CDATA.
  • Há um layout (ou seja, a classe VBox).
  • Cada vez que um componente de UI é declarado no aplicativo (por exemplo, em TextArea), uma variável de instância é gerada, que pode ser referenciada mais tarde dentro do aplicativo usando o atributo id do aplicativo.
  • A ligação de dados é realizada usando chaves (por exemplo, o atributo text do elemento TextArea está ligado à variável de instância message do ActionScript).

ActionScript

Enquanto MXML define a GUI, ActionScript oferece o comportamento para lidar com eventos, ligar dados (por meio da tag de metadados [Bindable]) e a capacidade de chamar um serviço remoto. Na Listagem 3, os métodos createContact, editContact, deleteContact e getAllContacts chamam todos os métodos remotos no lado do servidor. Quando um método remoto é chamado, o ActionScript tem a oportunidade de lidar com o resultado e qualquer falha declarando funções de retorno de chamada. Na Listagem 3, a função handleResult recebe o resultado como um Objeto e o coloca em um ArrayCollection. BlazeDS converteu a Lista em uma ArrayCollection no lado do servidor.

A Listagem 4 apresenta a classe de ActionScript Contato, que você cria para representar objetos de contato no lado do Flash.


Listagem 4. A classe ActionScript Contact
	
package bcit.contacts.dto {

[RemoteClass(alias="bcit.contacts.Contact")]
public class Contact {

    public function Contact() { id = -1; }

    public var id:Number;
    public var lastName:String;
    public var firstName:String;
    public var emailAddress:String;
    public var phoneNumber:String;

    public function toString():String {
        return id + ", " + firstName + " " + lastName + " " + emailAddress
            + " " + phoneNumber;
    }
}
}

Esses objetos ActionScript são enviados para o lado do servidor, no qual BlazeDS faz seu truque e converte os objetos ActionScript em objetos Java. A classe Contact é considerada um Data Transfer Object (DTO).


Configurando o aplicativo

O aplicativo também se apoia em arquivos de configuração que declaram configurações específicas do servidor. As duas principais áreas de configuração neste aplicativo são Hibernate e BlazeDS.

Configurando Hibernate

Hibernate pode ser configurado usando o arquivo de configuração JPA padrão, persistence.xml, que é mostrado na Listagem 5.


Listagem 5. Um subconjunto do arquivo de configuração persistence.xml
	
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
  http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="contacts" transaction-type="RESOURCE_LOCAL">
    <properties>
      <property name="hibernate.dialect"
        value="org.hibernate.dialect.MySQLDialect" />
      <property name="hibernate.default_schema" value="contacts" />
      <property name="hibernate.connection.driver_class"
        value="com.mysql.jdbc.Driver" />
      <property name="hibernate.connection.url"
        value="jdbc:mysql://localhost:3306/contacts" />
      <property name="hibernate.archive.autodetection" value="class, hbm"/>
      <property name="hibernate.connection.username" value="root"/>
      <property name="hibernate.connection.password" value="root"/>
    </properties>
  </persistence-unit>
</persistence>

O arquivo persistence.xml deve estar na pasta WEB-INF/classes/META-INF do aplicativo da Web para ser lido pelo Hibernate. Com ele no lugar, o Hibernate exige as seguintes informações:

  • Dialeto do banco de dados (ou seja, com qual banco de dados ele está falando, pois vários deles têm dialetos SQL diferentes)
  • Espaço de tabela pelo esquema padrão
  • O driver de banco de dados usado para conectar com o banco de dados
  • A URL do banco de dados
  • O que a autodetecção deveria detectar (por exemplo, classes anotadas, mapeamento do Hibernate de arquivos XML e assim por diante)
  • Nome de usuário e senha

Outras informações podem ajudar o desempenho do Hibernate, mas não são exigidas.

Configurando BlazeDS

BlazeDS tem quatro arquivos de configuração:

  • messaging-config.xml: Define informações de sistema de mensagens publicar/assinar
  • proxy-config.xml: Oferece informações de serviço de proxy para HTTP e serviços da Web
  • remoting-config.xml: Define informações para serviços de remoting, tais como aquele no aplicativo do artigo
  • services-config.xml: O arquivo de configuração de nível superior que referencia os outros arquivos de configuração e também fornece restrições de segurança, canais e criação de log

A listagem 6 demonstra o arquivo services-config.xml. Observe que, para o aplicativo do artigo, apenas o arquivo remoting-config.xml é relevante, pois o aplicativo está usando apenas o serviço de comunicação remota BlazeDS.


Listagem 6. Um subconjunto do arquivo de configurações services-config.xml
	
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
  <services>
    <service-include file-path="remoting-config.xml" />
    <service-include file-path="messaging-config.xml" />
    <service-include file-path="proxy-config.xml" />
    <default-channels>
       <channel ref="contacts-amf"/>
    </default-channels>
  </services>

  <channels>
    <channel-definition id="contacts-amf" class="mx.messaging.channels.AMFChannel">
      <endpoint url="http://localhost:8080/contacts/messagebroker/amf"
        class="flex.messaging.endpoints.AMFEndpoint"/>
      <properties>
        <polling-enabled>false</polling-enabled>
      </properties>
    </channel-definition>
  </channels>

  <logging>
    <target class="flex.messaging.log.ConsoleTarget" level="Error">
      <properties>
        <prefix>[BlazeDS] </prefix>
        <includeDate>false</includeDate>
        <includeTime>false</includeTime>
        <includeLevel>false</includeLevel>
        <includeCategory>false</includeCategory>
      </properties>
      <filters>
        <pattern>Endpoint.*</pattern>
        <pattern>Service.*</pattern>
        <pattern>Configuration</pattern>
      </filters>
    </target>
  </logging>

</services-config>

O arquivo de configuração services-config.xml referencia os outros arquivos de configuração (que precisam existir), configura a criação de log do BlazeDS e configura canais. Um canal é uma abstração do protocolo que é usado para que o cliente se comunique com o servidor. O aplicativo do artigo usa o protocolo AMF padrão sem pesquisa. Pesquisa significa que o cliente comunica-se continuamente com o servidor para garantir que a conexão ainda está estabelecida—algo que não é necessário neste aplicativo.

Participe do grupo de desenvolvimento da Web no My developerWorks

Discuta tópicos e compartilhe recursos com outros desenvolvedores sobre desenvolvimento da Web no grupo de desenvolvimento da Web do My developerWorks.

Não é membro do My developerWorks? Cadastre-se já!

O terminal do canal especifica a URL do servidor. Esse terminal é necessário para compilar o projeto; o aplicativo Flash cliente usa-o como um valor codificado permanentemente, para saber a qual servidor conectar-se. Também é possível definir a URL do terminal no código MXML ou ActionScript diretamente.

Por fim, o arquivo de configuração remoting-config.xml (mostrado na Listagem 7) especifica a classe de adaptador necessária para lidar com as operações de remoting, bem como as classes reais que respondem às chamadas de remoting. (Nesse caso, a classe bcit.contacts.ContactsService foi dada como respondente das solicitações remotas.)


Listagem 7. Um subconjunto do arquivo de configuração 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" default="true"
      class="flex.messaging.services.remoting.adapters.JavaAdapter"/>
  </adapters>

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

  <destination id="contacts">
    <properties>
      <source>bcit.contacts.ContactsService</source>
      <!--<scope>application</scope>-->
    </properties>
  </destination>

</service>


Conclusão

Este artigo mostrou a você como escrever um aplicativo da Web do lado do servidor que é executado no Tomcat e responde solicitações de informações de contato. Você também aprendeu a criar um aplicativo Flex usando MXML e ActionScript para criar um aplicativo Flash do lado do cliente. MySQL serviu de armazenamento de dados, e Hibernate—uma estrutura ORM—foi usado para transformar objetos Java em instruções SQL que poderiam consultar e atualizar o banco de dados MySQL. Por fim, a estrutura BlazeDS permitiu que o aplicativo Flash fizesse chamadas de procedimento remotas e realizasse comunicação remota no aplicativo da Web no lado do servidor Java.



Download

NomeTamanhoMétodo de download
JEE-BlazeDS-Flex-contacts.zip7MBHTTP

Informações sobre métodos de download

Mais downloads

Notas

  1. Este arquivo zip contém todo o código de origem para este projeto (Java, ActionScript 3, MXML), o arquivo de desenvolvimento Ant para gerar o WAR, arquivos de configuração e bibliotecas de terceiros (na forma de arquivos JAR) que este artigo menciona e usa.
  2. Um RDBMS de software livre exigido para uso com o projeto de exemplo neste artigo
  3. Uma ferramenta de desenvolvimento baseada em Java para criar o projeto de exemplo
  4. O SDK Java (JDK) versão 6, necessário para compilar código de origem Java no projeto de exemplo
  5. O SDK Flex 4 para compilar código de origem MXML e ActionScript no projeto de exemplo
  6. O contêiner do servlet da Apache Software Foundation que fornece um ambiente de servidor da Web de HTTP Java para executar o projeto de exemplo
  7. A estrutura Adobe para conectar a tecnologia Flex à Plataforma Java, Enterprise Edition (Java EE). Este software é apenas para referência, pois já está incluído no download de projeto para este artigo.
  8. Estrutura de ORM Red Hat para middleware de contêiner Java EE. Este software é apenas para referência, pois já está incluído no download de projeto para este artigo.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

  • My developerWorks: Comunique-se com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

Sobre o autor

Photo of Arron Ferguson

Arron Ferguson é instrutor de universidade há 13 anos, ensinando engenharia de software no British Columbia Institute of Technology (Instituto de Tecnologia da Colúmbia Britânica). Suas áreas de experiência e de interesse são Java, XML, tecnologias da Web, animação 2D e 3D e criação de mídia digital. Arron cria software e faz trabalhos freelance como editor técnico, revisor e escritor, incluindo o livro publicado Creating Content Management Systems in Java (Delmar Cengage Learning).

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Software livre
ArticleID=657865
ArticleTitle=Crie aplicativos da Web Flex 4 e Java
publish-date=05172011
author1-email=arron_ferguson@bcit.ca
author1-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).