Utilizando Web Services com EJB 3 e JBoss
Apresentando os recursos do EJB3 na criação de Web Services
De que trata o artigo:
O artigo tem o objetivo de apresentar a estrutura de um WebService utilizando os recursos do EJB3 no Servidor de Aplicações JBoss. Faz parte também dos objetivos deste artigo demonstrar o funcionamento do protocolo SOAP e apresentar os conceitos necessários para criação de um Web Service.
Para que serve:
O artigo serve para apresentar e demonstrar a utilização dos recursos do EJB3 para criação de Web Services utilizando o Servidor de Aplicações JBoss.
Em que situação o tema é útil:
O artigo é útil em sistemas em que haja necessidade de trocar informações utilizando a Web como meio de prover a interoperabilidade de sistemas não necessariamente desenvolvidos utilizando a linguagem de programação Java.
O uso de Web Services está se tornando cada vez mais comum tendo em vista uma maior necessidade de criarmos ambientes de software integrados onde várias plataformas diferentes precisam se comunicar.
Esta necessidade de integração acaba resgatando alguns conceitos que teoricamente são oriundos de projeto de software estruturado, tais como acoplamento e coesão. Sistemas isolados que no início atendiam um determinado grupo de usuários passam a ter a responsabilidade de buscar e/ou fornecer informações para outros sistemas, transformando este sistema, até então isolado, como um módulo de outro sistema. Daí os conceitos de acoplamento e coesão.
Os conceitos de acoplamento e coesão acabam voltando à tona de uma forma mais moderna, dando espaço a outros conceitos como SOA (Service Oriented Architeture, ou ainda, Arquitetura Orientada a Serviços), onde estes sistemas isolados numa visão mais retrógrada seriam os módulos, e numa visão mais moderna os Serviços.
O uso de Web Services é a forma mais objetiva de implementar projetos de software utilizando SOA. Web Services são recursos fracamente acoplados responsáveis por encapsular a lógica de negócio e disponibilizá-los de uma forma denominada “sem estado” (Stateless). Estas são algumas das características que projetos de software utilizando SOA devem possuir, por isso os Web services são recursos tão utilizados com projeto envolvendo a metodologia Orientada a Serviços.
A plataforma Java auxilia muito neste processo, oferecendo uma grande gama de ferramentas para proporcionar flexibilidade, portabilidade e escalabilidade no desenvolvimento de software.
Entre estas ferramentas disponíveis pelo Java, o Enterprise Java Bean, ou ainda EJB, são recursos que oferecem ao projeto estas características necessárias para o software que irá participar de um processo de integração. O EJB atualmente na sua versão três traz uma série de recursos, como as anotações, que agilizam o processo de desenvolvimento.
Neste artigo, abordaremos a construção de Web Services utilizando recursos do EJB3. Para isso, foram criados dois estudos de caso para demonstrar o uso das anotações. O primeiro estudo de caso é um exemplo básico de Web Service que disponibiliza o acesso a alguns métodos, onde o principal deles retorna uma String contendo um nome. O segundo estudo de caso é um pouco mais complexo, onde é feito o uso de mais algumas anotações que não foram utilizadas no primeiro estudo de caso, e também é utilizado o banco de dados PostgreSQL, com gerenciamento de acesso às conexões de banco realizadas pelo JBoss através de um DataSource. Além disso, no decorrer deste artigo alguns conceitos importantes serão definidos para o completo entendimento de projetos de software utilizando Web services.
Web Services – Conceitos Básicos
A necessidade de integração de sistemas, muitas vezes, surge com o ganho de complexidade nas regras de negócio, conhecido como Core Business, de empresas motivadas pelo seu crescimento. Os sistemas já implantados podem não mais atenderem aos requisitos da nova estrutura, e para isso os softwares já implantados que implementam as regras de negócio precisam ser remodelados.
Como citado anteriormente, este processo de integração de sistemas acaba resgatando conceitos como acoplamento e coesão, bastante comuns em projeto de software estruturado.
Acoplamento pode ser medido com a seguinte pergunta: Quão dependentes são estes sistemas? Quanto maior for à relação de dependência entre sistemas integrados, podemos dizer que estes são fortemente acoplados. Caso contrário, são ditos fracamente acoplados. O conceito de acoplamento está bastante relacionado ao que se refere à integração entre sistemas.
A coesão é um conceito mais ligado ao próprio software, que também pode ser medido pela pergunta: Quão dependentes entre si são os módulos do sistema? O conceito de coesão está mais ligado a um ponto de vista intrínseco. Diz-se que um software tem baixa coesão quando seus módulos possuem pouca dependência entre si, e alta coesão quando o inverso.
Dentro desta nova visão de arquitetura de software, que transforma softwares em serviços, dando espaço a construção de Software Orientados a Serviço (SOA) surge o conceito de Orquestração.
Orquestrar serviços pode ser definido dentro dos conceitos do SOA como “definir os procedimentos a serem realizados dentro das regras de negócio da Empresa”. A Orquestração deve garantir as pré e pós-condições de cada serviço.
Nesse cenário, é possível definir um Web Service como um software que disponibiliza um ou mais serviços de uma forma fracamente acoplada. Uma das suas principais vantagens é permitir que os clientes que o acessam não necessariamente sejam desenvolvidos na mesma tecnologia em que o Web service foi implementado. Para isso, é altamente recomendado que as informações retornadas por um Web service sejam de tipos primitivos como: String, Int, Float, Double, etc. Apesar de ser recomendado este procedimento na criação de Web services, isto não é uma regra. É possível retornar tipos complexos como objetos.
Esta flexibilidade é possível através da troca de informações entre o Web service e seus clientes utilizando uma linguagem “universal” neste processo de comunicação – a troca de documento XML. Este documento XML disponibilizado do lado do Web Service tem a responsabilidade de oferecer ao cliente os seus dados de uma forma que este entenda e processe as informações recebidas. Este documento é conhecido como WSDL (Web service Description Language). O WSDL recebe este nome pela sua estrutura e forma como foi concebido para ser o padrão de comunicação.
O WSDL é um documento reconhecido pelos padrões W3C. O papel fundamental deste documento é definir os end points do web service criado. Um end point pode ser definido como a interface exposta pelo web service para que as aplicações clientes solicitem as informações necessárias a serem obtidas. A solicitação efetuada ao web service é feita através de uma chamada HTTP. A união do documento WSDL usando como meio de comunicação o protocolo HTTP deu origem ao protocolo SOAP (Simple Object Access Protocol). O SOAP atualmente é um protocolo reconhecido pelo W3C para troca de mensagens em formato XML. O SOAP se encontra atualmente na versão 1.2.
Para tornar viável a comunicação entre o cliente e o web service, houve a necessidade de criar uma API do lado do cliente que facilitasse a troca e processamento de informações pelo protocolo SOAP. Inicialmente esta API era chamada de JAX – RPC (Java API for XML – Remote Procedure Call). Nos dias atuais, esta API evoluiu para o JAX – WS (Java API for XML – Web Service). A evolução desta API também foi um grande facilitador para implementações de softwares clientes de web service, tornando o processo de desenvolvimento mais ágil e prático.
Existem algumas formas do cliente solicitar informações à estrutura de um web service, onde as mais conhecidas são chamadas RPC (Remote Procedure Call) ou o envio de informações através de documentos – forma conhecida como Document Centric. A forma de requisição a ser efetuada aos web services de nossos estudos de casos será as requisições RPCs, que é a mais utilizada atualmente. Uma requisição RPC à estrutura de um web service é uma chamada síncrona, pois a cada requisição feita a um web service é aguardada uma resposta.
A API JAX-WS já implementa funcionalidades para facilitar e agilizar o tratamento do documento WSDL retornado pelo web service. Entre as formas existentes, a utilizada em nossos estudos de casos é o Dynamic Proxy. O Dynamic Proxy utiliza classes criadas dinamicamente para o acesso as informações de um web service. Estas classes dinâmicas são baseadas no conteúdo do documento WSDL gerado, e é responsabilidade da API JAX-WS em criar este “Proxy” do web service para obter as informações desejadas.
Para ficar mais claro, o RPC é a forma pela qual o cliente se comunica com o web service, ou seja, a chamada a estrutura em si. O Dynamic Proxy é a forma pela qual a API JAX-WS obtém e/ou trata as informações retornadas pela chamada RPC, tornando transparente o tratamento das informações contidas no documento WSDL. Imagine se este trabalho fosse responsabilidade do software cliente do web service? Ficaria muito trabalhosa o tratamento das informações.
No decorrer do artigo, esses conceitos serão discutidos através dos códigos-fonte de nossos estudos de caso para ficar mais claro as diferenças.
Conhecendo EJB 3 e JBoss
O Enterprise Java Beans (EJB) é umas das ferramentas que compõem o carro-chefe da tecnologia Java EE. O Java, por sua natureza, prima pela escalabilidade, robustez, portabilidade e manutenibilidade das aplicações desenvolvidas sobre a sua tecnologia. Os objetivos de construir uma aplicação disponibilizando algumas de suas informações em forma de serviço estão diretamente ligados aos da tecnologia Java EE.
A evolução do EJB para versão três levou em consideração esta nova demanda do mundo da Engenharia de Software. Através do documento JSR-181- “Web Services Metadata for the JavaTM Platform”, descrita anteriormente, são definidos alguns objetivos importantes, a saber:
· Definir a sintaxe das anotações Java para desenvolvimento de aplicação Web Services;
· Prover a simplificação do modelo de deployment de aplicações Java Web Services, facilitando e otimizando o processo de desenvolvimento;
· Disponibilizar uma sintaxe que possibilite a manipulação de suas ferramentas;
· Definir um padrão para desenvolvimento e deployment de Web services sem exigir conhecimento da implementação da API e de seus descritores.
As anotações descritas neste documento são:
· @Webservice
· @WebMethod
· @OneWay
· @WebParam
· @WebResult
· @Handler Chain
· @SOAPBinding
As anotações em negrito serão citadas e explicadas nos estudos de casos apresentados mais a frente.
Num passado não tão distante, o processo de criação de web services era bem trabalhoso. Anteriormente, era necessário criar o Deploymet Descriptor (arquivo responsável por definir os procedimentos de Deployment, chamado webservice.xml, que comparado a uma aplicação web é equivalente ao web.xml). Este arquivo era criado utilizando ferramentas disponibilizadas juntamente com o servidor de aplicações. Este mesmo processo também era uma realidade para criação do arquivo WSDL. Atualmente, o processo de criação destes arquivos passou a ser responsabilidade do servidor de aplicações.
Com o lançamento da JSR-181, os web services podem fazer uso da tecnologia Java EE utilizando as ferramentas do EJB3 juntamente com suas anotações definidas na JSR – conceito este fortemente inserido na sua versão 3.
Um web service desenvolvido com EJB3 pode ser disponibilizado no servidor de aplicações como um pacote JAR (disponibilizando apenas o “EJB Web Service” – Web Services que fazem uso das anotações do EJB3 para este fim) ou EAR (disponibilizando todo o pacote da aplicação, inclusive com os EJBs) como qualquer outro componente EJB.
O JBossAS na sua versão 4.2.3 foi o servidor de aplicações escolhido para demonstrar o uso de web services com EJB3. O JBossAS é uma produto completo que oferece todos os recursos para disponibilizar aplicações Java fazendo uso de Web Services com EJB. Dentro do JBossAS é encontrado o JBossWS (JBoss Web Service). Este é responsável pelo deployment e gerenciamento dos web services.
A interface de administração dos web services em produção pode ser acessada através do endereço http://IP_JBOSS:8080/jbossws. O mais importante nesta interface é ter acesso ao link View a list of deployed services. Através deste, é possível acessar informações como: contexto do web service, nome do End Point, End point Address, quantidade de requisições atendidas pelo web service etc. Na Figura 1 é possível visualizar a interface disponível para o contexto.
Figura 1. Contexto JBossWS
Através do End point address é possível visualizar o arquivo WSDL gerado pelo servidor de aplicações no deployment do web service. Na Figura 2 é possível visualizar alguns exemplos de web services já em produção.
Figura 2. Web Services em produção
Com a utilização destes novos recursos, o desenvolvedor pode ficar focado apenas na modelagem e desenvolvimento dos web services, sem precisar se preocupar com a criação de arquivos específicos, como o WSDL. O arquivo WSDL é criado dinamicamente pelo JBoss no ato do deployment do componente. É importante citar que este arquivo é criado uma única vez, e para que este seja modificado é necessário efetuar um novo deployment do pacote do web service.
A seguir, passaremos para o primeiro estudo de caso demonstrando o uso do das anotações e dos recursos de EJB.
Estudo de Caso 1 – Apresentando o uso da anotações da JSR-181
Este estudo de caso visa apresentar as principais anotações na construção de um web service e onde estas devem ser utilizadas no projeto. As anotações definidas neste primeiro estudo de casos são: @Webservice, @WebMethod, @OneWay, @SOAPBinding. Ainda no primeiro estudo de caso é utilizada a anotação @Stateless. Esta anotação não faz parte das anotações descritas na JSR 181, mas é de suma importância para a criação de Web Services.
O exemplo basicamente retorna o nome de uma pessoa qualquer que o web service disponibilizado irá responder a solicitação via protocolo SOAP. Lembrando que o protocolo SOAP utiliza uma chamada HTTP para troca de informações via documento XML.
Para construção deste primeiro estudo de caso, foi utilizada a IDE Eclipse com um “Java Project” comum utilizando JVM 1.5. É necessária a utilização de algumas bibliotecas disponibilizadas pelo JBoss para que durante a construção da aplicação cliente, esta reconheça as anotações necessárias a serem utilizadas para construção do web service. Vide a seção “Dicas importantes” para visualizar as bibliotecas do JBoss a serem utilizadas.
Através da Figura 3 podemos visualizar como o projeto foi estruturado, onde basicamente foi criado uma interface para representar o EndPoint (EndPoint.java) e uma classe que representa o web service em si (WebService1.java).
Figura 3. Estrutura do projeto – Estudo de caso 1
O cliente para acessar a estrutura do web service deve efetuar uma chamada HTTP ao endereço do Endpoint. Para nosso estudo de caso, este endereço é http://claimant:8080/webmobile1/WebService1?wsdl.
A resposta a esta chamada recebida pelo cliente é um documento WSDL criado dinamicamente, onde o cliente através de implementação da API JAX-WS trata o documento recebido como resposta. Internamente no JBoss o pacote webmobile1.jar, que representa o projeto do primeiro estudo de caso, faz a troca de informações entre o EndPoint e o Web Service para processar a requisição. Através da Figura 4 podemos visualizar este cenário.
Figura 4. Comunicação com Web Service
Vejamos na Listagem 1 a estrutura da interface br.claimant.endpoint.EndPoint.java.
Listagem 1. O Endpoint
package br.com.claimant.endpoint;
import java.rmi.Remote;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
@WebService(endpointInterface = "br.com.claimant.endpoint.EndPoint")
public interface EndPoint extends Remote {
@WebMethod(operationName = "getNome")
public String getNome();
@Oneway
@WebMethod(operationName = "ativaNada")
public void ativaNada();
}
Durante a criação da interface descrita na Listagem 1, foi utilizada a anotação @WebService. Com o uso desta anotação é que será possível disponibilizar uma interface Java como web service para ser acessado pela aplicação Cliente. Obrigatoriamente, a interface que representa o Endpoint deve implementar a interface Remote do pacote javax.rmi. Sem esta implementação não será possível acessar o seu conteúdo remotamente. É através da propriedade endpointInterface que o Servidor de Aplicações saberá em qual pacote irá buscar a interface que assume o papel de Endpoint.
Na interface br.com.claimant.endpoint.EndPoint foram declarados dois métodos: getNome() e ativaNada(). Com relação ao método getNome(), foi utilizada apenas a anotação @WebMethod. Esta anotação expõe o método para ser acessível à aplicação cliente do Web Service criado. Por default, todos os métodos de uma interface declarada como Endpoint serão acessíveis pelo web service. Este processo pode ser evitado utilizando a anotação @WebMethod(exclude=true). A anotação @WebMethod ainda faz uso da propriedade operationName, que define o nome do método (ou ainda a operação, do ponto de vista de um web service) que será encontrado no arquivo WSDL que será gerado dinamicamente pelo JBoss no ato do Deployment do “EJB Web Services”.
Já com relação ao método ativaNada(), além da anotação @WebMethod foi utilizada a anotação @Oneway. A anotação @Oneway é utilizada para métodos que apenas enviam uma solicitação ao web service e não aguardam retorno de informações. Perceba que o retorno do método que fazem uso desta anotação é declarado como void.
Para completar a construção de nosso primeiro web service, é necessário criar a classe do web service que irá implementar o Endpoint. A Listagem 2 apresenta seu código.
Listagem 2. O Web Service
package br.com.claimant.webservice;
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.BindingType;
import br.com.claimant.endpoint.*;
@Stateless
@WebService(targetNamespace = "http://claimant:8080/webmobile1",
name = "ENDPOINT",
serviceName = "EndPointService")
@SOAPBinding(style = Style.RPC)
public class WebService1 implements EndPoint {
public String getNome() {
return "Augusto Marinho";
}
public void ativaNada() {
// TODO Auto-generated method stub
}
}
A classe br.com.claimant.webservice.WebService1 obrigatoriamente deve implementar a interface declarada como Endpoint do web service. A classe que representa um web service fazendo uso de EJB3 deve ser um Bean de Sessão sem estado (stateless), lembram do conceito citado anteriormente?
Para indicar esta característica para o servidor de aplicações, é necessário fazer uso da anotação @Stateless. Esta anotação não faz parte da JSR 181, mas é importante para informar ao JBoss que este é um EJB, e deve ser tratado como tal; este deve ser um recurso de software “sem estado” e disponível a todos que queiram utilizar e que possam efetuar uma chamada a sua estrutura via HTTP.
Da mesma forma que a interface que representa o Endpoint utiliza a anotação @WebService, a classe que implementa está interface também faz uso desta com as seguintes diferenças.
· É na classe que deve ser definido o targetNamespace de um Web Service. Este pode ser comparado a um contexto de um Servlet.
· É na classe que deve ser definida a propriedade name e serviceName de um Web Service.
· Se estas recomendações não forem seguidas, com certeza o JBoss não irá efetuar o deployment do web service corretamente (estes passos são muitos importantes).
Na classe que representa o web service, ainda é utilizada a anotação @SOAPBinding. É através desta anotação que a aplicação cliente saberá se comunicar com o web service via protocolo SOAP. Lembrando que o protocolo SOAP nada mais é do que uma chamada HTTP com um retorno em formato XML. Através da Figura 4 é apresentado um esboço da comunicação.
Pronto! Com estes passos já é possível empacotar nosso “EJB Web Service” e efetuar o deployment no JBoss. Para empacotar o web service no formato JAR foi utilizado um script Ant para facilitar nosso trabalho. Como na estrutura computacional em que foi desenvolvido o estudo a máquina onde o JBoss estava em execução era diferente da máquina de desenvolvimento, é possível perceber que na execução do script Ant faz uma requisição SCP à máquina Server do JBoss para efetuar o deployment do pacote. Caso na sua estrutura não haja necessidade de efetuar este procedimento, vide a seção “Dicas importantes” para consultar as modificações. A Listagem 3 apresenta o script de build utilizado para empacotamento e deployment do pacote.
Listagem 3. Arquivo build.xml
Criando as propriedades para empacotamento
-->
perty name="src" value="../src" />
Este script encontra-se dentro do diretório build-ant, como pode ser visto através da Figura 3. Foram criadas quatro propriedades (tag property) que representam a estrutura de diretório do projeto, onde foram definidos os paths do fontes do projeto, caminho para qual será enviado o arquivo após compilado e empacotado (como arquivo jar) e onde será armazenadas as classes após o processo de compilação.
Após definidas as propriedades, o projeto possui três targets a saber: transfere, criajar, compile. Estes targets possuem dependências entre si, por isso que na segunda linha deste arquivo é informado o target default “transfere”, pois é executado de forma decrescente. Perceba que o target transfere possui uma dependência com o target “criajar”, que por sua vez possui uma dependência com o target “compile”.
Como todos estão “amarrados” em sua execução, com exceção do target “compile”, primeiro será executado o target “compile” e após será executados na ordem o target “criajar” e por último o “transfere”, que já irá fazer a chamada SCP à máquina do JBoss no diretório em que deve ser disponibilizado o pacote para efetuar o Hot Deployment (o JBoss por natureza efetuar o deployment automaticamente de qualquer pacote disponibilizado no diretório %JBOSS_HOME%/Server/default/deploy).
A Listagem 4 apresenta um pequeno trecho do arquivo Server.log contendo informações no ato do Deployment do pacote webmobile1.
Listagem 4. Trecho do server.log
23:29:48,136 INFO [EJBContainer] STOPPED EJB: br.com.claimant.webservice.WebService1 ejbName: WebService1
23:29:48,138 WARN [JmxKernelAbstraction] jboss.j2ee:jar=webmobile1.jar,name=WebService1,service=EJB3 is not registered
23:29:48,141 INFO [TomcatDeployer] undeploy, ctxPath=/webmobile1, warUrl=.../tmp/deploy/webmobile1.jar2199891621736841012.war/
23:29:48,173 INFO [DefaultEndpointRegistry] remove: jboss.ws:context=webmobile1,endpoint=WebService1
23:29:48,263 INFO [JmxKernelAbstraction] creating wrapper delegate for: org.jboss.ejb3.stateless.StatelessContainer
23:29:48,264 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=webmobile1.jar,name=WebService1,service=EJB3 with dependencies:
23:29:48,317 INFO [EJBContainer] STARTED EJB: br.com.claimant.webservice.WebService1 ejbName: WebService1
23:29:48,382 INFO [EJB3Deployer] Deployed: file:/usr/local/programas/jboss/server/default/deploy/webmobile1.jar
23:29:48,385 INFO [DefaultEndpointRegistry] register: jboss.ws:context=webmobile1,endpoint=WebService1
23:29:48,786 INFO [WSDLFilePublisher] WSDL published to: file:/usr/local/programas/jboss/server/default/data/wsdl/webmobile1.jar/EndPointService4990958546927506202.wsdl
23:29:48,868 INFO [TomcatDeployer] deploy, ctxPath=/webmobile1, warUrl=.../tmp/deploy/webmobile1.jar4346819442342762836.war/
Perceba que nas linhas em negrito é apresentada a criação do arquivo WSDL dinamicamente pelo JBoss. É importante lembrar que este arquivo é criado apenas uma única vez. Para o arquivo WSDL ser modificado, deverá ser feito um novo deployment do pacote.
Para finalizar este primeiro estudo de classes, será apresentado um pequeno exemplo de aplicação cliente standalone para demonstrar o funcionamento. Vide na Listagem 5 o código-fonte.
Listagem 5. Consumindo o Web Service
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import br.com.claimant.endpoint.*;
public class Principal {
/**
* @param args
* @throws MalformedURLException
* @throws Exception
*/
public static void main(String[] args) throws MalformedURLException, Exception {
System.out.println("... CONECTANDO AO WEBSERVICE ...");
URL url = new URL("http://claimant:8080/webmobile1/WebService1?wsdl");
QName qname = new QName("http://claimant:8080/webmobile1","EndPointService");
System.out.println("Criando um serviço com " + url + "-" + qname);
ServiceFactory factory = ServiceFactory.newInstance();
Service remote = factory.createService(url,qname);
EndPoint proxy = (EndPoint) remote.getPort(br.com.claimant.endpoint.EndPoint.class);
System.out.println("Retorno WebServices: " + proxy.getNome());
}
}
Através desta pequena aplicação cliente é possível invocar métodos de web services e possuir acesso às informações retornadas via protocolo SOAP. Para esclarecermos seu funcionamento, os seguintes comentários são importantes.
O objeto URL instanciado deve fazer sempre referência ao path completo do arquivo WDSL a ser invocado. O objeto QName instanciado representa um nome qualificado para especificação XML definida. Um objeto da classe QName contém informações referentes ao NameSpaceURI, partes locais e prefixos de um documento XML. Para este caso em específico, faz referência ao contexto do web service e o nome de serviço a ser invocado (Service name).
Além disso, o objeto service instanciado da classe javax.xml.rpc.Service representa o serviço que será invocado do web service. Quando é apresentado no código da Listagem 5 o trecho remote.getPort(br.com.claimant.endpoint.EndPoint.class) está sendo realizado uma chamada RPC para que seja retornada uma instância do Endpoint do web service (qualquer semelhança com um cliente de EJB não é mera coincidência). A chamada RPC fica caracterizada no trecho de código a seguir:
Service remote = factory.createService(url,qname);
Perceba que é necessário passar como parâmetro a instância dos objetos URL e QName, que basicamente representam respectivamente o endereço do arquivo WSDL e o serviço a ser acessado. E neste trecho de código que podemos caracterizar o uso do Dynamic Proxy, pois uma instância do web service é obtida dinamicamente, ou ainda, em tempo de execução. Após termos obtido uma cópia da instância do Endpoint, o Proxy, já é possível invocar os métodos do web service. Perceba que no trecho de código remote.getPort(br.com.claimant.endpoint.EndPoint.class); é feita uma chamada à interface que representa o EndPoint. O método getPort() do objeto remote (que representa uma instância da classe Service do pacote javax.xml.rpc.Service) retorna um Object, por isso é necessário efetuar o Type Casting do Retorna para um objeto da interface Endpoint do pacote br.com.claimant.endpoint.EndPoint. Na última linha de código do nosso exemplo de aplicação cliente já é possível efetuar uma chamada a estrutura do web service através do Proxy obtido, conforme trecho abaixo:
System.out.println("Retorno WebServices: " + proxy.getNome());
A chamada ao método getNome() do Web Service é apresentada na Figura 5.
Figura 5. Resultado da chamada ao método getNome
Através da Figura 5 foi possível visualizar o resultado retornado pelo web service através de uma chamada feita ao método getNome(). Como neste nosso primeiro exemplo foi definido no método getNome um retorno fixo com o nome “Augusto Marinho”, toda e qualquer chamada a esta estrutura retornará o mesmo resultado.
No Estudo de Caso 2 será apresentado mais dinamismo no funcionamento do web service, aproveitando para apresentar os recursos oferecidos pelo JBoss a uma aplicação Java EE. Para este segundo exemplo, será utilizado o PostgreSQL.
Estudo de Caso 2 – Autenticando a requisição
O nosso segundo estudo de caso visa implementar alguns critérios de segurança na construção de web services.
Como citado anteriormente, um web service implementado com recursos do EJB3 é um Bean de Sessão sem estado. Mediante esta característica, qualquer um que conheça a construção de uma aplicação cliente poderá ter acesso às informações de negócio disponibilizadas por um web service sem procedimentos de autenticação. É evidente que este acesso poderá ser impedido pela estrutura de redes e outras soluções, mas em teoria, qualquer pessoa poderia desenvolver um software cliente para ter acesso a um web service exposto.
Além desta requisição não ser autêntica, ainda cabe a questão: como identificar o cliente e manter o “estado” desta conexão? Esta pergunta é cabível já que os web services utilizando Bean de Sessão sem estado são invocados por seus clientes através de uma requisição HTTP.
O protocolo HTTP por natureza é orientado a conexão e não mantém informações do solicitante após a resposta enviada. Ainda existe outra característica inibidora de persistência de informações do solicitante, já que a classe que representa o web service utiliza a anotação @Stateless, onde caracteriza uma ação “sem estado” ao Bean de Sessão. O servidor de aplicações após criar uma instância deste EJB e devolver a resposta solicitada, já não mantém mais qualquer informação com relação à ação executada, por isso o nome “sem estado”.
A solução para este cenário é criar um mecanismo que permita autenticar a requisição do cliente e manter o “estado” desta conexão por um intervalo de tempo para que o cliente não precise se autenticar a cada requisição, tendo em vista que num ambiente de produção real este processo poderia causar sérios impactos de desempenho no ambiente.
Para viabilizar esta estratégia, continuaremos utilizando os web services como Beans de Sessão sem estado (Stateless), e passaremos a fazer uso do SessionID criado pelo web service no JBoss. O SessionID será criado e manipulado por uma instância da classe HttpSession, muito utilizada com Servlets e páginas JSPs para manter o “estado” da conexão HTTP.
Através destes recursos apresentados, o segundo estudo de caso cria um web service autenticado, onde a aplicação cliente somente terá que se autenticar uma única vez para efetuar chamadas ao métodos de um web service, até que está sessão seja encerrada pelo cliente. Para viabilizar esta arquitetura, o padrão de projeto web service broker (Figura 6) é bastante indicado para o modelo do serviço a ser disponibilizados pelos “EJBs Web Services”.
Figura 6. Padrão de Projeto Web Service broker
Na Figura 6 onde é definido um EndPointProcessor não necessariamente devemos fazer uso de um servlet para efetuar uma chamada ao web service. Na verdade, o bloco que
...