Neste artigo apresento o Marcos de Melo Siega, que pode ser contatado pelo e-mail marcosmsiega@gmail.com. O Marcos foi meu aluno em algumas disciplinas de sua graduação e está concluindo o último período do curso de Tecnologia em Análise e Desenvolvimento de Sistemas da UTFPR campus Medianeira neste primeiro semestre de 2013. Trabalhou recentemente no setor de desenvolvimento de sistemas da empresa Itaipu Binacional. |
1. Introdução
Um Web Service (Serviço Web) é um sistema de software projetado para suportar interação máquina-a-máquina interoperáveis sobre uma rede. Ele tem uma interface descrita em um formato processável por máquina (especificamente WSDL). Outros sistemas interagem com o Web Service de uma maneira prescrita por sua descrição usando mensagens SOAP, normalmente transmitidas por meio do protocolo HTTP com uma serialização XML e em conjunto com outros padrões relacionados à Web [W3C2004].
Este artigo apresenta detalhes da implementação de um Web Service utilizando a plataforma JEE6, o uso da API SAX para realizar a interpretação do descritor do serviço criado e a implementação de duas diferentes aplicações que farão o consumo do serviço criado, uma aplicação em C# e outra utilizando a tecnologia Java.
2. Implementação
Esta seção apresenta as etapas sugeridas para a criação de um Web Service sobre a plataforma JEE6, bem como a descrição dos recursos utilizados no processo de desenvolvimento.
2.1. Requisitos
A seguir estão listados os recursos necessários para a composição do ambiente de desenvolvimento:
- Java SE Development Kit (JDK) Versão 1.6 ou Recente
- GlassFish Server 3.1.2
- NetBeans IDE 7.2.1;
- SAX
- Visual Studio 2012.
2.2. Implementação
Com o ambiente de desenvolvimento instalado e corretamente configurado será dado início ao processo de implementação do Web Service.
2.2.1 Criação do Projeto
Para começar, criou-se um Novo Projeto no IDE NetBeans, e optou-se pelo tipo Aplicação Enterprise, como demostrado na Figura 1.
Figura 1: Janela do wizard para criação de um Novo Projeto na IDE NetBeans
Em seguida, faz-se necessária a especificação do nome e da localização do projeto, conforme Figura 2.
Figura 2: Janela do wizard para definição do nome e da localização do projeto criado
Para finalizar, é necessário realizar configurações de características importantes do Novo Projeto. Definiu-se qual servidor de aplicação hospedará o projeto, a versão da plataforma Java utilizada, a ativação da injeção de contextos e dependências, o nível do código-fonte para adaptar-se ao JEE 6 e optou-se pela criação automática de um módulo EJB, conforme Figura 3.
Figura 3: Janela do wizard para definição das configurações finais do Novo Projeto
2.2.2. Implementação do Web Service
Tendo criado o projeto, inicia-se a implementação do Serviço Web. Para começar, um novo Bean de Sessão (EJB) deve ser gerado dentro do módulo criado automaticamente na definição o Novo Projeto, conforme Figura 4, e este servirá de base para geração automática do Serviço Web.
Um nome para o novo EJB deve ser dado, a localização do Bean deve ser definida, e deve ser marcado como sendo Stateless, ou seja, destina-se a executar automaticamente operações individuais, não mantendo o seu estado para cada invocação de um método.
Figura 4: Janela do wizard para configuração do Novo EJB
Tendo gerado o EJB, faz-se a implementação de um método nele, de acordo com a Listagem 1, que estará disponível no serviço gerado posteriormente.
Listagem 1: Implementação do EJB que servirá de base para a geração do Web Service
package EJBs;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
//EJB que não preserva estado para cada invocação de método.
@Stateless
//EJB estará disponível somente no contexto do servidor de aplicação
@LocalBean
public class Operacoes{
//Método que realiza a soma de dois valores reais
public float soma(float numero, float outroNumero){
return numero+outroNumero;
};
}
Este EJB servirá de base para a geração automática do Web Service. Para tal, devem-se realizar os procedimentos apresentados nas Figuras 5 e 6.
Nesta etapa seleciona-se o tipo do arquivo criado. Na categoria Web Services encontra-se o tipo que deve ser criado, neste caso o tipo desejado é Web Service.
Figura 5: Janela do wizard para criação de Novo Web Service
Figura 6: Janela do wizard para configuração do Novo Web Service
Na etapa apresentada pela Figura 6, deve ser especificado um nome para o serviço Web, sua localização no projeto e a criação do Web Service a partir de um Bean de sessão existente. O Bean existente pode ser encontrado por meio da opção “Procurar”, disponível na janela do wizard.
Após realizar estas configurações, basta selecionar a opção de finalizar. O resultado desta etapa é o serviço apresentado na Listagem 2.
Listagem 2: Web Service gerado automaticamente utilizando o EJB criado
package servicos
import EJBs.operacoes;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
//Anotação de definição de um serviço, bem como sua nomeação.
@WebService(serviceName = “ServicoOperacoes”)
//Anotação que define que o EJB não preserva estado para cada invocação de método.
@Stateless
public class ServicoOperacoes{
//Injeção do EJB que possui o método que se deseja acessar.
@EJB
private Operacoes ejbRef;
//@WebMethod – Serve para informar o nome do método ao gerador do WSDL.
//@WebParam – Serve para informar o nome do parâmetro ao gerador do WSDL.
@WebMethod(operationName = “soma”)
public float soma(@WebParam(name =”numero”) float numero, @WebParam(name = “outroNumero”) float outroNumero){
return ejbRef.soma(numero, outroNumero);
}
}
Concluída a implementação do Web Service, resta apenas realizar sua implantação no servidor de aplicação GlassFish.
A Figura 7 apresenta o resultado da bem sucedida implantação do Web Service no servidor de aplicação.
Figura 7: Resultado da implantação do Web Service no servidor de aplicação Glassfish
Neste momento o serviço está disponível para consumo, e para tal, este artigo demonstra, nas seções seguintes, a implementação de dois clientes, um deles utilizando a tecnologia Java e outro C#.
Além dos clientes, utilizou-se a biblioteca SAX de processamento de XML para interpretar o descritor do serviço recém-criado.
3. Uso da API SAX (Simple API for XML)
SAX é uma API simples para manipulação de arquivos XML disponível para a plataforma Java. SAX foi a primeira API amplamente adotada para XML em Java, por este motivo é considerada padrão. Sua versão atual é SAX 2.0.1, e há versões para diversos ambientes de programação diferentes do Java. [Megginson 1998].
Esta seção apresenta um programa Java que ilustra a utilização prática da API SAX. O programa realiza o processamento do documento XML com informações sobre a descrição do serviço criado na seção anterior, representado pela Figura 8.
O XML contendo a descrição completa do serviço estará disponível no endereço fornecido pelo servidor de aplicação no momento em que a implantação ocorre. No exemplo trabalhado o descritor estará disponível através do seguinte endereço:
http://localhost:8080/ServicoOperacoes/ServicoOperacoes?wsdl
Figura 8: Estrutura do XML descritor do serviço implementado neste artigo
O programa Java é apresentado na Listagem 3. A classe MyParser processa o documento XML com o uso da API SAX, recuperando informações sobre as operações disponíveis. A explicação sobre o funcionamento do programa é apresentada no interior do código, em forma de comentário.
Listagem 3: Implementação do Parser Java utilizando a API SAX
package parser;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyParser extends DefaultHandler{
static Map<String, String> operacoes = new HashMap<String, String>();
private String tagAtual;
private String siglaAtual;
//Método que fará o parsing do arquivo utilizado no argumento do método
public void parsing(String pathDoArquivo){
//Criação de uma instância da classe javax.xml.parsers.SAXParser, através da fábrica (factory) SAXParserFactory
SAXParserFactory fabrica = SAXParserFactory.newInstance();
SAXParser parserSax;
try{
parserSax = fabrica.newSAXParser();
//O “this” passado como argumento do método seguinte indica que a própria classe atuará como gerenciadora de eventos SAX
parserSax.parse(pathDoArquivo, this);
//Tratamento de exceções
}catch(ParserConfigurationException | SAXException | IOException e){
StringBuffer msg = new StringBuffer();
msg.append(“Erro:\n”);
msg.append(e.getMessage()+”\n”);
msg.append(e.toString());
System.out.println(msg);
}
}
//Método startDocument do SAX. Disparado antes do processamento da primeira linha do arquivo XML.
public void startDocument(){
System.out.println(“Iniciando o parsing...”);
}
//Método disparado após o processamento da última linha do arquivo XML
public void endDocument(){
System.out.println(“Encerrando o parsing...”);
}
//Método invocado quando o processador SAX identifica a abertura de uma Tag
public void startElement(String uri, String localName,String qName, Attributes atts){
//Recupera o nome da Tag atual
tagAtual = qName;
//Adiciona ao mapa caso encontre a Tag “<operation>”
if(qName.compareTo(“operation”) == 0){
siglaAtual = atts.getValue(0);
operacoes.put(siglaAtual,”operation”);
}
}
//Método disparado quando encontrado o fechamento de uma Tag
public void endElement(String uri, String localName, String qName) throws SAXException{
tagAtual = “ ”;
}
public static void main(String[] args) throws Exception{
if(args.length != 1){
System.err.println(“Erro! Exemplo de utilização ‘MyParser nome_do_XML’);
System.exit(1);
}
MyParser meuParser = new MyParser();
meuParser.parsing(args[0]);
for(Entry<String,String> entrada : operacoes.entrySet()){
System.out.println(“Operação = ”+entrada.getKey() );
}
}
}
A classe MyParser processa o documento XML com o uso da API SAX, recuperando as informações sobre as operações disponíveis no serviço Web e as exibe na tela.
MyParser é uma subclasse de org.xml.sax.helpers.DefaultHandler, que faz com que ela ganhe automaticamente um processador SAX com o comportamento padrão.
4. Aplicações Clientes
Visto a criação do Web Service, as próximas seções apresentam a implementação de duas aplicações clientes que consumirão as operações oferecidas.
4.1 Java
Cria-se nesta seção uma aplicação Java que fará o consumo do Web Service desenvolvido. Os passos para a criação deste aplicativo podem ser vistos nas Figuras 9 e 10.
Figura 9: Janela do wizard para escolha do tipo da aplicação cliente
Figura 10: Janela do wizard para configurações do cliente Java
Tendo criado o projeto, dá-se início ao desenvolvimento da classe que consumirá o serviço. A geração dos componentes do projeto cliente, gerados a partir do serviço, e a estrutura da classe consumidora podem ser vistos na Figura 11 e na Listagem 4.
Figura 11: Janela do wizard para geração dos componentes do projeto cliente
A Listagem 4 demonstra um exemplo de implementação que faz uso da operação de Soma disponível no serviço criado.
Listagem 4: Implementação da classe Java consumidora do serviço
package Application;
import AppClient.ServicoOperacoes;
import AppClient.ServicoOperacoes_Service;
public class Cliente {
public static void main(String[] args){
ServicoOperacoes_Service service = new ServicoOperacoes_Service();
ServicoOperacoes port = servisse.getServicoOperacoesPort();
System.out.println(“Soma: ”+port.soma(12,13));
}
}
A Figura 12 apresenta o resultado obtido após a execução da classe Java implementada, disponível na Listagem 4.
Figura 12: Resultado obtido através da execução da classe Java implementada
4.2 C#
Esta seção apresenta uma aplicação C# que fará o consumo do Web Service desenvolvido. Os passos para a criação deste aplicativo podem ser vistos nas Figuras 13, 14 e 15.
Figura 13: Janela do wizard para criação do Novo Projeto C#
No passo apresentado na Figura 13, criou-se um novo projeto do tipo Console Application, que servirá para a criação da classe que fará o consumo do Web Service.
Após a criação do projeto, deve ser adicionada a ele uma referência para o Web Service, como pode ser observado nas Figuras 14 e 15.
Figura 14: Adição de referência para o Web Service no projeto consumidor do serviço
Figura 15: Janela do wizard para adição de referência para o Web Service
Após concluir a criação do projeto e a adição da referência para o Web Service, se inicia a implementação da classe que utilizará o serviço. A programação desta classe pode ser vista na Listagem 5.
Listagem 5: Implementação da classe em C# que fará o consumo do serviço
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClienteWebService{
class Program
{
Static void Main(String[] args)
{
Servico.ServicoOperacoesClient service = new Servico.ServicoOperacoesClient();
Console.WriteLine(“Soma: ”+service.soma(14,15));
Console.ReadKey();
}
}
}
5. Considerações Finais
Este artigo apresentou exemplos de implementação de Web Services utilizando a Plataforma JEE, bem como a aplicação prática da API SAX na interpretação de XML, neste caso, bastante adequada, pois os arquivos descritores de serviços geralmente possuem tamanhos consideráveis.
Além deste How-to (Como fazer), este estudo buscou fornecer uma “receita de bolo'' para a criação de aplicações consumidoras de serviços Web em diferentes linguagens, o que demonstra o poder da tecnologia estudada na interação de diferentes sistemas.