Web Service Passando Dados Binários, parte 5: Criando o Cliente Swing

O objetivo deste exercício é criar um cliente para o Web service criado e implantado anteriormente e, em seguida, adicionar uma interface de GUI a esse cliente. A interface exibe as imagens que o Web service passa como dados binários.

É possível fazer download de uma versão completa do cliente a partir do Catálogo de Amostras do NetBeans.

Lições Deste Tutorial

O conteúdo desta página se aplica ao NetBeans IDE 7.2, 7.3 e 7.4
  1. Visão Geral
  2. Criando o Web Service
  3. Codificando e Testando o Web Service
  4. Modificando o Esquema e os Arquivos WSDL para Passar Dados Binários
  5. => Criando o Cliente Swing

Conteúdo Desta Lição

  1. Criando a Aplicação Cliente

  2. Projetando o JFrame
  3. Vinculando os Componentes do JFrame

  4. Codificando a Classe Principal

Criando a Aplicação Cliente

Nesta seção, você criará uma aplicação Web. Nessa aplicação, você criará um cliente que consumirá o Web service criado e modificado em tutoriais anteriores.

Para criar a aplicação cliente:

  1. Selecione Arquivo > Novo Projeto (Ctrl-Shift-N no Linux/Windows, ⌘-Shift-N no MacOS). O Assistente de Novo Projeto será exibido.
  2. Selecione Aplicação Java na categoria Java. Clique em Próximo. O assistente de Nova Aplicação Java será exibido. Digite FlowerClient em Nome do Projeto. Selecione uma localização para o projeto e clique em Finalizar. O IDE criará um novo projeto de aplicação Java.
  3. Clique com o botão direito do mouse no nó do projeto FlowerClient e selecione Novo > Cliente de Web Service no menu de contexto. O assistente de Novo Cliente de Web Service será aberto.
  4. Selecione o botão de opção URL WSDL e cole o URL do arquivo WSDL nesse campo. (Por default, o URL é http://localhost:8080/FlowerAlbumService/FlowerServiceService?wsdl. Localize o URL no browser testando o Web service e substituindo ?Tester por ?wsdl no final do URL.) Aceite todos os outros valores default, incluindo um nome de pacote em branco.
    Assistente do Cliente de Web Service mostrando URL WSDL
  5. Clique em Finalizar. O IDE faz download do arquivo WSDL, adiciona stubs de cliente para interagir com o Web service e adiciona nós à janela Projetos no projeto de aplicação Java.
    Visualização Projetos mostrando o novo cliente do Web Service

Projetando o Form JFrame

Nesta seção, você adicionará um JFrame à aplicação Web e projetará uma interface de GUI dentro dele utilizando componentes Swing. Finalmente, você vinculará os componentes Swing ao código do cliente de Web service.

Se não desejar projetar o form JFrame você mesmo, você poderá fazer download de um arquivo Java do JFrame pré-projetado aqui.

  1. Clique com o botão direito do mouse no nó FlowerClient e selecione Novo > Form JFrame. Chame o quadro de FlowerFrame. Coloque-o no pacote flowerclient.
  2. FlowerFrame será aberto no editor. Abra a Paleta, se ainda não estiver aberta. Estenda o limite inferior do quadro em aproximadamente um terço.
    Form Flor no editor, na exibição do desenho, com a Paleta também aberta
  3. Arraste um JPanel da seção Contêineres Swing da Paleta para o FlowerFrame. Expanda-o para preencher o FlowerFrame inteiro.
    Adicionando e expandindo um JPanel no FlowerFrame
  4. Clique com o botão direito do mouse no Painel na View do Design. Selecione Alterar Nome da Variável... no menu de contexto. Defina o nome do painel como gardenFlowersPanel.
  5. Arraste um JLabel da Paleta para o início do gardenFlowersPanel. Clique com o botão direito do mouse no label e altere seu nome de variável para titleLabel. Clique com o botão direito do mouse novamente em titleLabel e selecione Editar Texto. Altere o texto para Flores do Jardim. Talvez você queira explorar as propriedades do titleLabele dar a ele uma fonte de maior expressão.
  6. Arraste um Grupo de Botões para a view de design. Aceite o nome da variável default do grupo de botões, buttonGroup1.
  7. Arraste quatro Botões de Opções para uma linha horizontal abaixo do titleLabel. Nas propriedades de cada botão, defina-o como um membro de buttonGroup1. As outras propriedades dos botões são:
    Botões de Opção em ButtonGroup1
    Nome da Variável Selecionado Texto
    asterRadioButton verdadeiro Áster
    honeysuckleRadioButton falso Madressilva
    roseRadioButton falso Rosa
    sunflowerRadioButton falso Girassol
  8. Arraste um Painel de Rolagem para baixo dos botões de opções. Expanda-o para preencher todo o espaço horizontal e cerca de dois terços do espaço vertical livre. Altere o nome da variável do painel de rolagem para mainScrollPane.
  9. Arraste um Painel para o mainScrollPane. Altere o nome da variável do Painel para mainPanel.
  10. Na view Design, clique com o botão direito do mouse no mainPanel e selecione Definir layout > Layout da Borda.
  11. Arraste um Botão para o mainPanel. Como o mainPanel tem layout de borda, o botão automaticamente preenche todo o painel. Altere o nome da variável do botão para mainPictureButton e mude o texto do botão para "Aguardando imagem..."
  12. Arraste outro Painel de Rolagem para o espaço abaixo do mainScrollPane. Expanda o novo painel de rolagem para preencher todo o espaço livre remanescente. Altere o nome da variável do novo painel de rolagem para thumbnailScrollPane.
  13. Arraste um Painel para o thumbnailScrollPane. Altere o nome da variável do Painel para thumbnailPanel. Defina o layout do thumbnailPanel para Layout de Grade.
  14. Arraste quatro Botões para o thumbnailPanel Como o thumbnailPanel tem Layout de Grade, os botões são automaticamente de mesmo tamanho e preenchem o painel completamente. As propriedades dos botões são: Botões no thumbnailPanel
    Nome da Variável Texto
    asterButton Aguardando...
    honeysuckleButton Aguardando...
    roseButton Aguardando
    sunflowerButton Aguardando...

O Form JFrame agora está totalmente projetado. Nesse ponto, o FlowerFrame deverá ter a seguinte aparência.
Quadro de Flores Concluído mostrando os textos do botão em vez de imagens

Vinculando os Componentes do JFrame

Nesta seção, você inicializará os componentes no construtor e vinculará os componentes aos listeners. Os listeners chamam o código que mostra as imagens das flores.

Inicializando os Componentes

Nesta seção, você preencherá o construtor FlowerFrame

  1. Alterne para a view de Código-fonte do editor. Localize o início do corpo da classe FlowerFrame e o construtor FlowerFrame.
    View de código-fonte do editor mostrando o construtor FlowerForm
  2. Na parte superior do corpo da classe do FlowerFrame, antes do construtor, crie um array de strings dos nomes de cada flor.
    protected static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};
  3. Entre o array da string FLOWERS e o construtor, adicione uma linha que inicialize um java.util.Map denominado flores. O mapa utiliza uma String e a mapeia para uma Image.
    private Map<String, Image> flowers;
  4. Adicione instruções de importação para java.util.Map e java.awt.Image.
  5. Adicione código ao construtor FlowerFrame para associar uma Image específica a uma String específica de uma instância específica do mapa flowers
    public FlowerFrame(Map<String, Image> flowers) {
    
        this.flowers = flowers;
        for (String flower:FLOWERS) {
            flowers.put(flower,null);
        }
    
        initComponents();    
    } 
  6. Inicialize ItemListeners para os botões de opções e ActionListeners para os quatro botões de flores e defina o título default.
    public FlowerFrame(Map<String, Image> flowers) {
    
        this.flowers = flowers;
        for (String flower:FLOWERS) {
            flowers.put(flower,null);
        }
    
        initComponents(); 
        
        setTitle("Garden Flowers [waiting for picture]");
        
        ItemListener rbListener = new RBListener();
        asterRadioButton.addItemListener(rbListener);
        honeysuckleRadioButton.addItemListener(rbListener);
        roseRadioButton.addItemListener(rbListener);
        sunflowerRadioButton.addItemListener(rbListener);
        
        ActionListener bListener = new ButtonListener();
        asterButton.addActionListener(bListener);
        honeysuckleButton.addActionListener(bListener);
        roseButton.addActionListener(bListener);
        sunflowerButton.addActionListener(bListener);
    }
  7. Adicione instruções de importação para java.awt.event.ItemListener e java.awt.event.ActionListener.

