corner imagecorner image
IDEPlatformPluginsDocs & SupportCommunityPartners

Serviço Web passando dados binários, parte 5: Criando o cliente Swing

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

É possível baixar 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 6.9-7.1
  1. Visão geral
  2. Criando o serviço Web
  3. Codificando e testando o serviço da Web
  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 o aplicativo cliente

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

  4. Codificando a classe principal

Criando o aplicativo cliente

Nesta seção, você cria um aplicativo da Web. Nesse aplicativo, você criará um cliente que consome o serviço da Web criado e modificado em tutoriais anteriores.

Para criar o aplicativo cliente:

  1. Escolha Arquivo > Novo projeto (Ctrl-Shift-N no Linux/Windows, ⌘-Shift-N no MacOS). É exibido o assistente para Novo projeto.
  2. Selecione Aplicativo Java na categoria Java. Clique em Próximo. O assistente Novo aplicativo Java aparece. Digite FlowerClient em Nome do projeto. Selecione uma localização para o projeto e clique em Terminar. O IDE cria um novo projeto de aplicativo Java.
  3. Clique com o botão direito do mouse no nó do projeto FlowerClient e escolha Novo > Cliente de serviço Web no menu de contexto. O assistente para Novo cliente de serviço da Web é aberto.
  4. Selecione o botão de opção URL WSDL e cole o URL do arquivo WSDL nesse campo. (Por padrão, o URL é http://localhost:8080/FlowerAlbumService/FlowerServiceService?wsdl. Encontre o URL no navegador testando o serviço da Web e substituindo ?Tester com ?wsdl no final do URL.) Aceite todos os outros valores padrão, incluindo um nome de pacote em branco.
    Assistente do Cliente de serviços da Web exibindo URL WSDL
  5. Clique em Terminar. O IDE baixa o arquivo WSDL, adiciona stubs de cliente para interagir com o serviço da Web e adiciona nós à janela Projetos no projeto de aplicativo Java.
    Visualizaçao Projetos mostrando o cliente de serviço Web

Projetando o formulário JFrame

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

Se não desejar projetar o formulário JFrame você mesmo, é possível baixar um arquivo Java do JFrame pré-projetado aqui.

  1. Clique com o botão direito do mouse no nó FlowerClient e selecione Novo > Formulário JFrame. Chame o quadro de FlowerFrame. Coloque-o no pacote flowerclient.
  2. FlowerFrame é aberto no editor. Abra a Paleta, se ainda não estiver aberta. Extenda o limite inferior do quadro em aproximadamente um terço.
    Formulário Flor no editor, na visualização de projeto, 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 Visualização do desenho. Selecione Alterar nome da variável... no menu de contexto. Chame o painel de gardenFlowersPanel.
  5. Arraste um JLabel da Paleta para o início do gardenFlowersPanel. Clique com o botão direito do mouse no rótulo 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 visualização do desenho. Aceite o nome da variável padrão do grupo de botões, buttonGroup1.
  7. Arraste quatro Botões de opções em 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 true Aster
    honeysuckleRadioButton false Honeysuckle
    roseRadioButton false Rose
    sunflowerRadioButton false Sunflower
  8. Arraste um Painel de rolagem abaixo 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 visualização Desenho, 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 figura..."
  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 Esperando...
    honeysuckleButton Esperando...
    roseButton Esperando
    sunflowerButton Esperando...

O Formulário JFrame agora está completamente projetado. Nesse ponto, o FlowerFrame deverá ter a seguinte aparência.
Quadro Flower 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 ouvintes. Os ouvintes 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 visualização de Código-fonte do editor. Localize o início do corpo da classe FlowerFrame e o construtor FlowerFrame.
    Visualização de Código-fonte do editor mostrando o construtor FlowerForm vazio
  2. No início do corpo da classe do FlowerFrame, antes do construtor, crie uma matriz de strings dos nomes de todas as flores.
    protected static final String[] FLOWERS = {"aster", "honeysuckle", "rose", "sunflower"};
  3. Entre a matriz da string FLORES e o construtor, adicione uma linha que inicialize um java.util.Map denominado flores. O mapa utiliza uma String e a mapeia para uma Imagem.
    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 Imagem específica com uma String específica para uma instância específica do mapa flores
    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 padrão.
    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á avisos 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á ouvintes personalizados para os botões de opções e os botões de flores. Também é possível escrever um método que determine qual flor será selecionada pelos botões e obterá uma Imagem daquela flor a partir do mapa flores. Finalmente, você escreverá um método que é chamado pela classe Principal e que obterá uma Imagem para cada miniatura.

  1. Encontre o método public static void main(String args[]) no corpo da classe FlowerFrame. Exclua esse método e sua documentação. (O aplicativo utiliza a classe Principal em vez dele.)
  2. No lugar do método principal, escreva um ItemListener personalizado para os botões de opções. Esse ouvinte mostrará uma nova imagem de flor quando um botão de opções 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 ouvinte selecionará o botão de opções 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 qual botão de opções é selecionado e obtém uma Imagem da flor correspondente a partir do mapa flores.
    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 flores. A classe Principal 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, se não foram corrigidas quando foram coladas no código. É possível corrigi-las de uma vez clicando com o botão direito do mouse no editor e escolhendo 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 Principal para que mostre o FlowerFrame, conecte-se ao serviço da Web e chame as operações do serviço da Web.

  1. Abra a classe Main.java no editor.
    Classe principal vazia
  2. No corpo da classe, antes do método principal, inicialize uma variável int para o número de figuras baixadas.
     private static int downloadedPictures;
  3. No corpo do método principal, 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 principal, adicione código para mostrar o FlowerFrame.
    // Mostrar o FlowerFrame.
    final FlowerFrame frame = new FlowerFrame(flowers);
    frame.setVisible(true);  
  6. No corpo do método principal, adicione o código para conectar o cliente ao serviço.
    // O cliente se conecta ao serviço com este código.
    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 principal, adicione o código que cria uma matriz de quatro threads Executáveis e chame a operação getFlower do serviço da Web uma vez em cada thread.
    // O serviço da web da operação getFlower
    // é chamado 4 vezes, cada uma em um thread separado.
    // Quando a operação terminar, a figura é mostrada em
    // um botão específico.
    Runnable[] tasks = new Runnable[4];
    
    for (int i=0; i<4;i++) {
        final int index = i;
        tasks[i] = new Runnable() {
            public void run() {
                try {
                
                    // Chamar a operação getFlower
                    // no serviço da Web:
                    Image img = port.getFlower(FlowerFrame.FLOWERS[index]);
                    System.out.println("picture downloaded: "+FlowerFrame.FLOWERS[index]);
                         
                    // Adicionar strings ao hashmap:
                    flowers.put(FlowerFrame.FLOWERS[index],img);
                            
                    // Chamar a operação showFlower
                    // no 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 serviço da Web em um thread separado.
    // O serviço da Web da operação getThumbnails é chamado
    // em um thread separado, logo depois dos quatro threads concluídos anteriormente.
    // 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, se não foram corrigidas quando foram coladas no código. É possível corrigi-las de uma vez clicando com o botão direito do mouse no editor e escolhendo Corrigir importações no menu de contexto. Você recebe uma escolha de Classes de listagem a importar; 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 principal 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);
        
        // Mostra o FlowerFrame.
        final FlowerFrame frame = new FlowerFrame(flowers);
        frame.setVisible(true);
        
// O cliente se conecta ao serviço com este código. FlowerService_Service service = new FlowerService_Service(); final FlowerService port = service.getFlowerServicePort(); Runnable[] tasks = new Runnable[4]; // O serviço da Web da operação getFlower // é chamado 4 vezes, cada uma em um thread separado. // Quando a operação terminar, a figura é mostrada em // um botão específico. for (int i=0; i<4;i++) { final int index = i; tasks[i] = new Runnable() { public void run() { try { // Chame a operação getFlower // no serviço da web: Image img = port.getFlower(FlowerFrame.FLOWERS[index]); System.out.println("picture downloaded: "+FlowerFrame.FLOWERS[index]); // Adicione strings ao hashmap: flowers.put(FlowerFrame.FLOWERS[index],img); // Chame a operação showFlower // no FlowerFrame: frame.showFlower(); } catch (IOException_Exception ex) { ex.printStackTrace(); } downloadedPictures++; } }; new Thread(tasks[i]).start(); } // O serviço da Web da operação getThumbnails é chamado // em um thread separado, logo depois dos quatros threads anteriores serem concluídos. // Quando as imagens são baixadas, as miniaturas são mostradas // no botão do frame. Runnable thumbsTask = new Runnable() { public void run() { try { while (downloadedPictures < 4) { try {Thread.sleep(100);} catch (InterruptedException ex) {} } // Chame a operação getThumbnails // no serviço da Web: 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(); } }

O aplicativo cliente agora está completo, com o código que interage com o serviço da Web que delega para o módulo EJB a fim de expor suas imagens. Clique com o botão direito do mouse no cliente e escolha Executar. O aplicativo Swing é iniciado e, depois de um tempo, é preenchido com as imagens recebidas do serviço da Web. Se as imagens não aparecerem, limpe e construa o projeto FlowerService e execute-o novamente. Note que é possível alterar a imagem que aparece no quadro principal selecionando um botão de opções ou clicando em uma miniatura.

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