Agora, o construtor está completo. Você receberá advertências de erros de compilação no código porque ele não contém as classes RBListener e ButtonListener. Essas duas classes são implementações personalizadas do ItemListener e ActionListener, respectivamente. Você escreverá essas duas classes na próxima seção.

Mostrando as Flores

Nesta seção, você escreverá listeners personalizados para os botões de opções e os botões de flores. Você também escreverá um método que determinará qual flor será selecionada pelos botões e obterá uma Image daquela flor a partir do mapa flowers. Finalmente, você escreverá um método que é chamado pela classe Main e que obterá uma Image para cada miniatura.

  1. Encontre o método public static void main(String args[]) no corpo da classe FlowerFrame. Delete esse método e sua documentação. (A aplicação utilizará a classe Main.)
  2. No lugar do método main, escreva um ItemListener personalizado para os botões de opções. Esse listener mostrará uma nova imagem de flor quando um botão de opção for selecionado.
    private class RBListener implements ItemListener {
        public void itemStateChanged(ItemEvent e) {
            showFlower();
        }
    }
  3. Adicione uma instrução de importação para java.awt.event.ItemEvent.
  4. Abaixo do ItemListener personalizado, escreva um ActionListener personalizado para os quatro botões de flores. Quando um botão for clicado, o listener selecionará o botão de opção relacionado:
    private class ButtonListener implements ActionListener {
    
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == asterButton) asterRadioButton.setSelected(true);
            else if (e.getSource() == honeysuckleButton) honeysuckleRadioButton.setSelected(true);
            else if (e.getSource() == roseButton) roseRadioButton.setSelected(true);
            else if (e.getSource() == sunflowerButton) sunflowerRadioButton.setSelected(true);
        }
    }
  5. Adicione uma instrução de importação para java.awt.event.ActionEvent.
  6. Abaixo do ActionListener personalizado, escreva o método showFlower. Esse método determina o botão de opção selecionado e obtém uma Image da flor correspondente a partir do mapa flowers.
    void showFlower() {
        Image img = null;
        if (asterRadioButton.isSelected()) {
            img = flowers.get("aster");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Aster]");
            }
        } else if (honeysuckleRadioButton.isSelected()) {
            img = flowers.get("honeysuckle");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Honeysuckle]");
            }
    
        } else if (roseRadioButton.isSelected()) {
            img = flowers.get("rose");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Rose]");
            }
        } else if (sunflowerRadioButton.isSelected()) {
            img = flowers.get("sunflower");
            if (img != null) {
                mainPictureButton.setIcon(new ImageIcon(img));
                setTitle("Garden Flowers [Sunflower]");
            }
        }
        if (img == null) {
            mainPictureButton.setIcon(null);
            setTitle("Garden Flowers [waiting for picture]");            
        } else mainPictureButton.setText("");
    }
  7. Adicione uma instrução de importação para javax.swing.ImageIcon.
  8. Escreva o método setThumbnails. Esse método obtém uma imagem para cada miniatura do mapa flowers. A classe Main chama esse método.
    void setThumbnails(Map<String, Image> thumbs) {
        Image img = thumbs.get("aster");
        if (img != null) {
            asterButton.setIcon(new ImageIcon(img));
            asterButton.setText("");
        }
        img = thumbs.get("honeysuckle");
        if (img != null) {
            honeysuckleButton.setIcon(new ImageIcon(img));
            honeysuckleButton.setText("");
        }
        img = thumbs.get("rose");
        if (img != null) {
            roseButton.setIcon(new ImageIcon(img));
            roseButton.setText("");
        }
        img = thumbs.get("sunflower");
        if (img != null) {
            sunflowerButton.setIcon(new ImageIcon(img));
            sunflowerButton.setText("");
        }
    }
  9. Corrija as importações em FlowerFrame, caso elas não tenham sido corrigidas quando foram coladas no código. É possível corrigir todas de uma vez clicando com o botão direito do mouse no editor e selecionando Corrigir Importações, no menu de contexto. O conjunto completo de instruções de importação é:
    import java.awt.Image;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    import java.util.Map;
    import javax.swing.ImageIcon;

O FlowerFrame agora está completo.

Codificando a Classe Principal

Nesta seção, você completará a classe Main para que mostre o FlowerFrame, estabelecerá uma conexão com o Web service e chamará as operações do Web service.

  1. Abra a classe Main.java no editor.
    Classe Main vazia
  2. No corpo da classe, antes do método principal, inicialize uma variável int para a quantidade de imagens obtidas por download.
     private static int downloadedPictures;
  3. No corpo do método main, crie um HashMap de quatro flores e outro HashMap de quatro miniaturas.
    final Map<String,Image> flowers = new HashMap<String,Image>(4);
    final Map<String,Image> thumbs = new HashMap<String,Image>(4);
  4. Adicione instruções de importação para java.awt.Image, java.util.Map e java.util.HashMap.
  5. No corpo do método main, adicione código para mostrar o FlowerFrame.
    // Show the FlowerFrame.
    final FlowerFrame frame = new FlowerFrame(flowers);
    frame.setVisible(true);  
  6. No corpo do método main, adicione o código para conectar o cliente ao serviço.
    // The client connects to the service with this code.
    FlowerServiceService service = new FlowerServiceService();
    final FlowerService port = service.getFlowerServicePort();
  7. Adicione instruções de importação para org.flower.service.FlowerService e org.flower.service.FlowerServiceService.
  8. No corpo do método main, adicione o código que cria um array de quatro threads Runnable e chama a operação getFlower do Web service uma vez em cada thread.
    // The web service getFlower operation
    // is called 4 times, each in a separate thread.
    // When the operation finishes the picture is shown in
    // a specific button.
    Runnable[] tasks = new Runnable[4];
    
    for (int i=0; i<4;i++) {
        final int index = i;
        tasks[i] = new Runnable() {
            public void run() {
                try {
                
                    // Call the getFlower operation
                    // on the web service:
                    Image img = port.getFlower(FlowerFrame.FLOWERS[index]);
                    System.out.println("picture downloaded: "+FlowerFrame.FLOWERS[index]);
                         
                    // Add strings to the hashmap:
                    flowers.put(FlowerFrame.FLOWERS[index],img);
                            
                    // Call the showFlower operation
                    // on the FlowerFrame:
                    frame.showFlower();
                            
                } catch (IOException_Exception ex) {
                    ex.printStackTrace();
                }
                downloadedPictures++;
            }
        };
        new Thread(tasks[i]).start();
    }
  9. Adicione uma instrução de importação para org.flower.service.IOException_Exception.
  10. No corpo do método principal, adicione o código que chama a operação getThumbnails do Web service em um thread separado.
    // The web service getThumbnails operation is called
    // in a separate thread, just after the previous four threads finish.
    // When the images are downloaded, the thumbnails are shown at 
    // the bottom of the frame.
    Runnable thumbsTask = new Runnable() {
        public void run() {
            try {
                while (downloadedPictures < 4) {                        
                    try {Thread.sleep(100);} catch (InterruptedException ex) {}
                }
                     
                // Call the getThumbnails operation
                // on the web service:
                List<Image> images = port.getThumbnails();
                System.out.println("thumbs downloaded");
                        
                if (images != null && images.size() == 4) {
                    for (int i=0;i<4;i++) {
                        thumbs.put(FlowerFrame.FLOWERS[i],images.get(i));
                    }
                    frame.setThumbnails(thumbs);
                }
            } catch (IOException_Exception ex) {
                ex.printStackTrace();
            }
        }            
    };
    new Thread(thumbsTask).start();
    
  11. Corrija as importações em Main.java, caso elas não tenham sido corrigidas quando foram coladas no código. É possível corrigir todas de uma vez clicando com o botão direito do mouse no editor e selecionando Corrigir Importações, no menu de contexto. Você verá uma Lista de classes para importação; selecione java.util.List. O conjunto completo de instruções de importação é:
    import flower.album.FlowerService;
    import flower.album.FlowerService_Service;
    import flower.album.IOException_Exception;
    import java.awt.Image;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

A classe Main agora está completa.

public class Main {

     private static int downloadedPictures;
    
     public static void main(String[] args) {
    
        final Map<String,Image> flowers = new HashMap<String,Image>(4);
        final Map<String,Image> thumbs = new HashMap<String,Image>(4);
        
        // Show the FlowerFrame.
        final FlowerFrame frame = new FlowerFrame(flowers);
        frame.setVisible(true);
        
// The client connects to the service with this code. FlowerService_Service service = new FlowerService_Service(); final FlowerService port = service.getFlowerServicePort(); Runnable[] tasks = new Runnable[4]; // The web service getFlower operation // is called 4 times, each in a separate thread. // When the operation finishes the picture is shown in // a specific button. for (int i=0; i<4;i++) { final int index = i; tasks[i] = new Runnable() { public void run() { try { // Call the getFlower operation // on the web service: Image img = port.getFlower(FlowerFrame.FLOWERS[index]); System.out.println("picture downloaded: "+FlowerFrame.FLOWERS[index]); // Add strings to the hashmap: flowers.put(FlowerFrame.FLOWERS[index],img); // Call the showFlower operation // on the FlowerFrame: frame.showFlower(); } catch (IOException_Exception ex) { ex.printStackTrace(); } downloadedPictures++; } }; new Thread(tasks[i]).start(); } // The web service getThumbnails operation is called // in a separate thread, just after the previous four threads finish. // When the images are downloaded, the thumbnails are shown at // the bottom of the frame. Runnable thumbsTask = new Runnable() { public void run() { try { while (downloadedPictures < 4) { try {Thread.sleep(100);} catch (InterruptedException ex) {} } // Call the getThumbnails operation // on the web service: List<Image> images = port.getThumbnails(); System.out.println("thumbs downloaded"); if (images != null && images.size() == 4) { for (int i=0;i<4;i++) { thumbs.put(FlowerFrame.FLOWERS[i],images.get(i)); } frame.setThumbnails(thumbs); } } catch (IOException_Exception ex) { ex.printStackTrace(); } } }; new Thread(thumbsTask).start(); } }

A aplicação cliente agora está completa, com o código que interage com o Web service que é delegado ao módulo EJB para a exposição de suas imagens. Clique com o botão direito do mouse no cliente e selecione Executar. A aplicação Swing é iniciada e, depois de um tempo, é preenchida com as imagens recebidas do Web service. Se as imagens não aparecerem, limpe e construa o projeto FlowerService e execute-o novamente. Observe que é possível alterar a imagem exibida no quadro principal selecionando um botão de opção ou clicando em uma miniatura.

Para enviar comentários e sugestões, obter suporte e se manter informado sobre os mais recentes desenvolvimentos das funcionalidades de desenvolvimento Java EE do NetBeans IDE, inscreva-se na lista de notícias .

get support for the NetBeans

Support


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo